5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2001 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
22 #include "serverincludes.h"
23 #include "server_internal.h"
25 static int silc_server_is_registered(SilcServer server,
26 SilcSocketConnection sock,
27 SilcServerCommandContext cmd,
30 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
32 SilcCommandStatus status);
34 silc_server_command_send_status_data(SilcServerCommandContext cmd,
36 SilcCommandStatus status,
38 const unsigned char *arg,
41 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
42 SilcServerCommandReplyContext cmdr,
44 SILC_TASK_CALLBACK(silc_server_command_process_timeout);
46 /* Server command list. */
47 SilcServerCommand silc_command_list[] =
49 SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
50 SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
51 SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
52 SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
53 SILC_SERVER_CMD(list, LIST, SILC_CF_LAG_STRICT | SILC_CF_REG),
54 SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
55 SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
56 SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
57 SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG_STRICT | SILC_CF_REG | SILC_CF_OPER),
58 SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
59 SILC_SERVER_CMD(connect, CONNECT,
60 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
61 SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
62 SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
63 SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG_STRICT | SILC_CF_REG),
64 SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
65 SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
66 SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG_STRICT | SILC_CF_REG),
67 SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
68 SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
69 SILC_SERVER_CMD(ban, BAN, SILC_CF_LAG_STRICT | SILC_CF_REG),
70 SILC_SERVER_CMD(close, CLOSE,
71 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
72 SILC_SERVER_CMD(shutdown, SHUTDOWN, SILC_CF_LAG | SILC_CF_REG |
74 SILC_SERVER_CMD(silcoper, SILCOPER,
75 SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
76 SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
77 SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
78 SILC_SERVER_CMD(getkey, GETKEY, SILC_CF_LAG | SILC_CF_REG),
83 /* Performs several checks to the command. It first checks whether this
84 command was called as pending command callback. If it was then it checks
85 whether error occurred in the command reply where the pending command
88 It also checks that the requested command includes correct amount
90 #define SILC_SERVER_COMMAND_CHECK(command, context, min, max) \
94 SILC_LOG_DEBUG(("Start")); \
96 if (silc_server_command_pending_error_check(cmd, context2, command)) { \
97 silc_server_command_free(cmd); \
101 _argc = silc_argument_get_arg_num(cmd->args); \
103 silc_server_command_send_status_reply(cmd, command, \
104 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
105 silc_server_command_free(cmd); \
109 silc_server_command_send_status_reply(cmd, command, \
110 SILC_STATUS_ERR_TOO_MANY_PARAMS); \
111 silc_server_command_free(cmd); \
116 /* Returns TRUE if the connection is registered. Unregistered connections
117 usually cannot send commands hence the check. */
119 static int silc_server_is_registered(SilcServer server,
120 SilcSocketConnection sock,
121 SilcServerCommandContext cmd,
124 SilcIDListData idata = (SilcIDListData)sock->user_data;
129 if (idata->status & SILC_IDLIST_STATUS_REGISTERED)
132 silc_server_command_send_status_reply(cmd, command,
133 SILC_STATUS_ERR_NOT_REGISTERED);
134 silc_server_command_free(cmd);
138 /* Internal context to hold data when executed command with timeout. */
140 SilcServerCommandContext ctx;
141 SilcServerCommand *cmd;
142 } *SilcServerCommandTimeout;
144 /* Timeout callback to process commands with timeout for client. Client's
145 commands are always executed with timeout. */
147 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
149 SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
150 SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data;
152 /* Update access time */
153 client->last_command = time(NULL);
155 if (!(timeout->cmd->flags & SILC_CF_REG))
156 timeout->cmd->cb(timeout->ctx, NULL);
157 else if (silc_server_is_registered(timeout->ctx->server,
161 timeout->cmd->cb(timeout->ctx, NULL);
166 /* Processes received command packet. */
168 void silc_server_command_process(SilcServer server,
169 SilcSocketConnection sock,
170 SilcPacketContext *packet)
172 SilcServerCommandContext ctx;
173 SilcServerCommand *cmd;
176 /* Allocate command context. This must be free'd by the
177 command routine receiving it. */
178 ctx = silc_server_command_alloc();
179 ctx->server = server;
180 ctx->sock = silc_socket_dup(sock);
181 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
183 /* Parse the command payload in the packet */
184 ctx->payload = silc_command_payload_parse(packet->buffer->data,
185 packet->buffer->len);
187 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
188 silc_buffer_free(packet->buffer);
189 silc_packet_context_free(packet);
190 silc_socket_free(ctx->sock);
194 ctx->args = silc_command_get_args(ctx->payload);
196 /* Get the command */
197 command = silc_command_get(ctx->payload);
198 for (cmd = silc_command_list; cmd->cb; cmd++)
199 if (cmd->cmd == command)
203 silc_server_command_send_status_reply(ctx, command,
204 SILC_STATUS_ERR_UNKNOWN_COMMAND);
205 silc_server_command_free(ctx);
209 /* Execute client's commands always with timeout. Normally they are
210 executed with zero (0) timeout but if client is sending command more
211 frequently than once in 2 seconds, then the timeout may be 0 to 2
213 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
214 SilcClientEntry client = (SilcClientEntry)sock->user_data;
215 SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
221 if (client->last_command && (time(NULL) - client->last_command) < 2) {
222 client->fast_command++;
225 client->fast_command = ((client->fast_command - 1) <= 0 ? 0 :
226 client->fast_command--);
230 if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
231 (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
232 silc_schedule_task_add(server->schedule, sock->sock,
233 silc_server_command_process_timeout,
235 2 - (time(NULL) - client->last_command), 0,
237 SILC_TASK_PRI_NORMAL);
239 silc_schedule_task_add(server->schedule, sock->sock,
240 silc_server_command_process_timeout,
244 SILC_TASK_PRI_NORMAL);
248 /* Execute for server */
250 if (!(cmd->flags & SILC_CF_REG))
252 else if (silc_server_is_registered(server, sock, ctx, cmd->cmd))
256 /* Allocate Command Context */
258 SilcServerCommandContext silc_server_command_alloc()
260 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
265 /* Free's the command context allocated before executing the command */
267 void silc_server_command_free(SilcServerCommandContext ctx)
270 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
272 if (ctx->users < 1) {
274 silc_command_payload_free(ctx->payload);
276 silc_packet_context_free(ctx->packet);
278 silc_socket_free(ctx->sock); /* Decrease reference counter */
283 /* Duplicate Command Context by adding reference counter. The context won't
284 be free'd untill it hits zero. */
286 SilcServerCommandContext
287 silc_server_command_dup(SilcServerCommandContext ctx)
290 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
295 /* Add new pending command to be executed when reply to a command has been
296 received. The `reply_cmd' is the command that will call the `callback'
297 with `context' when reply has been received. It can be SILC_COMMAND_NONE
298 to match any command with the `ident'. If `ident' is non-zero
299 the `callback' will be executed when received reply with command
300 identifier `ident'. If there already exists pending command for the
301 specified command, ident, callback and context this function has no
304 bool silc_server_command_pending(SilcServer server,
305 SilcCommand reply_cmd,
307 SilcServerPendingDestructor destructor,
308 SilcCommandCb callback,
311 SilcServerCommandPending *reply;
313 /* Check whether identical pending already exists for same command,
314 ident, callback and callback context. If it does then it would be
315 error to register it again. */
316 silc_dlist_start(server->pending_commands);
317 while ((reply = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
318 if (reply->reply_cmd == reply_cmd && reply->ident == ident &&
319 reply->callback == callback && reply->context == context)
323 reply = silc_calloc(1, sizeof(*reply));
324 reply->reply_cmd = reply_cmd;
325 reply->ident = ident;
326 reply->context = context;
327 reply->callback = callback;
328 reply->destructor = destructor;
329 silc_dlist_add(server->pending_commands, reply);
334 /* Deletes pending command by reply command type. */
336 void silc_server_command_pending_del(SilcServer server,
337 SilcCommand reply_cmd,
340 SilcServerCommandPending *r;
342 silc_dlist_start(server->pending_commands);
343 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
344 if (r->reply_cmd == reply_cmd && r->ident == ident) {
345 silc_dlist_del(server->pending_commands, r);
351 /* Checks for pending commands and marks callbacks to be called from
352 the command reply function. Returns TRUE if there were pending command. */
354 SilcServerCommandPendingCallbacks
355 silc_server_command_pending_check(SilcServer server,
356 SilcServerCommandReplyContext ctx,
359 uint32 *callbacks_count)
361 SilcServerCommandPending *r;
362 SilcServerCommandPendingCallbacks callbacks = NULL;
365 silc_dlist_start(server->pending_commands);
366 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
367 if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE)
368 && r->ident == ident) {
369 callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
370 callbacks[i].context = r->context;
371 callbacks[i].callback = r->callback;
372 callbacks[i].destructor = r->destructor;
378 *callbacks_count = i;
382 /* Destructor function for pending callbacks. This is called when using
383 pending commands to free the context given for the pending command. */
385 static void silc_server_command_destructor(void *context)
387 silc_server_command_free((SilcServerCommandContext)context);
390 /* Sends simple status message as command reply packet */
393 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
395 SilcCommandStatus status)
399 SILC_LOG_DEBUG(("Sending command status %d", status));
402 silc_command_reply_payload_encode_va(command, status,
403 silc_command_get_ident(cmd->payload),
405 silc_server_packet_send(cmd->server, cmd->sock,
406 SILC_PACKET_COMMAND_REPLY, 0,
407 buffer->data, buffer->len, FALSE);
408 silc_buffer_free(buffer);
411 /* Sends command status reply with one extra argument. The argument
412 type must be sent as argument. */
415 silc_server_command_send_status_data(SilcServerCommandContext cmd,
417 SilcCommandStatus status,
419 const unsigned char *arg,
424 SILC_LOG_DEBUG(("Sending command status %d", status));
427 silc_command_reply_payload_encode_va(command, status,
428 silc_command_get_ident(cmd->payload),
429 1, arg_type, arg, arg_len);
430 silc_server_packet_send(cmd->server, cmd->sock,
431 SILC_PACKET_COMMAND_REPLY, 0,
432 buffer->data, buffer->len, FALSE);
433 silc_buffer_free(buffer);
436 /* This function can be called to check whether in the command reply
437 an error occurred. This function has no effect if this is called
438 when the command function was not called as pending command callback.
439 This returns TRUE if error had occurred. */
442 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
443 SilcServerCommandReplyContext cmdr,
446 SilcCommandStatus status;
448 if (!cmd->pending || !cmdr)
451 SILC_GET16_MSB(status, silc_argument_get_arg_type(cmdr->args, 1, NULL));
452 if (status != SILC_STATUS_OK &&
453 status != SILC_STATUS_LIST_START &&
454 status != SILC_STATUS_LIST_ITEM &&
455 status != SILC_STATUS_LIST_END) {
458 /* Send the same command reply payload */
459 silc_command_set_ident(cmdr->payload,
460 silc_command_get_ident(cmd->payload));
461 buffer = silc_command_payload_encode_payload(cmdr->payload);
462 silc_server_packet_send(cmd->server, cmd->sock,
463 SILC_PACKET_COMMAND_REPLY, 0,
464 buffer->data, buffer->len, FALSE);
465 silc_buffer_free(buffer);
472 /******************************************************************************
476 ******************************************************************************/
479 silc_server_command_whois_parse(SilcServerCommandContext cmd,
480 SilcClientID ***client_id,
481 uint32 *client_id_count,
489 uint32 argc = silc_argument_get_arg_num(cmd->args);
492 /* If client ID is in the command it must be used instead of nickname */
493 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
495 /* No ID, get the nickname@server string and parse it. */
496 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
498 silc_parse_userfqdn(tmp, nickname, server_name);
500 silc_server_command_send_status_reply(cmd, command,
501 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
505 /* Command includes ID, we must use that. Also check whether the command
506 has more than one ID set - take them all. */
508 *client_id = silc_calloc(1, sizeof(**client_id));
509 (*client_id)[0] = silc_id_payload_parse_id(tmp, len);
510 if ((*client_id)[0] == NULL) {
511 silc_free(*client_id);
514 *client_id_count = 1;
516 /* Take all ID's from the command packet */
518 for (k = 1, i = 1; i < argc; i++) {
519 tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
521 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
522 (*client_id_count + 1));
523 (*client_id)[k] = silc_id_payload_parse_id(tmp, len);
524 if ((*client_id)[k] == NULL) {
525 /* Cleanup all and fail */
526 for (i = 0; i < *client_id_count; i++)
527 silc_free((*client_id)[i]);
528 silc_free(*client_id);
531 (*client_id_count)++;
538 /* Get the max count of reply messages allowed */
539 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
548 /* Resolve context used by both WHOIS and IDENTIFY commands */
550 SilcServerEntry router;
552 unsigned char **res_argv;
553 uint32 *res_argv_lens;
554 uint32 *res_argv_types;
556 } *SilcServerResolveContext;
559 silc_server_command_whois_check(SilcServerCommandContext cmd,
560 SilcClientEntry *clients,
561 uint32 clients_count)
563 SilcServer server = cmd->server;
564 SilcClientEntry entry;
565 SilcServerResolveContext resolve = NULL, r = NULL;
566 uint32 resolve_count = 0;
570 for (i = 0; i < clients_count; i++) {
575 if ((entry->nickname && entry->username && entry->userinfo) ||
576 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
580 /* If we are normal server, and we've not resolved this client from
581 router and it is global client, we'll check whether it is on some
582 channel. If not then we cannot be sure about its validity, and
583 we'll resolve it from router. */
584 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
585 entry->connection || silc_hash_table_count(entry->channels))
589 /* We need to resolve this entry since it is not complete */
591 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
592 /* The entry is being resolved (and we are not the resolver) so attach
593 to the command reply and we're done with this one. */
594 silc_server_command_pending(server, SILC_COMMAND_NONE,
595 entry->resolve_cmd_ident,
596 silc_server_command_destructor,
597 silc_server_command_whois,
598 silc_server_command_dup(cmd));
601 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
602 /* We've resolved this and it still is not ready. We'll return
603 and are that this will be handled again after it is resolved. */
604 for (i = 0; i < resolve_count; i++) {
605 for (k = 0; k < r->res_argc; k++)
606 silc_free(r->res_argv[k]);
607 silc_free(r->res_argv);
608 silc_free(r->res_argv_lens);
609 silc_free(r->res_argv_types);
614 /* We'll resolve this client */
618 for (k = 0; k < resolve_count; k++) {
619 if (resolve[k].router == entry->router) {
626 resolve = silc_realloc(resolve, sizeof(*resolve) *
627 (resolve_count + 1));
628 r = &resolve[resolve_count];
629 memset(r, 0, sizeof(*r));
630 r->router = entry->router;
631 r->ident = ++server->cmd_ident;
635 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
637 r->res_argv_lens = silc_realloc(r->res_argv_lens,
638 sizeof(*r->res_argv_lens) *
640 r->res_argv_types = silc_realloc(r->res_argv_types,
641 sizeof(*r->res_argv_types) *
643 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
644 r->res_argv[r->res_argc] = silc_calloc(idp->len,
645 sizeof(**r->res_argv));
646 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
647 r->res_argv_lens[r->res_argc] = idp->len;
648 r->res_argv_types[r->res_argc] = r->res_argc + 3;
650 silc_buffer_free(idp);
652 entry->resolve_cmd_ident = r->ident;
653 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
654 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
659 /* Do the resolving */
660 for (i = 0; i < resolve_count; i++) {
665 /* Send WHOIS request. We send WHOIS since we're doing the requesting
666 now anyway so make it a good one. */
667 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
668 r->res_argc, r->res_argv,
672 silc_server_packet_send(server, r->router->connection,
673 SILC_PACKET_COMMAND, cmd->packet->flags,
674 res_cmd->data, res_cmd->len, FALSE);
676 /* Reprocess this packet after received reply */
677 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
679 silc_server_command_destructor,
680 silc_server_command_whois,
681 silc_server_command_dup(cmd));
684 silc_buffer_free(res_cmd);
685 for (k = 0; k < r->res_argc; k++)
686 silc_free(r->res_argv[k]);
687 silc_free(r->res_argv);
688 silc_free(r->res_argv_lens);
689 silc_free(r->res_argv_types);
698 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
699 SilcClientEntry *clients,
700 uint32 clients_count,
702 const char *nickname,
703 SilcClientID **client_ids)
705 SilcServer server = cmd->server;
707 int i, k, len, valid_count;
708 SilcBuffer packet, idp, channels;
709 SilcClientEntry entry;
710 SilcCommandStatus status;
711 uint16 ident = silc_command_get_ident(cmd->payload);
712 char nh[256], uh[256];
713 unsigned char idle[4], mode[4];
714 unsigned char *fingerprint;
715 SilcSocketConnection hsock;
717 /* Process only valid clients and ignore those that are not registered. */
719 for (i = 0; i < clients_count; i++) {
720 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
727 /* No valid clients found, send error reply */
729 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
730 SILC_STATUS_ERR_NO_SUCH_NICK,
731 3, nickname, strlen(nickname));
732 } else if (client_ids && client_ids[0]) {
733 SilcBuffer idp = silc_id_payload_encode(client_ids[0], SILC_ID_CLIENT);
734 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
735 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
736 2, idp->data, idp->len);
737 silc_buffer_free(idp);
742 /* Start processing found clients. */
744 status = SILC_STATUS_LIST_START;
746 status = SILC_STATUS_OK;
748 for (i = 0, k = 0; i < clients_count; i++) {
754 status = SILC_STATUS_LIST_ITEM;
755 if (valid_count > 1 && k == valid_count - 1)
756 status = SILC_STATUS_LIST_END;
757 if (count && k - 1 == count)
758 status = SILC_STATUS_LIST_END;
760 /* Send WHOIS reply */
761 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
762 tmp = silc_argument_get_first_arg(cmd->args, NULL);
764 memset(uh, 0, sizeof(uh));
765 memset(nh, 0, sizeof(nh));
766 memset(idle, 0, sizeof(idle));
768 strncat(nh, entry->nickname, strlen(entry->nickname));
769 if (!strchr(entry->nickname, '@')) {
771 if (entry->servername) {
772 strncat(nh, entry->servername, strlen(entry->servername));
774 len = entry->router ? strlen(entry->router->server_name) :
775 strlen(server->server_name);
776 strncat(nh, entry->router ? entry->router->server_name :
777 server->server_name, len);
781 strncat(uh, entry->username, strlen(entry->username));
782 if (!strchr(entry->username, '@')) {
784 hsock = (SilcSocketConnection)entry->connection;
785 len = strlen(hsock->hostname);
786 strncat(uh, hsock->hostname, len);
789 channels = silc_server_get_client_channel_list(server, entry);
791 if (entry->data.fingerprint[0] != 0 && entry->data.fingerprint[1] != 0)
792 fingerprint = entry->data.fingerprint;
796 SILC_PUT32_MSB(entry->mode, mode);
798 if (entry->connection) {
799 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
803 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
805 2, idp->data, idp->len,
809 strlen(entry->userinfo),
810 6, channels ? channels->data : NULL,
811 channels ? channels->len : 0,
815 fingerprint ? 20 : 0);
817 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
818 0, packet->data, packet->len, FALSE);
820 silc_buffer_free(packet);
821 silc_buffer_free(idp);
823 silc_buffer_free(channels);
830 silc_server_command_whois_send_router(SilcServerCommandContext cmd)
832 SilcServer server = cmd->server;
836 old_ident = silc_command_get_ident(cmd->payload);
837 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
838 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
840 /* Send WHOIS command to our router */
841 silc_server_packet_send(server, (SilcSocketConnection)
842 server->router->connection,
843 SILC_PACKET_COMMAND, cmd->packet->flags,
844 tmpbuf->data, tmpbuf->len, TRUE);
846 /* Reprocess this packet after received reply from router */
847 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
848 silc_command_get_ident(cmd->payload),
849 silc_server_command_destructor,
850 silc_server_command_whois,
851 silc_server_command_dup(cmd));
853 silc_command_set_ident(cmd->payload, old_ident);
854 silc_buffer_free(tmpbuf);
858 silc_server_command_whois_process(SilcServerCommandContext cmd)
860 SilcServer server = cmd->server;
861 char *nick = NULL, *server_name = NULL;
863 SilcClientEntry *clients = NULL, entry;
864 SilcClientID **client_id = NULL;
865 uint32 client_id_count = 0, clients_count = 0;
867 bool check_global = FALSE;
869 /* Parse the whois request */
870 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
871 &nick, &server_name, &count,
875 /* Send the WHOIS request to the router only if it included nickname.
876 Since nicknames can be expanded into many clients we need to send it
877 to router. If the WHOIS included only client ID's we will check them
878 first locally since we just might have them. */
879 if (nick && !client_id_count && cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
880 server->server_type == SILC_SERVER && !cmd->pending &&
881 !server->standalone) {
882 silc_server_command_whois_send_router(cmd);
887 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
889 else if (server->server_type != SILC_SERVER)
892 /* Get all clients matching that ID or nickname from local list */
893 if (client_id_count) {
894 /* Check all Client ID's received in the command packet */
895 for (i = 0; i < client_id_count; i++) {
896 entry = silc_idlist_find_client_by_id(server->local_list,
897 client_id[i], TRUE, NULL);
898 if (!entry && check_global)
899 entry = silc_idlist_find_client_by_id(server->global_list,
900 client_id[i], TRUE, NULL);
902 clients = silc_realloc(clients, sizeof(*clients) *
903 (clients_count + 1));
904 clients[clients_count++] = entry;
906 /* If we are normal server and did not send the request first to router
907 do it now, since we do not have the Client ID information. */
908 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
909 server->server_type == SILC_SERVER && !cmd->pending &&
910 !server->standalone) {
911 silc_server_command_whois_send_router(cmd);
918 /* Find by nickname */
919 if (!silc_idlist_get_clients_by_hash(server->local_list,
920 nick, server->md5hash,
921 &clients, &clients_count))
922 silc_idlist_get_clients_by_nickname(server->local_list,
924 &clients, &clients_count);
926 if (!silc_idlist_get_clients_by_hash(server->global_list,
927 nick, server->md5hash,
928 &clients, &clients_count))
929 silc_idlist_get_clients_by_nickname(server->global_list,
931 &clients, &clients_count);
936 /* If we are normal server and did not send the request first to router
937 do it now, since we do not have the information. */
938 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
939 server->server_type == SILC_SERVER && !cmd->pending &&
940 !server->standalone) {
941 silc_server_command_whois_send_router(cmd);
946 /* Such client(s) really does not exist in the SILC network. */
947 if (!client_id_count) {
948 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
949 SILC_STATUS_ERR_NO_SUCH_NICK,
950 3, nick, strlen(nick));
952 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
953 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
954 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
955 2, idp->data, idp->len);
956 silc_buffer_free(idp);
961 /* Router always finds the client entry if it exists in the SILC network.
962 However, it might be incomplete entry and does not include all the
963 mandatory fields that WHOIS command reply requires. Check for these and
964 make query from the server who owns the client if some fields are
966 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
971 /* Send the command reply */
972 silc_server_command_whois_send_reply(cmd, clients, clients_count,
973 count, nick, client_id);
976 if (client_id_count) {
977 for (i = 0; i < client_id_count; i++)
978 silc_free(client_id[i]);
979 silc_free(client_id);
983 silc_free(server_name);
988 /* Server side of command WHOIS. Processes user's query and sends found
989 results as command replies back to the client. */
991 SILC_SERVER_CMD_FUNC(whois)
993 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
996 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 3328);
998 ret = silc_server_command_whois_process(cmd);
1001 silc_server_command_free(cmd);
1004 /******************************************************************************
1008 ******************************************************************************/
1011 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
1019 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1021 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
1022 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1026 /* Get the nickname@server string and parse it. */
1027 silc_parse_userfqdn(tmp, nickname, server_name);
1029 /* Get the max count of reply messages allowed */
1030 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1040 silc_server_command_whowas_check(SilcServerCommandContext cmd,
1041 SilcClientEntry *clients,
1042 uint32 clients_count)
1044 SilcServer server = cmd->server;
1046 SilcClientEntry entry;
1048 for (i = 0; i < clients_count; i++) {
1051 if (!entry->nickname || !entry->username) {
1058 old_ident = silc_command_get_ident(cmd->payload);
1059 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1060 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1062 /* Send WHOWAS command */
1063 silc_server_packet_send(server, entry->router->connection,
1064 SILC_PACKET_COMMAND, cmd->packet->flags,
1065 tmpbuf->data, tmpbuf->len, TRUE);
1067 /* Reprocess this packet after received reply */
1068 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1069 silc_command_get_ident(cmd->payload),
1070 silc_server_command_destructor,
1071 silc_server_command_whowas,
1072 silc_server_command_dup(cmd));
1073 cmd->pending = TRUE;
1075 silc_command_set_ident(cmd->payload, old_ident);
1077 silc_buffer_free(tmpbuf);
1086 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1087 SilcClientEntry *clients,
1088 uint32 clients_count)
1090 SilcServer server = cmd->server;
1092 int i, count = 0, len;
1093 SilcBuffer packet, idp;
1094 SilcClientEntry entry = NULL;
1095 SilcCommandStatus status;
1096 uint16 ident = silc_command_get_ident(cmd->payload);
1098 char nh[256], uh[256];
1100 status = SILC_STATUS_OK;
1101 if (clients_count > 1)
1102 status = SILC_STATUS_LIST_START;
1104 for (i = 0; i < clients_count; i++) {
1107 /* We will take only clients that are not valid anymore. They are the
1108 ones that are not registered anymore but still have a ID. They
1109 have disconnected us, and thus valid for WHOWAS. */
1110 if (entry->data.status & SILC_IDLIST_STATUS_REGISTERED || !entry->id)
1113 if (count && i - 1 == count)
1118 if (clients_count > 2)
1119 status = SILC_STATUS_LIST_ITEM;
1120 if (clients_count > 1 && i == clients_count - 1)
1121 status = SILC_STATUS_LIST_END;
1123 /* Send WHOWAS reply */
1124 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1125 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1126 memset(uh, 0, sizeof(uh));
1127 memset(nh, 0, sizeof(nh));
1129 strncat(nh, entry->nickname, strlen(entry->nickname));
1130 if (!strchr(entry->nickname, '@')) {
1131 strncat(nh, "@", 1);
1132 if (entry->servername) {
1133 strncat(nh, entry->servername, strlen(entry->servername));
1135 len = entry->router ? strlen(entry->router->server_name) :
1136 strlen(server->server_name);
1137 strncat(nh, entry->router ? entry->router->server_name :
1138 server->server_name, len);
1142 strncat(uh, entry->username, strlen(entry->username));
1143 if (!strchr(entry->username, '@')) {
1144 strncat(uh, "@", 1);
1145 strcat(uh, "*private*");
1149 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1151 2, idp->data, idp->len,
1156 strlen(entry->userinfo) : 0);
1157 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1158 0, packet->data, packet->len, FALSE);
1160 silc_buffer_free(packet);
1161 silc_buffer_free(idp);
1164 if (found == FALSE && entry)
1165 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1166 SILC_STATUS_ERR_NO_SUCH_NICK,
1168 strlen(entry->nickname));
1172 silc_server_command_whowas_process(SilcServerCommandContext cmd)
1174 SilcServer server = cmd->server;
1175 char *nick = NULL, *server_name = NULL;
1177 SilcClientEntry *clients = NULL;
1178 uint32 clients_count = 0;
1180 bool check_global = FALSE;
1182 /* Protocol dictates that we must always send the received WHOWAS request
1183 to our router if we are normal server, so let's do it now unless we
1184 are standalone. We will not send any replies to the client until we
1185 have received reply from the router. */
1186 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1187 server->server_type == SILC_SERVER && !cmd->pending &&
1188 !server->standalone) {
1192 old_ident = silc_command_get_ident(cmd->payload);
1193 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1194 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1196 /* Send WHOWAS command to our router */
1197 silc_server_packet_send(server, (SilcSocketConnection)
1198 server->router->connection,
1199 SILC_PACKET_COMMAND, cmd->packet->flags,
1200 tmpbuf->data, tmpbuf->len, TRUE);
1202 /* Reprocess this packet after received reply from router */
1203 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1204 silc_command_get_ident(cmd->payload),
1205 silc_server_command_destructor,
1206 silc_server_command_whowas,
1207 silc_server_command_dup(cmd));
1208 cmd->pending = TRUE;
1210 silc_command_set_ident(cmd->payload, old_ident);
1212 silc_buffer_free(tmpbuf);
1217 /* We are ready to process the command request. Let's search for the
1218 requested client and send reply to the requesting client. */
1220 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1221 check_global = TRUE;
1222 else if (server->server_type != SILC_SERVER)
1223 check_global = TRUE;
1225 /* Parse the whowas request */
1226 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1229 /* Get all clients matching that nickname from local list */
1230 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1232 &clients, &clients_count))
1233 silc_idlist_get_clients_by_hash(server->local_list,
1234 nick, server->md5hash,
1235 &clients, &clients_count);
1237 /* Check global list as well */
1239 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1241 &clients, &clients_count))
1242 silc_idlist_get_clients_by_hash(server->global_list,
1243 nick, server->md5hash,
1244 &clients, &clients_count);
1248 /* Such a client really does not exist in the SILC network. */
1249 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1250 SILC_STATUS_ERR_NO_SUCH_NICK,
1251 3, nick, strlen(nick));
1255 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1260 /* Send the command reply to the client */
1261 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1266 silc_free(server_name);
1271 /* Server side of command WHOWAS. */
1273 SILC_SERVER_CMD_FUNC(whowas)
1275 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1278 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1280 ret = silc_server_command_whowas_process(cmd);
1283 silc_server_command_free(cmd);
1286 /******************************************************************************
1290 ******************************************************************************/
1293 silc_server_command_identify_send_router(SilcServerCommandContext cmd)
1295 SilcServer server = cmd->server;
1299 old_ident = silc_command_get_ident(cmd->payload);
1300 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1301 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1303 /* Send IDENTIFY command to our router */
1304 silc_server_packet_send(server, (SilcSocketConnection)
1305 server->router->connection,
1306 SILC_PACKET_COMMAND, cmd->packet->flags,
1307 tmpbuf->data, tmpbuf->len, TRUE);
1309 /* Reprocess this packet after received reply from router */
1310 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1311 silc_command_get_ident(cmd->payload),
1312 silc_server_command_destructor,
1313 silc_server_command_identify,
1314 silc_server_command_dup(cmd));
1315 cmd->pending = TRUE;
1316 silc_command_set_ident(cmd->payload, old_ident);
1317 silc_buffer_free(tmpbuf);
1321 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1322 SilcClientEntry **clients,
1323 uint32 *clients_count,
1324 SilcServerEntry **servers,
1325 uint32 *servers_count,
1326 SilcChannelEntry **channels,
1327 uint32 *channels_count,
1330 SilcServer server = cmd->server;
1333 uint32 argc = silc_argument_get_arg_num(cmd->args);
1335 bool check_global = FALSE;
1340 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1341 check_global = TRUE;
1342 else if (server->server_type != SILC_SERVER)
1343 check_global = TRUE;
1345 /* If ID Payload is in the command it must be used instead of names */
1346 tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1348 /* No ID, get the names. */
1350 /* If we are normal server and have not resolved information from
1351 router yet, do so now. */
1352 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1353 server->server_type == SILC_SERVER && !cmd->pending &&
1354 !server->standalone) {
1355 silc_server_command_identify_send_router(cmd);
1359 /* Try to get nickname@server. */
1360 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1363 char *nick_server = NULL;
1365 silc_parse_userfqdn(tmp, &nick, &nick_server);
1367 if (!silc_idlist_get_clients_by_hash(server->local_list,
1368 nick, server->md5hash,
1369 clients, clients_count))
1370 silc_idlist_get_clients_by_nickname(server->local_list,
1372 clients, clients_count);
1374 if (!silc_idlist_get_clients_by_hash(server->global_list,
1375 nick, server->md5hash,
1376 clients, clients_count))
1377 silc_idlist_get_clients_by_nickname(server->global_list,
1379 clients, clients_count);
1383 silc_free(nick_server);
1386 /* the nickname does not exist, send error reply */
1387 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1388 SILC_STATUS_ERR_NO_SUCH_NICK,
1389 3, tmp, strlen(tmp));
1394 /* Try to get server name */
1395 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1397 entry = silc_idlist_find_server_by_name(server->local_list,
1399 if (!entry && check_global)
1400 entry = silc_idlist_find_server_by_name(server->global_list,
1403 *servers = silc_realloc(*servers, sizeof(**servers) *
1404 (*servers_count + 1));
1405 (*servers)[(*servers_count)++] = entry;
1409 /* the server does not exist, send error reply */
1410 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1411 SILC_STATUS_ERR_NO_SUCH_SERVER,
1412 3, tmp, strlen(tmp));
1417 /* Try to get channel name */
1418 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1420 entry = silc_idlist_find_channel_by_name(server->local_list,
1422 if (!entry && check_global)
1423 entry = silc_idlist_find_channel_by_name(server->global_list,
1426 *channels = silc_realloc(*channels, sizeof(**channels) *
1427 (*channels_count + 1));
1428 (*channels)[(*channels_count)++] = entry;
1432 /* The channel does not exist, send error reply */
1433 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1434 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1435 3, tmp, strlen(tmp));
1440 if (!(*clients) && !(*servers) && !(*channels)) {
1441 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1442 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1446 /* Command includes ID, we must use that. Also check whether the command
1447 has more than one ID set - take them all. */
1449 /* Take all ID's from the command packet */
1450 for (i = 0; i < argc; i++) {
1453 tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
1457 idp = silc_id_payload_parse(tmp, len);
1459 silc_free(*clients);
1460 silc_free(*servers);
1461 silc_free(*channels);
1462 silc_server_command_send_status_reply(
1463 cmd, SILC_COMMAND_IDENTIFY,
1464 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1468 id = silc_id_payload_get_id(idp);
1470 switch (silc_id_payload_get_type(idp)) {
1472 case SILC_ID_CLIENT:
1473 entry = (void *)silc_idlist_find_client_by_id(server->local_list,
1475 if (!entry && check_global)
1476 entry = (void *)silc_idlist_find_client_by_id(server->global_list,
1479 *clients = silc_realloc(*clients, sizeof(**clients) *
1480 (*clients_count + 1));
1481 (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
1483 /* If we are normal server and have not resolved information from
1484 router yet, do so now. */
1485 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1486 server->server_type == SILC_SERVER && !cmd->pending &&
1487 !server->standalone) {
1488 silc_server_command_identify_send_router(cmd);
1489 silc_free(*clients);
1490 silc_free(*servers);
1491 silc_free(*channels);
1494 silc_server_command_send_status_data(
1495 cmd, SILC_COMMAND_IDENTIFY,
1496 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1504 case SILC_ID_SERVER:
1505 entry = (void *)silc_idlist_find_server_by_id(server->local_list,
1507 if (!entry && check_global)
1508 entry = (void *)silc_idlist_find_server_by_id(server->global_list,
1511 *servers = silc_realloc(*servers, sizeof(**servers) *
1512 (*servers_count + 1));
1513 (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
1515 /* If we are normal server and have not resolved information from
1516 router yet, do so now. */
1517 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1518 server->server_type == SILC_SERVER && !cmd->pending &&
1519 !server->standalone) {
1520 silc_server_command_identify_send_router(cmd);
1521 silc_free(*clients);
1522 silc_free(*servers);
1523 silc_free(*channels);
1526 silc_server_command_send_status_data(
1527 cmd, SILC_COMMAND_IDENTIFY,
1528 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
1535 case SILC_ID_CHANNEL:
1536 entry = (void *)silc_idlist_find_channel_by_id(server->local_list,
1538 if (!entry && check_global)
1539 entry = (void *)silc_idlist_find_channel_by_id(server->global_list,
1542 *channels = silc_realloc(*channels, sizeof(**channels) *
1543 (*channels_count + 1));
1544 (*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
1546 /* If we are normal server and have not resolved information from
1547 router yet, do so now. */
1548 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1549 server->server_type == SILC_SERVER && !cmd->pending &&
1550 !server->standalone) {
1551 silc_server_command_identify_send_router(cmd);
1552 silc_free(*clients);
1553 silc_free(*servers);
1554 silc_free(*channels);
1557 silc_server_command_send_status_data(
1558 cmd, SILC_COMMAND_IDENTIFY,
1559 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
1572 silc_free(*clients);
1573 silc_free(*servers);
1574 silc_free(*channels);
1578 /* Get the max count of reply messages allowed */
1579 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1588 /* Checks that all mandatory fields in client entry are present. If not
1589 then send WHOIS request to the server who owns the client. We use
1590 WHOIS because we want to get as much information as possible at once. */
1593 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1594 SilcClientEntry *clients,
1595 uint32 clients_count)
1597 SilcServer server = cmd->server;
1598 SilcClientEntry entry;
1599 SilcServerResolveContext resolve = NULL, r = NULL;
1600 uint32 resolve_count = 0;
1604 for (i = 0; i < clients_count; i++) {
1609 if (entry->nickname ||
1610 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1614 /* If we are normal server, and we've not resolved this client from
1615 router and it is global client, we'll check whether it is on some
1616 channel. If not then we cannot be sure about its validity, and
1617 we'll resolve it from router. */
1618 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
1619 entry->connection || silc_hash_table_count(entry->channels))
1623 /* We need to resolve this entry since it is not complete */
1625 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1626 /* The entry is being resolved (and we are not the resolver) so attach
1627 to the command reply and we're done with this one. */
1628 silc_server_command_pending(server, SILC_COMMAND_NONE,
1629 entry->resolve_cmd_ident,
1630 silc_server_command_destructor,
1631 silc_server_command_identify,
1632 silc_server_command_dup(cmd));
1635 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1636 /* We've resolved this and it still is not ready. We'll return
1637 and are that this will be handled again after it is resolved. */
1638 for (i = 0; i < resolve_count; i++) {
1639 for (k = 0; k < r->res_argc; k++)
1640 silc_free(r->res_argv[k]);
1641 silc_free(r->res_argv);
1642 silc_free(r->res_argv_lens);
1643 silc_free(r->res_argv_types);
1648 /* We'll resolve this client */
1652 for (k = 0; k < resolve_count; k++) {
1653 if (resolve[k].router == entry->router) {
1660 resolve = silc_realloc(resolve, sizeof(*resolve) *
1661 (resolve_count + 1));
1662 r = &resolve[resolve_count];
1663 memset(r, 0, sizeof(*r));
1664 r->router = entry->router;
1665 r->ident = ++server->cmd_ident;
1669 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1671 r->res_argv_lens = silc_realloc(r->res_argv_lens,
1672 sizeof(*r->res_argv_lens) *
1674 r->res_argv_types = silc_realloc(r->res_argv_types,
1675 sizeof(*r->res_argv_types) *
1677 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1678 r->res_argv[r->res_argc] = silc_calloc(idp->len,
1679 sizeof(**r->res_argv));
1680 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1681 r->res_argv_lens[r->res_argc] = idp->len;
1682 r->res_argv_types[r->res_argc] = r->res_argc + 3;
1684 silc_buffer_free(idp);
1686 entry->resolve_cmd_ident = r->ident;
1687 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1688 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1693 /* Do the resolving */
1694 for (i = 0; i < resolve_count; i++) {
1699 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1700 now anyway so make it a good one. */
1701 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1702 r->res_argc, r->res_argv,
1706 silc_server_packet_send(server, r->router->connection,
1707 SILC_PACKET_COMMAND, cmd->packet->flags,
1708 res_cmd->data, res_cmd->len, FALSE);
1710 /* Reprocess this packet after received reply */
1711 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1713 silc_server_command_destructor,
1714 silc_server_command_identify,
1715 silc_server_command_dup(cmd));
1716 cmd->pending = TRUE;
1718 silc_buffer_free(res_cmd);
1719 for (k = 0; k < r->res_argc; k++)
1720 silc_free(r->res_argv[k]);
1721 silc_free(r->res_argv);
1722 silc_free(r->res_argv_lens);
1723 silc_free(r->res_argv_types);
1732 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1733 SilcClientEntry *clients,
1734 uint32 clients_count,
1735 SilcServerEntry *servers,
1736 uint32 servers_count,
1737 SilcChannelEntry *channels,
1738 uint32 channels_count,
1741 SilcServer server = cmd->server;
1742 int i, k, len, valid_count;
1743 SilcBuffer packet, idp;
1744 SilcCommandStatus status;
1745 uint16 ident = silc_command_get_ident(cmd->payload);
1746 char nh[256], uh[256];
1747 SilcSocketConnection hsock;
1749 status = SILC_STATUS_OK;
1752 SilcClientEntry entry;
1754 /* Process only valid entries. */
1756 for (i = 0; i < clients_count; i++) {
1757 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1764 /* No valid entries found at all, just send error */
1767 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1769 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1770 SILC_STATUS_ERR_NO_SUCH_NICK,
1771 3, tmp, strlen(tmp));
1773 tmp = silc_argument_get_arg_type(cmd->args, 5, (uint32 *)&len);
1774 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1775 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1781 /* Process all valid client entries and send command replies */
1783 if (valid_count > 1)
1784 status = SILC_STATUS_LIST_START;
1786 for (i = 0, k = 0; i < clients_count; i++) {
1792 status = SILC_STATUS_LIST_ITEM;
1793 if (valid_count > 1 && k == valid_count - 1
1794 && !servers_count && !channels_count)
1795 status = SILC_STATUS_LIST_END;
1796 if (count && k - 1 == count)
1797 status = SILC_STATUS_LIST_END;
1798 if (count && k - 1 > count)
1801 /* Send IDENTIFY reply */
1803 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1804 memset(uh, 0, sizeof(uh));
1805 memset(nh, 0, sizeof(nh));
1806 strncat(nh, entry->nickname, strlen(entry->nickname));
1807 if (!strchr(entry->nickname, '@')) {
1808 strncat(nh, "@", 1);
1809 if (entry->servername) {
1810 strncat(nh, entry->servername, strlen(entry->servername));
1812 len = entry->router ? strlen(entry->router->server_name) :
1813 strlen(server->server_name);
1814 strncat(nh, entry->router ? entry->router->server_name :
1815 server->server_name, len);
1819 if (!entry->username) {
1820 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1822 2, idp->data, idp->len,
1825 strncat(uh, entry->username, strlen(entry->username));
1826 if (!strchr(entry->username, '@')) {
1827 strncat(uh, "@", 1);
1828 hsock = (SilcSocketConnection)entry->connection;
1829 len = strlen(hsock->hostname);
1830 strncat(uh, hsock->hostname, len);
1833 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1835 2, idp->data, idp->len,
1840 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1841 0, packet->data, packet->len, FALSE);
1843 silc_buffer_free(packet);
1844 silc_buffer_free(idp);
1851 SilcServerEntry entry;
1853 if (status == SILC_STATUS_OK && servers_count > 1)
1854 status = SILC_STATUS_LIST_START;
1856 for (i = 0, k = 0; i < servers_count; i++) {
1860 status = SILC_STATUS_LIST_ITEM;
1861 if (servers_count > 1 && k == servers_count - 1 && !channels_count)
1862 status = SILC_STATUS_LIST_END;
1863 if (count && k - 1 == count)
1864 status = SILC_STATUS_LIST_END;
1865 if (count && k - 1 > count)
1868 /* Send IDENTIFY reply */
1869 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1871 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1873 2, idp->data, idp->len,
1874 3, entry->server_name,
1875 entry->server_name ?
1876 strlen(entry->server_name) : 0);
1877 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1878 0, packet->data, packet->len, FALSE);
1880 silc_buffer_free(packet);
1881 silc_buffer_free(idp);
1888 SilcChannelEntry entry;
1890 if (status == SILC_STATUS_OK && channels_count > 1)
1891 status = SILC_STATUS_LIST_START;
1893 for (i = 0, k = 0; i < channels_count; i++) {
1894 entry = channels[i];
1897 status = SILC_STATUS_LIST_ITEM;
1898 if (channels_count > 1 && k == channels_count - 1)
1899 status = SILC_STATUS_LIST_END;
1900 if (count && k - 1 == count)
1901 status = SILC_STATUS_LIST_END;
1902 if (count && k - 1 > count)
1905 /* Send IDENTIFY reply */
1906 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1908 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1910 2, idp->data, idp->len,
1911 3, entry->channel_name,
1912 entry->channel_name ?
1913 strlen(entry->channel_name): 0);
1914 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1915 0, packet->data, packet->len, FALSE);
1917 silc_buffer_free(packet);
1918 silc_buffer_free(idp);
1926 silc_server_command_identify_process(SilcServerCommandContext cmd)
1930 SilcClientEntry *clients = NULL;
1931 SilcServerEntry *servers = NULL;
1932 SilcChannelEntry *channels = NULL;
1933 uint32 clients_count = 0, servers_count = 0, channels_count = 0;
1935 /* Parse the IDENTIFY request */
1936 ret = silc_server_command_identify_parse(cmd,
1937 &clients, &clients_count,
1938 &servers, &servers_count,
1939 &channels, &channels_count,
1945 /* Check that all mandatory fields are present and request those data
1946 from the server who owns the client if necessary. */
1947 if (clients && !silc_server_command_identify_check_client(cmd, clients,
1953 /* Send the command reply to the client */
1954 silc_server_command_identify_send_reply(cmd,
1955 clients, clients_count,
1956 servers, servers_count,
1957 channels, channels_count,
1963 silc_free(channels);
1967 SILC_SERVER_CMD_FUNC(identify)
1969 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1972 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1974 ret = silc_server_command_identify_process(cmd);
1977 silc_server_command_free(cmd);
1980 /* Checks string for bad characters and returns TRUE if they are found. */
1982 static int silc_server_command_bad_chars(char *nick)
1986 for (i = 0; i < strlen(nick); i++) {
1987 if (!isascii(nick[i]))
1989 if (nick[i] <= 32) return TRUE;
1990 if (nick[i] == ' ') return TRUE;
1991 if (nick[i] == '*') return TRUE;
1992 if (nick[i] == '?') return TRUE;
1993 if (nick[i] == ',') return TRUE;
1999 /* Server side of command NICK. Sets nickname for user. Setting
2000 nickname causes generation of a new client ID for the client. The
2001 new client ID is sent to the client after changing the nickname. */
2003 SILC_SERVER_CMD_FUNC(nick)
2005 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2006 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2007 SilcServer server = cmd->server;
2008 SilcBuffer packet, nidp, oidp = NULL;
2009 SilcClientID *new_id;
2011 uint16 ident = silc_command_get_ident(cmd->payload);
2014 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2017 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
2019 /* Check nickname */
2020 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
2021 if (silc_server_command_bad_chars(nick) == TRUE) {
2022 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2023 SILC_STATUS_ERR_BAD_NICKNAME);
2027 if (strlen(nick) > 128)
2030 /* Check for same nickname */
2031 if (!strcmp(client->nickname, nick)) {
2032 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2036 /* Create new Client ID */
2037 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
2039 cmd->server->md5hash, nick,
2042 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2045 /* Send notify about nickname change to our router. We send the new
2046 ID and ask to replace it with the old one. If we are router the
2047 packet is broadcasted. Send NICK_CHANGE notify. */
2048 if (!server->standalone)
2049 silc_server_send_notify_nick_change(server, server->router->connection,
2050 server->server_type == SILC_SERVER ?
2051 FALSE : TRUE, client->id,
2054 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2056 /* Remove old cache entry */
2057 silc_idcache_del_by_context(server->local_list->clients, client);
2060 silc_free(client->id);
2062 /* Save the nickname as this client is our local client */
2063 silc_free(client->nickname);
2065 client->nickname = strdup(nick);
2066 client->id = new_id;
2068 /* Update client cache */
2069 silc_idcache_add(server->local_list->clients, client->nickname,
2070 client->id, (void *)client, 0, NULL);
2072 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2074 /* Send NICK_CHANGE notify to the client's channels */
2075 silc_server_send_notify_on_channels(server, NULL, client,
2076 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
2077 oidp->data, oidp->len,
2078 nidp->data, nidp->len);
2081 /* Send the new Client ID as reply command back to client */
2082 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
2083 SILC_STATUS_OK, ident, 1,
2084 2, nidp->data, nidp->len);
2085 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2086 0, packet->data, packet->len, FALSE);
2088 silc_buffer_free(packet);
2089 silc_buffer_free(nidp);
2091 silc_buffer_free(oidp);
2094 silc_server_command_free(cmd);
2097 /* Sends the LIST command reply */
2100 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2101 SilcChannelEntry *lch,
2103 SilcChannelEntry *gch,
2107 SilcBuffer packet, idp;
2108 SilcChannelEntry entry;
2109 SilcCommandStatus status;
2110 uint16 ident = silc_command_get_ident(cmd->payload);
2112 unsigned char usercount[4];
2114 int valid_lcount = 0, valid_rcount = 0;
2116 for (i = 0; i < lch_count; i++) {
2117 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2122 for (i = 0; i < gch_count; i++) {
2123 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2129 status = SILC_STATUS_OK;
2130 if ((lch_count + gch_count) > 1)
2131 status = SILC_STATUS_LIST_START;
2134 for (i = 0, k = 0; i < lch_count; i++) {
2140 status = SILC_STATUS_LIST_ITEM;
2141 if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
2142 status = SILC_STATUS_LIST_END;
2144 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2146 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2147 topic = "*private*";
2148 memset(usercount, 0, sizeof(usercount));
2150 topic = entry->topic;
2151 users = silc_hash_table_count(entry->user_list);
2152 SILC_PUT32_MSB(users, usercount);
2155 /* Send the reply */
2157 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2159 2, idp->data, idp->len,
2160 3, entry->channel_name,
2161 strlen(entry->channel_name),
2162 4, topic, topic ? strlen(topic) : 0,
2164 silc_server_packet_send(cmd->server, cmd->sock,
2165 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2166 packet->len, FALSE);
2167 silc_buffer_free(packet);
2168 silc_buffer_free(idp);
2173 for (i = 0, k = 0; i < gch_count; i++) {
2179 status = SILC_STATUS_LIST_ITEM;
2180 if (valid_rcount > 1 && k == valid_rcount - 1)
2181 status = SILC_STATUS_LIST_END;
2183 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2185 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2186 topic = "*private*";
2187 memset(usercount, 0, sizeof(usercount));
2189 topic = entry->topic;
2190 users = silc_hash_table_count(entry->user_list);
2191 SILC_PUT32_MSB(users, usercount);
2194 /* Send the reply */
2196 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2198 2, idp->data, idp->len,
2199 3, entry->channel_name,
2200 strlen(entry->channel_name),
2201 4, topic, topic ? strlen(topic) : 0,
2203 silc_server_packet_send(cmd->server, cmd->sock,
2204 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2205 packet->len, FALSE);
2206 silc_buffer_free(packet);
2207 silc_buffer_free(idp);
2212 /* Server side of LIST command. This lists the channel of the requested
2213 server. Secret channels are not listed. */
2215 SILC_SERVER_CMD_FUNC(list)
2217 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2218 SilcServer server = cmd->server;
2219 SilcChannelID *channel_id = NULL;
2222 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2223 uint32 lch_count = 0, gch_count = 0;
2225 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2227 /* If we are normal server, send the command to router, since we
2228 want to know all channels in the network. */
2229 if (!cmd->pending && server->server_type == SILC_SERVER &&
2230 !server->standalone) {
2234 old_ident = silc_command_get_ident(cmd->payload);
2235 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2236 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2237 silc_server_packet_send(server, server->router->connection,
2238 SILC_PACKET_COMMAND, cmd->packet->flags,
2239 tmpbuf->data, tmpbuf->len, TRUE);
2241 /* Reprocess this packet after received reply from router */
2242 silc_server_command_pending(server, SILC_COMMAND_LIST,
2243 silc_command_get_ident(cmd->payload),
2244 silc_server_command_destructor,
2245 silc_server_command_list,
2246 silc_server_command_dup(cmd));
2247 cmd->pending = TRUE;
2248 silc_command_set_ident(cmd->payload, old_ident);
2249 silc_buffer_free(tmpbuf);
2253 /* Get Channel ID */
2254 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2256 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2258 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2259 SILC_STATUS_ERR_NO_CHANNEL_ID);
2264 /* Get the channels from local list */
2265 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2268 /* Get the channels from global list */
2269 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2272 /* Send the reply */
2273 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2274 gchannels, gch_count);
2276 silc_free(lchannels);
2277 silc_free(gchannels);
2280 silc_server_command_free(cmd);
2283 /* Server side of TOPIC command. Sets topic for channel and/or returns
2284 current topic to client. */
2286 SILC_SERVER_CMD_FUNC(topic)
2288 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2289 SilcServer server = cmd->server;
2290 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2291 SilcChannelID *channel_id;
2292 SilcChannelEntry channel;
2293 SilcChannelClientEntry chl;
2294 SilcBuffer packet, idp;
2296 uint32 argc, tmp_len;
2297 uint16 ident = silc_command_get_ident(cmd->payload);
2299 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2301 argc = silc_argument_get_arg_num(cmd->args);
2303 /* Get Channel ID */
2304 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2306 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2307 SILC_STATUS_ERR_NO_CHANNEL_ID);
2310 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2312 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2313 SILC_STATUS_ERR_NO_CHANNEL_ID);
2317 /* Check whether the channel exists */
2318 channel = silc_idlist_find_channel_by_id(server->local_list,
2321 channel = silc_idlist_find_channel_by_id(server->global_list,
2324 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2325 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2332 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2334 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2335 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2339 if (strlen(tmp) > 256) {
2340 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2341 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2345 /* See whether the client is on channel and has rights to change topic */
2346 if (!silc_hash_table_find(channel->user_list, client, NULL,
2348 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2349 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2353 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2354 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2355 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2356 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2361 /* Set the topic for channel */
2362 silc_free(channel->topic);
2363 channel->topic = strdup(tmp);
2365 /* Send TOPIC_SET notify type to the network */
2366 if (!server->standalone)
2367 silc_server_send_notify_topic_set(server, server->router->connection,
2368 server->server_type == SILC_ROUTER ?
2369 TRUE : FALSE, channel,
2370 client->id, SILC_ID_CLIENT,
2373 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2375 /* Send notify about topic change to all clients on the channel */
2376 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2377 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2378 idp->data, idp->len,
2379 channel->topic, strlen(channel->topic));
2380 silc_buffer_free(idp);
2383 /* Send the topic to client as reply packet */
2384 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2385 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2386 SILC_STATUS_OK, ident, 2,
2387 2, idp->data, idp->len,
2390 strlen(channel->topic) : 0);
2391 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2392 0, packet->data, packet->len, FALSE);
2394 silc_buffer_free(packet);
2395 silc_buffer_free(idp);
2396 silc_free(channel_id);
2399 silc_server_command_free(cmd);
2402 /* Server side of INVITE command. Invites some client to join some channel.
2403 This command is also used to manage the invite list of the channel. */
2405 SILC_SERVER_CMD_FUNC(invite)
2407 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2408 SilcServer server = cmd->server;
2409 SilcSocketConnection sock = cmd->sock, dest_sock;
2410 SilcChannelClientEntry chl;
2411 SilcClientEntry sender, dest;
2412 SilcClientID *dest_id = NULL;
2413 SilcChannelEntry channel;
2414 SilcChannelID *channel_id = NULL;
2415 SilcIDListData idata;
2416 SilcBuffer idp, idp2, packet;
2417 unsigned char *tmp, *add, *del;
2419 uint16 ident = silc_command_get_ident(cmd->payload);
2421 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2423 /* Get Channel ID */
2424 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2426 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2427 SILC_STATUS_ERR_NO_CHANNEL_ID);
2430 channel_id = silc_id_payload_parse_id(tmp, len);
2432 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2433 SILC_STATUS_ERR_NO_CHANNEL_ID);
2437 /* Get the channel entry */
2438 channel = silc_idlist_find_channel_by_id(server->local_list,
2441 channel = silc_idlist_find_channel_by_id(server->global_list,
2444 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2445 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2450 /* Check whether the sender of this command is on the channel. */
2451 sender = (SilcClientEntry)sock->user_data;
2452 if (!silc_server_client_on_channel(sender, channel)) {
2453 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2454 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2458 /* Check whether the channel is invite-only channel. If yes then the
2459 sender of this command must be at least channel operator. */
2460 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2461 silc_hash_table_find(channel->user_list, sender, NULL, (void *)&chl);
2462 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2463 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2464 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2469 /* Get destination client ID */
2470 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2474 dest_id = silc_id_payload_parse_id(tmp, len);
2476 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2477 SILC_STATUS_ERR_NO_CLIENT_ID);
2481 /* Get the client entry */
2482 dest = silc_server_get_client_resolve(server, dest_id);
2484 if (server->server_type != SILC_SERVER) {
2485 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2486 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2490 /* The client info is being resolved. Reprocess this packet after
2491 receiving the reply to the query. */
2492 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2494 silc_server_command_destructor,
2495 silc_server_command_invite,
2496 silc_server_command_dup(cmd));
2497 cmd->pending = TRUE;
2498 silc_free(channel_id);
2503 /* Check whether the requested client is already on the channel. */
2504 if (silc_server_client_on_channel(dest, channel)) {
2505 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2506 SILC_STATUS_ERR_USER_ON_CHANNEL);
2510 /* Get route to the client */
2511 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2513 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2514 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2518 memset(invite, 0, sizeof(invite));
2519 strncat(invite, dest->nickname, strlen(dest->nickname));
2520 strncat(invite, "!", 1);
2521 strncat(invite, dest->username, strlen(dest->username));
2522 if (!strchr(dest->username, '@')) {
2523 strncat(invite, "@", 1);
2524 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2527 len = strlen(invite);
2528 if (!channel->invite_list)
2529 channel->invite_list = silc_calloc(len + 2,
2530 sizeof(*channel->invite_list));
2532 channel->invite_list = silc_realloc(channel->invite_list,
2533 sizeof(*channel->invite_list) *
2535 strlen(channel->invite_list) + 2));
2536 strncat(channel->invite_list, invite, len);
2537 strncat(channel->invite_list, ",", 1);
2539 /* Send notify to the client that is invited to the channel */
2540 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2541 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2542 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2544 SILC_NOTIFY_TYPE_INVITE, 3,
2545 idp->data, idp->len,
2546 channel->channel_name,
2547 strlen(channel->channel_name),
2548 idp2->data, idp2->len);
2549 silc_buffer_free(idp);
2550 silc_buffer_free(idp2);
2553 /* Add the client to the invite list of the channel */
2554 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2556 if (!channel->invite_list)
2557 channel->invite_list = silc_calloc(len + 2,
2558 sizeof(*channel->invite_list));
2560 channel->invite_list = silc_realloc(channel->invite_list,
2561 sizeof(*channel->invite_list) *
2563 strlen(channel->invite_list) + 2));
2564 if (add[len - 1] == ',')
2565 add[len - 1] = '\0';
2567 strncat(channel->invite_list, add, len);
2568 strncat(channel->invite_list, ",", 1);
2571 /* Get the invite to be removed and remove it from the list */
2572 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2573 if (del && channel->invite_list) {
2574 char *start, *end, *n;
2576 if (!strncmp(channel->invite_list, del,
2577 strlen(channel->invite_list) - 1)) {
2578 silc_free(channel->invite_list);
2579 channel->invite_list = NULL;
2581 start = strstr(channel->invite_list, del);
2582 if (start && strlen(start) >= len) {
2584 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2585 strncat(n, channel->invite_list, start - channel->invite_list);
2586 strncat(n, end + 1, ((channel->invite_list +
2587 strlen(channel->invite_list)) - end) - 1);
2588 silc_free(channel->invite_list);
2589 channel->invite_list = n;
2594 /* Send notify to the primary router */
2595 if (!server->standalone)
2596 silc_server_send_notify_invite(server, server->router->connection,
2597 server->server_type == SILC_ROUTER ?
2598 TRUE : FALSE, channel,
2599 sender->id, add, del);
2601 /* Send command reply */
2602 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2606 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2607 SILC_STATUS_OK, ident, 2,
2609 3, channel->invite_list,
2610 channel->invite_list ?
2611 strlen(channel->invite_list) : 0);
2614 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2615 SILC_STATUS_OK, ident, 1,
2617 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2618 packet->data, packet->len, FALSE);
2619 silc_buffer_free(packet);
2623 silc_free(channel_id);
2624 silc_server_command_free(cmd);
2629 SilcSocketConnection sock;
2633 /* Quits connection to client. This gets called if client won't
2634 close the connection even when it has issued QUIT command. */
2636 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2638 QuitInternal q = (QuitInternal)context;
2640 /* Free all client specific data, such as client entry and entires
2641 on channels this client may be on. */
2642 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2644 q->sock->user_data = NULL;
2646 /* Close the connection on our side */
2647 silc_server_close_connection(q->server, q->sock);
2649 silc_free(q->signoff);
2653 /* Quits SILC session. This is the normal way to disconnect client. */
2655 SILC_SERVER_CMD_FUNC(quit)
2657 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2658 SilcServer server = cmd->server;
2659 SilcSocketConnection sock = cmd->sock;
2661 unsigned char *tmp = NULL;
2664 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2666 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2669 /* Get destination ID */
2670 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2674 q = silc_calloc(1, sizeof(*q));
2677 q->signoff = tmp ? strdup(tmp) : NULL;
2679 /* We quit the connection with little timeout */
2680 silc_schedule_task_add(server->schedule, sock->sock,
2681 silc_server_command_quit_cb, (void *)q,
2682 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2685 silc_server_command_free(cmd);
2688 /* Server side of command KILL. This command is used by router operator
2689 to remove an client from the SILC Network temporarily. */
2691 SILC_SERVER_CMD_FUNC(kill)
2693 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2694 SilcServer server = cmd->server;
2695 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2696 SilcClientEntry remote_client;
2697 SilcClientID *client_id;
2698 unsigned char *tmp, *comment;
2699 uint32 tmp_len, tmp_len2;
2701 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2703 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2706 /* KILL command works only on router */
2707 if (server->server_type != SILC_ROUTER) {
2708 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2709 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2713 /* Check whether client has the permissions. */
2714 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2715 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2716 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2720 /* Get the client ID */
2721 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2723 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2724 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2727 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2729 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2730 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2734 /* Get the client entry */
2735 remote_client = silc_idlist_find_client_by_id(server->local_list,
2736 client_id, TRUE, NULL);
2737 if (!remote_client) {
2738 remote_client = silc_idlist_find_client_by_id(server->global_list,
2739 client_id, TRUE, NULL);
2740 if (!remote_client) {
2741 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2742 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2748 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2752 /* Send reply to the sender */
2753 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2756 /* Send the KILL notify packets. First send it to the channel, then
2757 to our primary router and then directly to the client who is being
2758 killed right now. */
2760 /* Send KILLED notify to the channels. It is not sent to the client
2761 as it will be sent differently destined directly to the client and not
2763 silc_server_send_notify_on_channels(server, remote_client,
2764 remote_client, SILC_NOTIFY_TYPE_KILLED,
2767 comment, comment ? tmp_len2 : 0);
2769 /* Send KILLED notify to primary route */
2770 if (!server->standalone)
2771 silc_server_send_notify_killed(server, server->router->connection, TRUE,
2772 remote_client->id, comment);
2774 /* Send KILLED notify to the client directly */
2775 silc_server_send_notify_killed(server, remote_client->connection ?
2776 remote_client->connection :
2777 remote_client->router->connection, FALSE,
2778 remote_client->id, comment);
2780 /* Remove the client from all channels. This generates new keys to the
2781 channels as well. */
2782 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2785 /* Remove the client entry, If it is locally connected then we will also
2786 disconnect the client here */
2787 if (remote_client->connection) {
2788 /* Remove locally conneted client */
2789 SilcSocketConnection sock = remote_client->connection;
2790 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2791 silc_server_close_connection(server, sock);
2793 /* Remove remote client */
2794 if (!silc_idlist_del_client(server->global_list, remote_client))
2795 silc_idlist_del_client(server->local_list, remote_client);
2799 silc_server_command_free(cmd);
2802 /* Server side of command INFO. This sends information about us to
2803 the client. If client requested specific server we will send the
2804 command to that server. */
2806 SILC_SERVER_CMD_FUNC(info)
2808 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2809 SilcServer server = cmd->server;
2810 SilcBuffer packet, idp;
2813 char *dest_server, *server_info = NULL, *server_name;
2814 uint16 ident = silc_command_get_ident(cmd->payload);
2815 SilcServerEntry entry = NULL;
2816 SilcServerID *server_id = NULL;
2818 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2820 /* Get server name */
2821 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2824 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2826 server_id = silc_id_payload_parse_id(tmp, tmp_len);
2828 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2829 SILC_STATUS_ERR_NO_SERVER_ID);
2835 /* Check whether we have this server cached */
2836 entry = silc_idlist_find_server_by_id(server->local_list,
2837 server_id, TRUE, NULL);
2839 entry = silc_idlist_find_server_by_id(server->global_list,
2840 server_id, TRUE, NULL);
2841 if (!entry && server->server_type != SILC_SERVER) {
2842 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2843 SILC_STATUS_ERR_NO_SUCH_SERVER);
2849 /* Some buggy servers has sent request to router about themselves. */
2850 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2853 if ((!dest_server && !server_id && !entry) || (entry &&
2854 entry == server->id_entry) ||
2855 (dest_server && !cmd->pending &&
2856 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2857 /* Send our reply */
2858 char info_string[256];
2860 memset(info_string, 0, sizeof(info_string));
2861 snprintf(info_string, sizeof(info_string),
2862 "location: %s server: %s admin: %s <%s>",
2863 server->config->admin_info->location,
2864 server->config->admin_info->server_type,
2865 server->config->admin_info->admin_name,
2866 server->config->admin_info->admin_email);
2868 server_info = info_string;
2869 entry = server->id_entry;
2871 /* Check whether we have this server cached */
2872 if (!entry && dest_server) {
2873 entry = silc_idlist_find_server_by_name(server->global_list,
2874 dest_server, TRUE, NULL);
2876 entry = silc_idlist_find_server_by_name(server->local_list,
2877 dest_server, TRUE, NULL);
2881 if (!cmd->pending &&
2882 server->server_type != SILC_SERVER && entry && !entry->server_info) {
2883 /* Send to the server */
2887 old_ident = silc_command_get_ident(cmd->payload);
2888 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2889 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2891 silc_server_packet_send(server, entry->connection,
2892 SILC_PACKET_COMMAND, cmd->packet->flags,
2893 tmpbuf->data, tmpbuf->len, TRUE);
2895 /* Reprocess this packet after received reply from router */
2896 silc_server_command_pending(server, SILC_COMMAND_INFO,
2897 silc_command_get_ident(cmd->payload),
2898 silc_server_command_destructor,
2899 silc_server_command_info,
2900 silc_server_command_dup(cmd));
2901 cmd->pending = TRUE;
2902 silc_command_set_ident(cmd->payload, old_ident);
2903 silc_buffer_free(tmpbuf);
2907 if (!entry && !cmd->pending && !server->standalone) {
2908 /* Send to the primary router */
2912 old_ident = silc_command_get_ident(cmd->payload);
2913 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2914 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2916 silc_server_packet_send(server, server->router->connection,
2917 SILC_PACKET_COMMAND, cmd->packet->flags,
2918 tmpbuf->data, tmpbuf->len, TRUE);
2920 /* Reprocess this packet after received reply from router */
2921 silc_server_command_pending(server, SILC_COMMAND_INFO,
2922 silc_command_get_ident(cmd->payload),
2923 silc_server_command_destructor,
2924 silc_server_command_info,
2925 silc_server_command_dup(cmd));
2926 cmd->pending = TRUE;
2927 silc_command_set_ident(cmd->payload, old_ident);
2928 silc_buffer_free(tmpbuf);
2933 silc_free(server_id);
2936 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2937 SILC_STATUS_ERR_NO_SUCH_SERVER);
2941 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2943 server_info = entry->server_info;
2944 server_name = entry->server_name;
2946 /* Send the reply */
2947 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2948 SILC_STATUS_OK, ident, 3,
2949 2, idp->data, idp->len,
2951 strlen(server_name),
2954 strlen(server_info) : 0);
2955 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2956 packet->data, packet->len, FALSE);
2958 silc_buffer_free(packet);
2959 silc_buffer_free(idp);
2962 silc_server_command_free(cmd);
2965 /* Server side of command PING. This just replies to the ping. */
2967 SILC_SERVER_CMD_FUNC(ping)
2969 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2970 SilcServer server = cmd->server;
2975 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
2978 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2980 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2981 SILC_STATUS_ERR_NO_SERVER_ID);
2984 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2988 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2989 /* Send our reply */
2990 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2993 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2994 SILC_STATUS_ERR_NO_SUCH_SERVER);
3001 silc_server_command_free(cmd);
3004 /* Internal routine to join channel. The channel sent to this function
3005 has been either created or resolved from ID lists. This joins the sent
3006 client to the channel. */
3008 static void silc_server_command_join_channel(SilcServer server,
3009 SilcServerCommandContext cmd,
3010 SilcChannelEntry channel,
3011 SilcClientID *client_id,
3015 const unsigned char *auth,
3018 SilcSocketConnection sock = cmd->sock;
3020 uint32 tmp_len, user_count;
3021 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
3022 SilcClientEntry client;
3023 SilcChannelClientEntry chl;
3024 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
3025 uint16 ident = silc_command_get_ident(cmd->payload);
3026 char check[512], check2[512];
3027 bool founder = FALSE;
3029 SILC_LOG_DEBUG(("Start"));
3034 /* Get the client entry */
3035 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3036 client = (SilcClientEntry)sock->user_data;
3038 client = silc_server_get_client_resolve(server, client_id);
3043 /* The client info is being resolved. Reprocess this packet after
3044 receiving the reply to the query. */
3045 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
3046 server->cmd_ident, NULL,
3047 silc_server_command_join,
3048 silc_server_command_dup(cmd));
3049 cmd->pending = TRUE;
3053 cmd->pending = FALSE;
3057 * Check founder auth payload if provided. If client can gain founder
3058 * privileges it can override various conditions on joining the channel,
3059 * and can have directly the founder mode set on the channel.
3061 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3062 SilcIDListData idata = (SilcIDListData)client;
3064 if (channel->founder_key && idata->public_key &&
3065 silc_pkcs_public_key_compare(channel->founder_key,
3066 idata->public_key)) {
3067 void *auth_data = (channel->founder_method == SILC_AUTH_PASSWORD ?
3068 (void *)channel->founder_passwd :
3069 (void *)channel->founder_key);
3070 uint32 auth_data_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
3071 channel->founder_passwd_len : 0);
3073 /* Check whether the client is to become founder */
3074 if (silc_auth_verify_data(auth, auth_len, channel->founder_method,
3075 auth_data, auth_data_len,
3076 idata->hash, client->id, SILC_ID_CLIENT)) {
3077 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3084 * Check channel modes
3088 memset(check, 0, sizeof(check));
3089 memset(check2, 0, sizeof(check2));
3090 strncat(check, client->nickname, strlen(client->nickname));
3091 strncat(check, "!", 1);
3092 strncat(check, client->username, strlen(client->username));
3093 if (!strchr(client->username, '@')) {
3094 strncat(check, "@", 1);
3095 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3098 strncat(check2, client->nickname, strlen(client->nickname));
3099 if (!strchr(client->nickname, '@')) {
3100 strncat(check2, "@", 1);
3101 strncat(check2, server->server_name, strlen(server->server_name));
3103 strncat(check2, "!", 1);
3104 strncat(check2, client->username, strlen(client->username));
3105 if (!strchr(client->username, '@')) {
3106 strncat(check2, "@", 1);
3107 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3110 /* Check invite list if channel is invite-only channel */
3111 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3112 if (!channel->invite_list ||
3113 (!silc_string_match(channel->invite_list, check) &&
3114 !silc_string_match(channel->invite_list, check2))) {
3115 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3116 SILC_STATUS_ERR_NOT_INVITED);
3121 /* Check ban list if it exists. If the client's nickname, server,
3122 username and/or hostname is in the ban list the access to the
3123 channel is denied. */
3124 if (channel->ban_list) {
3125 if (!channel->ban_list ||
3126 silc_string_match(channel->ban_list, check) ||
3127 silc_string_match(channel->ban_list, check2)) {
3128 silc_server_command_send_status_reply(
3129 cmd, SILC_COMMAND_JOIN,
3130 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
3135 /* Check user count limit if set. */
3136 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3137 if (silc_hash_table_count(channel->user_list) + 1 >
3138 channel->user_limit) {
3139 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3140 SILC_STATUS_ERR_CHANNEL_IS_FULL);
3146 /* Check the channel passphrase if set. */
3147 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3148 /* Get passphrase */
3149 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3151 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
3152 memcpy(passphrase, tmp, tmp_len);
3155 if (!passphrase || !channel->passphrase ||
3156 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3157 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3158 SILC_STATUS_ERR_BAD_PASSWORD);
3164 * Client is allowed to join to the channel. Make it happen.
3167 /* Check whether the client already is on the channel */
3168 if (silc_server_client_on_channel(client, channel)) {
3169 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3170 SILC_STATUS_ERR_USER_ON_CHANNEL);
3174 /* Generate new channel key as protocol dictates */
3176 if (!silc_server_create_channel_key(server, channel, 0))
3179 /* Send the channel key. This is broadcasted to the channel but is not
3180 sent to the client who is joining to the channel. */
3181 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3182 silc_server_send_channel_key(server, NULL, channel,
3183 server->server_type == SILC_ROUTER ?
3184 FALSE : !server->standalone);
3187 /* Join the client to the channel by adding it to channel's user list.
3188 Add also the channel to client entry's channels list for fast cross-
3190 chl = silc_calloc(1, sizeof(*chl));
3192 chl->client = client;
3193 chl->channel = channel;
3194 silc_hash_table_add(channel->user_list, client, chl);
3195 silc_hash_table_add(client->channels, channel, chl);
3197 /* Get users on the channel */
3198 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3201 /* Encode Client ID Payload of the original client who wants to join */
3202 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3204 /* Encode command reply packet */
3205 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3206 SILC_PUT32_MSB(channel->mode, mode);
3207 SILC_PUT32_MSB(created, tmp2);
3208 SILC_PUT32_MSB(user_count, tmp3);
3210 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3211 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3212 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
3213 strlen(channel->channel_key->
3215 channel->channel_key->cipher->name,
3216 channel->key_len / 8, channel->key);
3221 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3222 SILC_STATUS_OK, ident, 13,
3223 2, channel->channel_name,
3224 strlen(channel->channel_name),
3225 3, chidp->data, chidp->len,
3226 4, clidp->data, clidp->len,
3229 7, keyp ? keyp->data : NULL,
3230 keyp ? keyp->len : 0,
3231 8, channel->ban_list,
3233 strlen(channel->ban_list) : 0,
3234 9, channel->invite_list,
3235 channel->invite_list ?
3236 strlen(channel->invite_list) : 0,
3239 strlen(channel->topic) : 0,
3240 11, silc_hmac_get_name(channel->hmac),
3241 strlen(silc_hmac_get_name(channel->
3244 13, user_list->data, user_list->len,
3245 14, mode_list->data,
3248 /* Send command reply */
3249 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3250 reply->data, reply->len, FALSE);
3252 /* Send JOIN notify to locally connected clients on the channel. If
3253 we are normal server then router will send or have sent JOIN notify
3254 already. However since we've added the client already to our channel
3255 we'll ignore it (in packet_receive.c) so we must send it here. If
3256 we are router then this will send it to local clients and local
3258 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3259 SILC_NOTIFY_TYPE_JOIN, 2,
3260 clidp->data, clidp->len,
3261 chidp->data, chidp->len);
3263 if (!cmd->pending) {
3264 /* Send JOIN notify packet to our primary router */
3265 if (!server->standalone)
3266 silc_server_send_notify_join(server, server->router->connection,
3267 server->server_type == SILC_ROUTER ?
3268 TRUE : FALSE, channel, client->id);
3271 /* Distribute the channel key to all backup routers. */
3272 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3273 keyp->data, keyp->len, FALSE, TRUE);
3275 /* If client became founder by providing correct founder auth data
3276 notify the mode change to the channel. */
3278 SILC_PUT32_MSB(chl->mode, mode);
3279 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3280 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3281 clidp->data, clidp->len,
3282 mode, 4, clidp->data, clidp->len);
3284 /* Set CUMODE notify type to network */
3285 if (!server->standalone)
3286 silc_server_send_notify_cumode(server, server->router->connection,
3287 server->server_type == SILC_ROUTER ?
3288 TRUE : FALSE, channel,
3289 chl->mode, client->id, SILC_ID_CLIENT,
3294 silc_buffer_free(reply);
3295 silc_buffer_free(clidp);
3296 silc_buffer_free(chidp);
3297 silc_buffer_free(keyp);
3298 silc_buffer_free(user_list);
3299 silc_buffer_free(mode_list);
3302 silc_free(passphrase);
3305 /* Server side of command JOIN. Joins client into requested channel. If
3306 the channel does not exist it will be created. */
3308 SILC_SERVER_CMD_FUNC(join)
3310 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3311 SilcServer server = cmd->server;
3312 unsigned char *auth;
3313 uint32 tmp_len, auth_len;
3314 char *tmp, *channel_name = NULL, *cipher, *hmac;
3315 SilcChannelEntry channel;
3317 bool created = FALSE, create_key = TRUE;
3318 SilcClientID *client_id;
3320 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3322 /* Get channel name */
3323 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3325 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3326 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3331 if (strlen(channel_name) > 256)
3332 channel_name[255] = '\0';
3334 if (silc_server_command_bad_chars(channel_name) == TRUE) {
3335 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3336 SILC_STATUS_ERR_BAD_CHANNEL);
3340 /* Get Client ID of the client who is joining to the channel */
3341 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3343 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3344 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3347 client_id = silc_id_payload_parse_id(tmp, tmp_len);
3349 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3350 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3354 /* Get cipher, hmac name and auth payload */
3355 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3356 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3357 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3359 /* See if the channel exists */
3360 channel = silc_idlist_find_channel_by_name(server->local_list,
3361 channel_name, NULL);
3363 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3364 /* If this is coming from client the Client ID in the command packet must
3365 be same as the client's ID. */
3366 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3367 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3368 if (!SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
3369 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3370 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3375 if (!channel || channel->disabled) {
3376 /* Channel not found */
3378 /* If we are standalone server we don't have a router, we just create
3379 the channel by ourselves. */
3380 if (server->standalone) {
3381 channel = silc_server_create_new_channel(server, server->id, cipher,
3382 hmac, channel_name, TRUE);
3384 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3385 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3389 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3395 /* The channel does not exist on our server. If we are normal server
3396 we will send JOIN command to our router which will handle the
3397 joining procedure (either creates the channel if it doesn't exist
3398 or joins the client to it). */
3399 if (server->server_type != SILC_ROUTER) {
3403 /* If this is pending command callback then we've resolved
3404 it and it didn't work, return since we've notified the
3405 client already in the command reply callback. */
3409 old_ident = silc_command_get_ident(cmd->payload);
3410 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3411 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3413 /* Send JOIN command to our router */
3414 silc_server_packet_send(server, (SilcSocketConnection)
3415 server->router->connection,
3416 SILC_PACKET_COMMAND, cmd->packet->flags,
3417 tmpbuf->data, tmpbuf->len, TRUE);
3419 /* Reprocess this packet after received reply from router */
3420 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3421 silc_command_get_ident(cmd->payload),
3422 silc_server_command_destructor,
3423 silc_server_command_join,
3424 silc_server_command_dup(cmd));
3425 cmd->pending = TRUE;
3429 /* We are router and the channel does not seem exist so we will check
3430 our global list as well for the channel. */
3431 channel = silc_idlist_find_channel_by_name(server->global_list,
3432 channel_name, NULL);
3434 /* Channel really does not exist, create it */
3435 channel = silc_server_create_new_channel(server, server->id, cipher,
3436 hmac, channel_name, TRUE);
3438 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3439 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3443 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3451 /* Channel not found */
3453 /* If the command came from router and we are normal server then
3454 something went wrong with the joining as the channel was not found.
3455 We can't do anything else but ignore this. */
3456 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3457 server->server_type != SILC_ROUTER)
3460 /* We are router and the channel does not seem exist so we will check
3461 our global list as well for the channel. */
3462 channel = silc_idlist_find_channel_by_name(server->global_list,
3463 channel_name, NULL);
3465 /* Channel really does not exist, create it */
3466 channel = silc_server_create_new_channel(server, server->id, cipher,
3467 hmac, channel_name, TRUE);
3469 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3470 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3474 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3481 /* Check whether the channel was created by our router */
3482 if (cmd->pending && context2) {
3483 SilcServerCommandReplyContext reply =
3484 (SilcServerCommandReplyContext)context2;
3486 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3487 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3488 SILC_GET32_MSB(created, tmp);
3489 create_key = FALSE; /* Router returned the key already */
3492 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS)
3496 /* If the channel does not have global users and is also empty the client
3497 will be the channel founder and operator. */
3498 if (!channel->global_users && !silc_hash_table_count(channel->user_list))
3499 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3501 /* Join to the channel */
3502 silc_server_command_join_channel(server, cmd, channel, client_id,
3503 created, create_key, umode,
3506 silc_free(client_id);
3509 silc_server_command_free(cmd);
3512 /* Server side of command MOTD. Sends server's current "message of the
3513 day" to the client. */
3515 SILC_SERVER_CMD_FUNC(motd)
3517 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3518 SilcServer server = cmd->server;
3519 SilcBuffer packet, idp;
3520 char *motd, *dest_server;
3522 uint16 ident = silc_command_get_ident(cmd->payload);
3524 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3526 /* Get server name */
3527 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3529 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3530 SILC_STATUS_ERR_NO_SUCH_SERVER);
3534 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3537 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3539 if (server->config && server->config->motd &&
3540 server->config->motd->motd_file) {
3542 motd = silc_file_readfile(server->config->motd->motd_file, &motd_len);
3547 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3548 SILC_STATUS_OK, ident, 2,
3553 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3554 SILC_STATUS_OK, ident, 1,
3558 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3559 packet->data, packet->len, FALSE);
3560 silc_buffer_free(packet);
3561 silc_buffer_free(idp);
3563 SilcServerEntry entry;
3565 /* Check whether we have this server cached */
3566 entry = silc_idlist_find_server_by_name(server->global_list,
3567 dest_server, TRUE, NULL);
3569 entry = silc_idlist_find_server_by_name(server->local_list,
3570 dest_server, TRUE, NULL);
3573 if (server->server_type != SILC_SERVER && !cmd->pending &&
3574 entry && !entry->motd) {
3575 /* Send to the server */
3579 old_ident = silc_command_get_ident(cmd->payload);
3580 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3581 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3583 silc_server_packet_send(server, entry->connection,
3584 SILC_PACKET_COMMAND, cmd->packet->flags,
3585 tmpbuf->data, tmpbuf->len, TRUE);
3587 /* Reprocess this packet after received reply from router */
3588 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3589 silc_command_get_ident(cmd->payload),
3590 silc_server_command_destructor,
3591 silc_server_command_motd,
3592 silc_server_command_dup(cmd));
3593 cmd->pending = TRUE;
3594 silc_command_set_ident(cmd->payload, old_ident);
3595 silc_buffer_free(tmpbuf);
3599 if (!entry && !cmd->pending && !server->standalone) {
3600 /* Send to the primary router */
3604 old_ident = silc_command_get_ident(cmd->payload);
3605 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3606 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3608 silc_server_packet_send(server, server->router->connection,
3609 SILC_PACKET_COMMAND, cmd->packet->flags,
3610 tmpbuf->data, tmpbuf->len, TRUE);
3612 /* Reprocess this packet after received reply from router */
3613 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3614 silc_command_get_ident(cmd->payload),
3615 silc_server_command_destructor,
3616 silc_server_command_motd,
3617 silc_server_command_dup(cmd));
3618 cmd->pending = TRUE;
3619 silc_command_set_ident(cmd->payload, old_ident);
3620 silc_buffer_free(tmpbuf);
3625 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3626 SILC_STATUS_ERR_NO_SUCH_SERVER);
3630 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3631 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3632 SILC_STATUS_OK, ident, 2,
3636 strlen(entry->motd) : 0);
3637 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3638 packet->data, packet->len, FALSE);
3639 silc_buffer_free(packet);
3640 silc_buffer_free(idp);
3644 silc_server_command_free(cmd);
3647 /* Server side of command UMODE. Client can use this command to set/unset
3648 user mode. Client actually cannot set itself to be as server/router
3649 operator so this can be used only to unset the modes. */
3651 SILC_SERVER_CMD_FUNC(umode)
3653 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3654 SilcServer server = cmd->server;
3655 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3657 unsigned char *tmp_mask;
3659 uint16 ident = silc_command_get_ident(cmd->payload);
3661 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3664 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 2, 2);
3666 /* Get the client's mode mask */
3667 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3669 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3670 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3673 SILC_GET32_MSB(mask, tmp_mask);
3679 if (mask & SILC_UMODE_SERVER_OPERATOR) {
3680 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR)) {
3681 /* Cannot operator mode */
3682 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3683 SILC_STATUS_ERR_PERM_DENIED);
3687 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
3688 /* Remove the server operator rights */
3689 client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3692 if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3693 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
3694 /* Cannot operator mode */
3695 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3696 SILC_STATUS_ERR_PERM_DENIED);
3700 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
3701 /* Remove the router operator rights */
3702 client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3705 if (mask & SILC_UMODE_GONE) {
3706 client->mode |= SILC_UMODE_GONE;
3708 if (client->mode & SILC_UMODE_GONE)
3709 /* Remove the gone status */
3710 client->mode &= ~SILC_UMODE_GONE;
3713 /* Send UMODE change to primary router */
3714 if (!server->standalone)
3715 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3716 client->id, client->mode);
3718 /* Send command reply to sender */
3719 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3720 SILC_STATUS_OK, ident, 1,
3722 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3723 packet->data, packet->len, FALSE);
3724 silc_buffer_free(packet);
3727 silc_server_command_free(cmd);
3730 /* Checks that client has rights to add or remove channel modes. If any
3731 of the checks fails FALSE is returned. */
3733 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3734 SilcChannelClientEntry client,
3737 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3738 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3740 /* Check whether has rights to change anything */
3741 if (!is_op && !is_fo)
3744 /* Check whether has rights to change everything */
3748 /* We know that client is channel operator, check that they are not
3749 changing anything that requires channel founder rights. Rest of the
3750 modes are available automatically for channel operator. */
3752 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3753 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3754 if (is_op && !is_fo)
3757 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3758 if (is_op && !is_fo)
3763 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3764 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE))
3765 if (is_op && !is_fo)
3768 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3769 if (is_op && !is_fo)
3774 if (mode & SILC_CHANNEL_MODE_CIPHER) {
3775 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER))
3776 if (is_op && !is_fo)
3779 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3780 if (is_op && !is_fo)
3785 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3786 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH))
3787 if (is_op && !is_fo)
3790 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3791 if (is_op && !is_fo)
3799 /* Server side command of CMODE. Changes channel mode */
3801 SILC_SERVER_CMD_FUNC(cmode)
3803 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3804 SilcServer server = cmd->server;
3805 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3806 SilcIDListData idata = (SilcIDListData)client;
3807 SilcChannelID *channel_id;
3808 SilcChannelEntry channel;
3809 SilcChannelClientEntry chl;
3810 SilcBuffer packet, cidp;
3811 unsigned char *tmp, *tmp_id, *tmp_mask;
3812 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3813 uint32 mode_mask, tmp_len, tmp_len2;
3814 uint16 ident = silc_command_get_ident(cmd->payload);
3816 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 2, 7);
3818 /* Get Channel ID */
3819 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3821 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3822 SILC_STATUS_ERR_NO_CHANNEL_ID);
3825 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3827 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3828 SILC_STATUS_ERR_NO_CHANNEL_ID);
3832 /* Get the channel mode mask */
3833 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3835 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3836 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3839 SILC_GET32_MSB(mode_mask, tmp_mask);
3841 /* Get channel entry */
3842 channel = silc_idlist_find_channel_by_id(server->local_list,
3845 channel = silc_idlist_find_channel_by_id(server->global_list,
3848 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3849 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3854 /* Check whether this client is on the channel */
3855 if (!silc_server_client_on_channel(client, channel)) {
3856 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3857 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3861 /* Get entry to the channel user list */
3862 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
3864 /* Check that client has rights to change any requested channel modes */
3865 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3866 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3867 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3872 * Check the modes. Modes that requires nothing special operation are
3876 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3877 /* Channel uses private keys to protect traffic. Client(s) has set the
3878 key locally they want to use, server does not know that key. */
3879 /* Nothing interesting to do here */
3881 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3882 /* The mode is removed and we need to generate and distribute
3883 new channel key. Clients are not using private channel keys
3884 anymore after this. */
3886 /* Re-generate channel key */
3887 if (!silc_server_create_channel_key(server, channel, 0))
3890 /* Send the channel key. This sends it to our local clients and if
3891 we are normal server to our router as well. */
3892 silc_server_send_channel_key(server, NULL, channel,
3893 server->server_type == SILC_ROUTER ?
3894 FALSE : !server->standalone);
3896 cipher = channel->channel_key->cipher->name;
3897 hmac = (char *)silc_hmac_get_name(channel->hmac);
3901 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3902 /* User limit is set on channel */
3905 /* Get user limit */
3906 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3908 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3909 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3910 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3914 SILC_GET32_MSB(user_limit, tmp);
3915 channel->user_limit = user_limit;
3918 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3919 /* User limit mode is unset. Remove user limit */
3920 channel->user_limit = 0;
3923 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3924 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3925 /* Passphrase has been set to channel */
3927 /* Get the passphrase */
3928 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3930 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3931 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3935 /* Save the passphrase */
3936 passphrase = channel->passphrase = strdup(tmp);
3939 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3940 /* Passphrase mode is unset. remove the passphrase */
3941 if (channel->passphrase) {
3942 silc_free(channel->passphrase);
3943 channel->passphrase = NULL;
3948 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3949 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3950 /* Cipher to use protect the traffic */
3951 SilcCipher newkey, oldkey;
3954 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3956 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3957 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3961 /* Delete old cipher and allocate the new one */
3962 if (!silc_cipher_alloc(cipher, &newkey)) {
3963 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3964 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3968 oldkey = channel->channel_key;
3969 channel->channel_key = newkey;
3971 /* Re-generate channel key */
3972 if (!silc_server_create_channel_key(server, channel, 0)) {
3973 /* We don't have new key, revert to old one */
3974 channel->channel_key = oldkey;
3978 /* Remove old channel key for good */
3979 silc_cipher_free(oldkey);
3981 /* Send the channel key. This sends it to our local clients and if
3982 we are normal server to our router as well. */
3983 silc_server_send_channel_key(server, NULL, channel,
3984 server->server_type == SILC_ROUTER ?
3985 FALSE : !server->standalone);
3988 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3989 /* Cipher mode is unset. Remove the cipher and revert back to
3991 SilcCipher newkey, oldkey;
3992 cipher = channel->cipher;
3994 /* Delete old cipher and allocate default one */
3995 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
3996 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3997 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4001 oldkey = channel->channel_key;
4002 channel->channel_key = newkey;
4004 /* Re-generate channel key */
4005 if (!silc_server_create_channel_key(server, channel, 0)) {
4006 /* We don't have new key, revert to old one */
4007 channel->channel_key = oldkey;
4011 /* Remove old channel key for good */
4012 silc_cipher_free(oldkey);
4014 /* Send the channel key. This sends it to our local clients and if
4015 we are normal server to our router as well. */
4016 silc_server_send_channel_key(server, NULL, channel,
4017 server->server_type == SILC_ROUTER ?
4018 FALSE : !server->standalone);
4022 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
4023 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
4024 /* HMAC to use protect the traffic */
4025 unsigned char hash[32];
4029 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4031 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4032 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4036 /* Delete old hmac and allocate the new one */
4037 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4038 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4039 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4043 silc_hmac_free(channel->hmac);
4044 channel->hmac = newhmac;
4046 /* Set the HMAC key out of current channel key. The client must do
4048 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4049 channel->key_len / 8, hash);
4050 silc_hmac_set_key(channel->hmac, hash,
4051 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4052 memset(hash, 0, sizeof(hash));
4055 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4056 /* Hmac mode is unset. Remove the hmac and revert back to
4059 unsigned char hash[32];
4060 hmac = channel->hmac_name;
4062 /* Delete old hmac and allocate default one */
4063 silc_hmac_free(channel->hmac);
4064 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4065 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4066 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4070 silc_hmac_free(channel->hmac);
4071 channel->hmac = newhmac;
4073 /* Set the HMAC key out of current channel key. The client must do
4075 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4076 channel->key_len / 8,
4078 silc_hmac_set_key(channel->hmac, hash,
4079 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4080 memset(hash, 0, sizeof(hash));
4084 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4085 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4086 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4087 /* Set the founder authentication */
4088 SilcAuthPayload auth;
4090 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4092 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4093 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4097 auth = silc_auth_payload_parse(tmp, tmp_len);
4099 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4100 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4104 /* Save the public key */
4105 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
4106 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
4109 channel->founder_method = silc_auth_get_method(auth);
4111 if (channel->founder_method == SILC_AUTH_PASSWORD) {
4112 tmp = silc_auth_get_data(auth, &tmp_len);
4113 channel->founder_passwd =
4114 silc_calloc(tmp_len + 1, sizeof(*channel->founder_passwd));
4115 memcpy(channel->founder_passwd, tmp, tmp_len);
4116 channel->founder_passwd_len = tmp_len;
4118 /* Verify the payload before setting the mode */
4119 if (!silc_auth_verify(auth, channel->founder_method,
4120 channel->founder_key, 0, idata->hash,
4121 client->id, SILC_ID_CLIENT)) {
4122 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4123 SILC_STATUS_ERR_AUTH_FAILED);
4128 silc_auth_payload_free(auth);
4132 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4133 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4134 if (channel->founder_key)
4135 silc_pkcs_public_key_free(channel->founder_key);
4136 if (channel->founder_passwd) {
4137 silc_free(channel->founder_passwd);
4138 channel->founder_passwd = NULL;
4144 /* Finally, set the mode */
4145 channel->mode = mode_mask;
4147 /* Send CMODE_CHANGE notify. */
4148 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4149 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4150 SILC_NOTIFY_TYPE_CMODE_CHANGE, 5,
4151 cidp->data, cidp->len,
4153 cipher, cipher ? strlen(cipher) : 0,
4154 hmac, hmac ? strlen(hmac) : 0,
4155 passphrase, passphrase ?
4156 strlen(passphrase) : 0);
4158 /* Set CMODE notify type to network */
4159 if (!server->standalone)
4160 silc_server_send_notify_cmode(server, server->router->connection,
4161 server->server_type == SILC_ROUTER ?
4162 TRUE : FALSE, channel,
4163 mode_mask, client->id, SILC_ID_CLIENT,
4164 cipher, hmac, passphrase);
4166 /* Send command reply to sender */
4167 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4168 SILC_STATUS_OK, ident, 2,
4169 2, tmp_id, tmp_len2,
4171 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4172 packet->data, packet->len, FALSE);
4174 silc_buffer_free(packet);
4175 silc_free(channel_id);
4176 silc_buffer_free(cidp);
4179 silc_server_command_free(cmd);
4182 /* Server side of CUMODE command. Changes client's mode on a channel. */
4184 SILC_SERVER_CMD_FUNC(cumode)
4186 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4187 SilcServer server = cmd->server;
4188 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4189 SilcIDListData idata = (SilcIDListData)client;
4190 SilcChannelID *channel_id;
4191 SilcClientID *client_id;
4192 SilcChannelEntry channel;
4193 SilcClientEntry target_client;
4194 SilcChannelClientEntry chl;
4195 SilcBuffer packet, idp;
4196 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4197 uint32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4199 uint16 ident = silc_command_get_ident(cmd->payload);
4201 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4203 /* Get Channel ID */
4204 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4206 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4207 SILC_STATUS_ERR_NO_CHANNEL_ID);
4210 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
4212 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4213 SILC_STATUS_ERR_NO_CHANNEL_ID);
4217 /* Get channel entry */
4218 channel = silc_idlist_find_channel_by_id(server->local_list,
4221 channel = silc_idlist_find_channel_by_id(server->global_list,
4224 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4225 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4230 /* Check whether sender is on the channel */
4231 if (!silc_server_client_on_channel(client, channel)) {
4232 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4233 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4237 /* Check that client has rights to change other's rights */
4238 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4239 sender_mask = chl->mode;
4241 /* Get the target client's channel mode mask */
4242 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4244 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4245 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4248 SILC_GET32_MSB(target_mask, tmp_mask);
4250 /* Get target Client ID */
4251 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4253 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4254 SILC_STATUS_ERR_NO_CLIENT_ID);
4257 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
4259 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4260 SILC_STATUS_ERR_NO_CLIENT_ID);
4264 /* Get target client's entry */
4265 target_client = silc_idlist_find_client_by_id(server->local_list,
4266 client_id, TRUE, NULL);
4267 if (!target_client) {
4268 target_client = silc_idlist_find_client_by_id(server->global_list,
4269 client_id, TRUE, NULL);
4272 if (target_client != client &&
4273 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4274 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4275 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4276 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4280 /* Check whether target client is on the channel */
4281 if (target_client != client) {
4282 if (!silc_server_client_on_channel(target_client, channel)) {
4283 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4284 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4288 /* Get entry to the channel user list */
4289 silc_hash_table_find(channel->user_list, target_client, NULL,
4297 /* If the target client is founder, no one else can change their mode
4299 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
4300 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4301 SILC_STATUS_ERR_NOT_YOU);
4305 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4306 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4307 /* The client tries to claim the founder rights. */
4308 unsigned char *tmp_auth;
4309 uint32 tmp_auth_len, auth_len;
4312 if (target_client != client) {
4313 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4314 SILC_STATUS_ERR_NOT_YOU);
4318 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4319 !channel->founder_key || !idata->public_key ||
4320 !silc_pkcs_public_key_compare(channel->founder_key,
4321 idata->public_key)) {
4322 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4323 SILC_STATUS_ERR_NOT_YOU);
4327 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4329 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4330 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4334 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4335 (void *)channel->founder_passwd : (void *)channel->founder_key);
4336 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4337 channel->founder_passwd_len : 0);
4339 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4340 channel->founder_method, auth, auth_len,
4341 idata->hash, client->id, SILC_ID_CLIENT)) {
4342 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4343 SILC_STATUS_ERR_AUTH_FAILED);
4347 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4351 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4352 if (target_client == client) {
4353 /* Remove channel founder rights from itself */
4354 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4357 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4358 SILC_STATUS_ERR_NOT_YOU);
4364 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4365 /* Promote to operator */
4366 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4367 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4368 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4369 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4370 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4374 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4378 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4379 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4380 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4381 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4382 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4386 /* Demote to normal user */
4387 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4392 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4393 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4395 /* Send notify to channel, notify only if mode was actually changed. */
4397 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4398 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4399 idp->data, idp->len,
4403 /* Set CUMODE notify type to network */
4404 if (!server->standalone)
4405 silc_server_send_notify_cumode(server, server->router->connection,
4406 server->server_type == SILC_ROUTER ?
4407 TRUE : FALSE, channel,
4408 target_mask, client->id,
4413 /* Send command reply to sender */
4414 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4415 SILC_STATUS_OK, ident, 3,
4417 3, tmp_ch_id, tmp_ch_len,
4418 4, tmp_id, tmp_len);
4419 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4420 packet->data, packet->len, FALSE);
4422 silc_buffer_free(packet);
4423 silc_free(channel_id);
4424 silc_free(client_id);
4425 silc_buffer_free(idp);
4428 silc_server_command_free(cmd);
4431 /* Server side of KICK command. Kicks client out of channel. */
4433 SILC_SERVER_CMD_FUNC(kick)
4435 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4436 SilcServer server = cmd->server;
4437 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4438 SilcClientEntry target_client;
4439 SilcChannelID *channel_id;
4440 SilcClientID *client_id;
4441 SilcChannelEntry channel;
4442 SilcChannelClientEntry chl;
4444 uint32 tmp_len, target_idp_len;
4445 unsigned char *tmp, *comment, *target_idp;
4447 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4449 /* Get Channel ID */
4450 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4452 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4453 SILC_STATUS_ERR_NO_CHANNEL_ID);
4456 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
4458 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4459 SILC_STATUS_ERR_NO_CHANNEL_ID);
4463 /* Get channel entry */
4464 channel = silc_idlist_find_channel_by_id(server->local_list,
4467 channel = silc_idlist_find_channel_by_id(server->local_list,
4470 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4471 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4476 /* Check whether sender is on the channel */
4477 if (!silc_server_client_on_channel(client, channel)) {
4478 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4479 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4483 /* Check that the kicker is channel operator or channel founder */
4484 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4485 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4486 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4487 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4491 /* Get target Client ID */
4492 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4494 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4495 SILC_STATUS_ERR_NO_CLIENT_ID);
4498 client_id = silc_id_payload_parse_id(target_idp, target_idp_len);
4500 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4501 SILC_STATUS_ERR_NO_CLIENT_ID);
4505 /* Get target client's entry */
4506 target_client = silc_idlist_find_client_by_id(server->local_list,
4507 client_id, TRUE, NULL);
4508 if (!target_client) {
4509 target_client = silc_idlist_find_client_by_id(server->global_list,
4510 client_id, TRUE, NULL);
4513 /* Check that the target client is not channel founder. Channel founder
4514 cannot be kicked from the channel. */
4515 silc_hash_table_find(channel->user_list, target_client, NULL, (void *)&chl);
4516 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4517 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4518 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4522 /* Check whether target client is on the channel */
4523 if (!silc_server_client_on_channel(target_client, channel)) {
4524 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4525 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4531 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4535 /* Send command reply to sender */
4536 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4539 /* Send KICKED notify to local clients on the channel */
4540 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4541 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4542 SILC_NOTIFY_TYPE_KICKED, 3,
4543 target_idp, target_idp_len,
4544 comment, comment ? strlen(comment) : 0,
4545 idp->data, idp->len);
4546 silc_buffer_free(idp);
4548 /* Remove the client from the channel. If the channel does not exist
4549 after removing the client then the client kicked itself off the channel
4550 and we don't have to send anything after that. */
4551 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4552 target_client, FALSE))
4555 /* Send KICKED notify to primary route */
4556 if (!server->standalone)
4557 silc_server_send_notify_kicked(server, server->router->connection,
4558 server->server_type == SILC_ROUTER ?
4559 TRUE : FALSE, channel,
4560 target_client->id, comment);
4562 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4563 /* Re-generate channel key */
4564 if (!silc_server_create_channel_key(server, channel, 0))
4567 /* Send the channel key to the channel. The key of course is not sent
4568 to the client who was kicked off the channel. */
4569 silc_server_send_channel_key(server, target_client->connection, channel,
4570 server->server_type == SILC_ROUTER ?
4571 FALSE : !server->standalone);
4575 silc_server_command_free(cmd);
4578 /* Server side of OPER command. Client uses this comand to obtain server
4579 operator privileges to this server/router. */
4581 SILC_SERVER_CMD_FUNC(oper)
4583 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4584 SilcServer server = cmd->server;
4585 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4586 unsigned char *username, *auth;
4588 SilcServerConfigSectionAdminConnection *admin;
4589 SilcIDListData idata = (SilcIDListData)client;
4591 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4593 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4596 /* Get the username */
4597 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4599 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4600 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4604 /* Get the admin configuration */
4605 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4606 username, client->nickname);
4608 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4609 username, client->nickname);
4611 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4612 SILC_STATUS_ERR_AUTH_FAILED);
4617 /* Get the authentication payload */
4618 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4620 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4621 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4625 /* Verify the authentication data */
4626 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4627 admin->auth_data, admin->auth_data_len,
4628 idata->hash, client->id, SILC_ID_CLIENT)) {
4629 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4630 SILC_STATUS_ERR_AUTH_FAILED);
4634 /* Client is now server operator */
4635 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4637 /* Send UMODE change to primary router */
4638 if (!server->standalone)
4639 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4640 client->id, client->mode);
4642 /* Send reply to the sender */
4643 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4647 silc_server_command_free(cmd);
4650 /* Server side of SILCOPER command. Client uses this comand to obtain router
4651 operator privileges to this router. */
4653 SILC_SERVER_CMD_FUNC(silcoper)
4655 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4656 SilcServer server = cmd->server;
4657 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4658 unsigned char *username, *auth;
4660 SilcServerConfigSectionAdminConnection *admin;
4661 SilcIDListData idata = (SilcIDListData)client;
4663 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4665 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4668 if (server->server_type != SILC_ROUTER) {
4669 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4670 SILC_STATUS_ERR_AUTH_FAILED);
4674 /* Get the username */
4675 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4677 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4678 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4682 /* Get the admin configuration */
4683 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4684 username, client->nickname);
4686 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4687 username, client->nickname);
4689 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4690 SILC_STATUS_ERR_AUTH_FAILED);
4695 /* Get the authentication payload */
4696 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4698 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4699 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4703 /* Verify the authentication data */
4704 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4705 admin->auth_data, admin->auth_data_len,
4706 idata->hash, client->id, SILC_ID_CLIENT)) {
4707 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4708 SILC_STATUS_ERR_AUTH_FAILED);
4712 /* Client is now router operator */
4713 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4715 /* Send UMODE change to primary router */
4716 if (!server->standalone)
4717 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4718 client->id, client->mode);
4720 /* Send reply to the sender */
4721 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4725 silc_server_command_free(cmd);
4728 /* Server side command of CONNECT. Connects us to the specified remote
4729 server or router. */
4731 SILC_SERVER_CMD_FUNC(connect)
4733 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4734 SilcServer server = cmd->server;
4735 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4736 unsigned char *tmp, *host;
4738 uint32 port = SILC_PORT;
4740 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CONNECT, cmd, 1, 2);
4742 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4745 /* Check whether client has the permissions. */
4746 if (client->mode == SILC_UMODE_NONE) {
4747 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4748 SILC_STATUS_ERR_NO_SERVER_PRIV);
4752 if (server->server_type == SILC_ROUTER &&
4753 client->mode & SILC_UMODE_SERVER_OPERATOR) {
4754 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4755 SILC_STATUS_ERR_NO_ROUTER_PRIV);
4759 /* Get the remote server */
4760 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4762 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4763 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4768 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4770 SILC_GET32_MSB(port, tmp);
4772 /* Create the connection. It is done with timeout and is async. */
4773 silc_server_create_connection(server, host, port);
4775 /* Send reply to the sender */
4776 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4780 silc_server_command_free(cmd);
4783 /* Server side of command BAN. This is used to manage the ban list of the
4784 channel. To add clients and remove clients from the ban list. */
4786 SILC_SERVER_CMD_FUNC(ban)
4788 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4789 SilcServer server = cmd->server;
4790 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4792 SilcChannelEntry channel;
4793 SilcChannelClientEntry chl;
4794 SilcChannelID *channel_id = NULL;
4795 unsigned char *id, *add, *del;
4796 uint32 id_len, tmp_len;
4797 uint16 ident = silc_command_get_ident(cmd->payload);
4799 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4802 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4804 /* Get Channel ID */
4805 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4807 channel_id = silc_id_payload_parse_id(id, id_len);
4809 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4810 SILC_STATUS_ERR_NO_CHANNEL_ID);
4815 /* Get channel entry. The server must know about the channel since the
4816 client is expected to be on the channel. */
4817 channel = silc_idlist_find_channel_by_id(server->local_list,
4820 channel = silc_idlist_find_channel_by_id(server->global_list,
4823 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4824 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4829 /* Check whether this client is on the channel */
4830 if (!silc_server_client_on_channel(client, channel)) {
4831 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4832 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4836 /* Get entry to the channel user list */
4837 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4839 /* The client must be at least channel operator. */
4840 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4841 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4842 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4846 /* Get the new ban and add it to the ban list */
4847 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4849 if (!channel->ban_list)
4850 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4852 channel->ban_list = silc_realloc(channel->ban_list,
4853 sizeof(*channel->ban_list) *
4855 strlen(channel->ban_list) + 2));
4856 if (add[tmp_len - 1] == ',')
4857 add[tmp_len - 1] = '\0';
4859 strncat(channel->ban_list, add, tmp_len);
4860 strncat(channel->ban_list, ",", 1);
4863 /* Get the ban to be removed and remove it from the list */
4864 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4865 if (del && channel->ban_list) {
4866 char *start, *end, *n;
4868 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4869 silc_free(channel->ban_list);
4870 channel->ban_list = NULL;
4872 start = strstr(channel->ban_list, del);
4873 if (start && strlen(start) >= tmp_len) {
4874 end = start + tmp_len;
4875 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4876 strncat(n, channel->ban_list, start - channel->ban_list);
4877 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4879 silc_free(channel->ban_list);
4880 channel->ban_list = n;
4885 /* Send the BAN notify type to our primary router. */
4886 if (!server->standalone && (add || del))
4887 silc_server_send_notify_ban(server, server->router->connection,
4888 server->server_type == SILC_ROUTER ?
4889 TRUE : FALSE, channel, add, del);
4891 /* Send the reply back to the client */
4893 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4894 SILC_STATUS_OK, ident, 2,
4896 3, channel->ban_list,
4898 strlen(channel->ban_list) - 1 : 0);
4899 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4900 packet->data, packet->len, FALSE);
4902 silc_buffer_free(packet);
4905 silc_free(channel_id);
4906 silc_server_command_free(cmd);
4909 /* Server side command of CLOSE. Closes connection to a specified server. */
4911 SILC_SERVER_CMD_FUNC(close)
4913 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4914 SilcServer server = cmd->server;
4915 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4916 SilcServerEntry server_entry;
4917 SilcSocketConnection sock;
4920 unsigned char *name;
4921 uint32 port = SILC_PORT;
4923 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CLOSE, cmd, 1, 2);
4925 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4928 /* Check whether client has the permissions. */
4929 if (client->mode == SILC_UMODE_NONE) {
4930 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4931 SILC_STATUS_ERR_NO_SERVER_PRIV);
4935 /* Get the remote server */
4936 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4938 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4939 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4944 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4946 SILC_GET32_MSB(port, tmp);
4948 server_entry = silc_idlist_find_server_by_conn(server->local_list,
4949 name, port, FALSE, NULL);
4951 server_entry = silc_idlist_find_server_by_conn(server->global_list,
4952 name, port, FALSE, NULL);
4953 if (!server_entry) {
4954 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4955 SILC_STATUS_ERR_NO_SERVER_ID);
4959 /* Send reply to the sender */
4960 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4963 /* Close the connection to the server */
4964 sock = (SilcSocketConnection)server_entry->connection;
4966 /* If we shutdown primary router connection manually then don't trigger
4967 any reconnect or backup router connections, by setting the router
4969 if (server->router == server_entry) {
4970 server->id_entry->router = NULL;
4971 server->router = NULL;
4972 server->standalone = TRUE;
4974 silc_server_free_sock_user_data(server, sock);
4975 silc_server_close_connection(server, sock);
4978 silc_server_command_free(cmd);
4981 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4982 active connections. */
4984 SILC_SERVER_CMD_FUNC(shutdown)
4986 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4987 SilcServer server = cmd->server;
4988 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4990 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4992 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4995 /* Check whether client has the permission. */
4996 if (client->mode == SILC_UMODE_NONE) {
4997 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4998 SILC_STATUS_ERR_NO_SERVER_PRIV);
5002 /* Send reply to the sender */
5003 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
5006 /* Then, gracefully, or not, bring the server down. */
5007 silc_server_stop(server);
5011 silc_server_command_free(cmd);
5014 /* Server side command of LEAVE. Removes client from a channel. */
5016 SILC_SERVER_CMD_FUNC(leave)
5018 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5019 SilcServer server = cmd->server;
5020 SilcSocketConnection sock = cmd->sock;
5021 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
5022 SilcChannelID *id = NULL;
5023 SilcChannelEntry channel;
5027 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
5029 /* Get Channel ID */
5030 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
5032 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5033 SILC_STATUS_ERR_NO_CHANNEL_ID);
5036 id = silc_id_payload_parse_id(tmp, len);
5038 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5039 SILC_STATUS_ERR_NO_CHANNEL_ID);
5043 /* Get channel entry */
5044 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5046 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5048 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5049 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5054 /* Check whether this client is on the channel */
5055 if (!silc_server_client_on_channel(id_entry, channel)) {
5056 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5057 SILC_STATUS_ERR_NOT_ON_CHANNEL);
5061 /* Notify routers that they should remove this client from their list
5062 of clients on the channel. Send LEAVE notify type. */
5063 if (!server->standalone)
5064 silc_server_send_notify_leave(server, server->router->connection,
5065 server->server_type == SILC_ROUTER ?
5066 TRUE : FALSE, channel, id_entry->id);
5068 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5071 /* Remove client from channel */
5072 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5074 /* If the channel does not exist anymore we won't send anything */
5077 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5078 /* Re-generate channel key */
5079 if (!silc_server_create_channel_key(server, channel, 0))
5082 /* Send the channel key */
5083 silc_server_send_channel_key(server, NULL, channel,
5084 server->server_type == SILC_ROUTER ?
5085 FALSE : !server->standalone);
5090 silc_server_command_free(cmd);
5093 /* Server side of command USERS. Resolves clients and their USERS currently
5094 joined on the requested channel. The list of Client ID's and their modes
5095 on the channel is sent back. */
5097 SILC_SERVER_CMD_FUNC(users)
5099 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5100 SilcServer server = cmd->server;
5101 SilcChannelEntry channel;
5102 SilcChannelID *id = NULL;
5103 SilcBuffer packet, idp;
5104 unsigned char *channel_id;
5105 uint32 channel_id_len;
5106 SilcBuffer client_id_list;
5107 SilcBuffer client_mode_list;
5108 unsigned char lc[4];
5109 uint32 list_count = 0;
5110 uint16 ident = silc_command_get_ident(cmd->payload);
5113 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5115 /* Get Channel ID */
5116 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5118 /* Get channel name */
5119 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5121 if (!channel_id && !channel_name) {
5122 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5123 SILC_STATUS_ERR_NO_CHANNEL_ID);
5128 id = silc_id_payload_parse_id(channel_id, channel_id_len);
5130 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5131 SILC_STATUS_ERR_NO_CHANNEL_ID);
5136 /* If we are server and we don't know about this channel we will send
5137 the command to our router. If we know about the channel then we also
5138 have the list of users already. */
5140 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5142 channel = silc_idlist_find_channel_by_name(server->local_list,
5143 channel_name, NULL);
5145 if (!channel || channel->disabled) {
5146 if (server->server_type != SILC_ROUTER && !server->standalone &&
5150 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5151 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5153 /* Send USERS command */
5154 silc_server_packet_send(server, server->router->connection,
5155 SILC_PACKET_COMMAND, cmd->packet->flags,
5156 tmpbuf->data, tmpbuf->len, TRUE);
5158 /* Reprocess this packet after received reply */
5159 silc_server_command_pending(server, SILC_COMMAND_USERS,
5160 silc_command_get_ident(cmd->payload),
5161 silc_server_command_destructor,
5162 silc_server_command_users,
5163 silc_server_command_dup(cmd));
5164 cmd->pending = TRUE;
5165 silc_command_set_ident(cmd->payload, ident);
5167 silc_buffer_free(tmpbuf);
5172 /* Check the global list as well. */
5174 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5176 channel = silc_idlist_find_channel_by_name(server->global_list,
5177 channel_name, NULL);
5179 /* Channel really does not exist */
5180 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5181 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5186 /* If the channel is private or secret do not send anything, unless the
5187 user requesting this command is on the channel. */
5188 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5189 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5190 && !silc_server_client_on_channel(cmd->sock->user_data, channel)) {
5191 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5192 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5197 (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
5198 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5199 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5204 /* Get the users list */
5205 silc_server_get_users_on_channel(server, channel, &client_id_list,
5206 &client_mode_list, &list_count);
5209 SILC_PUT32_MSB(list_count, lc);
5212 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5213 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5214 SILC_STATUS_OK, ident, 4,
5215 2, idp->data, idp->len,
5217 4, client_id_list->data,
5218 client_id_list->len,
5219 5, client_mode_list->data,
5220 client_mode_list->len);
5221 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5222 packet->data, packet->len, FALSE);
5224 silc_buffer_free(idp);
5225 silc_buffer_free(packet);
5226 silc_buffer_free(client_id_list);
5227 silc_buffer_free(client_mode_list);
5231 silc_server_command_free(cmd);
5234 /* Server side of command GETKEY. This fetches the client's public key
5235 from the server where to the client is connected. */
5237 SILC_SERVER_CMD_FUNC(getkey)
5239 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5240 SilcServer server = cmd->server;
5242 SilcClientEntry client;
5243 SilcServerEntry server_entry;
5244 SilcClientID *client_id = NULL;
5245 SilcServerID *server_id = NULL;
5246 SilcIDPayload idp = NULL;
5247 uint16 ident = silc_command_get_ident(cmd->payload);
5248 unsigned char *tmp, *pkdata;
5249 uint32 tmp_len, pklen;
5250 SilcBuffer pk = NULL;
5253 SILC_LOG_DEBUG(("Start"));
5255 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5257 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5258 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5261 idp = silc_id_payload_parse(tmp, tmp_len);
5263 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5264 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5268 id_type = silc_id_payload_get_type(idp);
5269 if (id_type == SILC_ID_CLIENT) {
5270 client_id = silc_id_payload_get_id(idp);
5272 /* If the client is not found from local list there is no chance it
5273 would be locally connected client so send the command further. */
5274 client = silc_idlist_find_client_by_id(server->local_list,
5275 client_id, TRUE, NULL);
5277 client = silc_idlist_find_client_by_id(server->global_list,
5278 client_id, TRUE, NULL);
5280 if ((!client && !cmd->pending && !server->standalone) ||
5281 (client && !client->connection && !cmd->pending) ||
5282 (client && !client->data.public_key && !cmd->pending)) {
5285 SilcSocketConnection dest_sock;
5287 dest_sock = silc_server_get_client_route(server, NULL, 0,
5292 old_ident = silc_command_get_ident(cmd->payload);
5293 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5294 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5296 silc_server_packet_send(server, dest_sock,
5297 SILC_PACKET_COMMAND, cmd->packet->flags,
5298 tmpbuf->data, tmpbuf->len, TRUE);
5300 /* Reprocess this packet after received reply from router */
5301 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5302 silc_command_get_ident(cmd->payload),
5303 silc_server_command_destructor,
5304 silc_server_command_getkey,
5305 silc_server_command_dup(cmd));
5306 cmd->pending = TRUE;
5308 silc_command_set_ident(cmd->payload, old_ident);
5309 silc_buffer_free(tmpbuf);
5314 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5315 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5319 /* The client is locally connected, just get the public key and
5320 send it back. If they key does not exist then do not send it,
5321 send just OK reply */
5322 if (!client->data.public_key) {
5326 tmp = silc_pkcs_public_key_encode(client->data.public_key, &tmp_len);
5327 pk = silc_buffer_alloc(4 + tmp_len);
5328 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5329 silc_buffer_format(pk,
5330 SILC_STR_UI_SHORT(tmp_len),
5331 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5332 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5338 } else if (id_type == SILC_ID_SERVER) {
5339 server_id = silc_id_payload_get_id(idp);
5341 /* If the server is not found from local list there is no chance it
5342 would be locally connected server so send the command further. */
5343 server_entry = silc_idlist_find_server_by_id(server->local_list,
5344 server_id, TRUE, NULL);
5346 server_entry = silc_idlist_find_server_by_id(server->global_list,
5347 server_id, TRUE, NULL);
5349 if (server_entry != server->id_entry &&
5350 ((!server_entry && !cmd->pending && !server->standalone) ||
5351 (server_entry && !server_entry->connection && !cmd->pending &&
5352 !server->standalone) ||
5353 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5354 !server->standalone))) {
5358 old_ident = silc_command_get_ident(cmd->payload);
5359 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5360 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5362 silc_server_packet_send(server, server->router->connection,
5363 SILC_PACKET_COMMAND, cmd->packet->flags,
5364 tmpbuf->data, tmpbuf->len, TRUE);
5366 /* Reprocess this packet after received reply from router */
5367 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5368 silc_command_get_ident(cmd->payload),
5369 silc_server_command_destructor,
5370 silc_server_command_getkey,
5371 silc_server_command_dup(cmd));
5372 cmd->pending = TRUE;
5374 silc_command_set_ident(cmd->payload, old_ident);
5375 silc_buffer_free(tmpbuf);
5379 if (!server_entry) {
5380 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5381 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5385 /* If they key does not exist then do not send it, send just OK reply */
5386 if (!server_entry->data.public_key) {
5390 tmp = silc_pkcs_public_key_encode(server_entry->data.public_key,
5392 pk = silc_buffer_alloc(4 + tmp_len);
5393 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5394 silc_buffer_format(pk,
5395 SILC_STR_UI_SHORT(tmp_len),
5396 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5397 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5407 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5408 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5409 SILC_STATUS_OK, ident,
5413 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5414 packet->data, packet->len, FALSE);
5415 silc_buffer_free(packet);
5418 silc_buffer_free(pk);
5422 silc_id_payload_free(idp);
5423 silc_free(client_id);
5424 silc_free(server_id);
5425 silc_server_command_free(cmd);