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,
40 SILC_TASK_CALLBACK(silc_server_command_process_timeout);
42 /* Server command list. */
43 SilcServerCommand silc_command_list[] =
45 SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
46 SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
47 SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
48 SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
49 SILC_SERVER_CMD(list, LIST, SILC_CF_LAG_STRICT | SILC_CF_REG),
50 SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
51 SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
52 SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
53 SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG_STRICT | SILC_CF_REG | SILC_CF_OPER),
54 SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
55 SILC_SERVER_CMD(connect, CONNECT,
56 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
57 SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
58 SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
59 SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG_STRICT | SILC_CF_REG),
60 SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
61 SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
62 SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG_STRICT | SILC_CF_REG),
63 SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
64 SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
65 SILC_SERVER_CMD(ban, BAN, SILC_CF_LAG_STRICT | SILC_CF_REG),
66 SILC_SERVER_CMD(close, CLOSE,
67 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
68 SILC_SERVER_CMD(shutdown, SHUTDOWN, SILC_CF_LAG | SILC_CF_REG |
70 SILC_SERVER_CMD(silcoper, SILCOPER,
71 SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
72 SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
73 SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
74 SILC_SERVER_CMD(getkey, GETKEY, SILC_CF_LAG | SILC_CF_REG),
79 #define SILC_SERVER_COMMAND_CHECK_ARGC(command, context, min, max) \
81 uint32 _argc = silc_argument_get_arg_num(cmd->args); \
83 SILC_LOG_DEBUG(("Start")); \
86 silc_server_command_send_status_reply(cmd, command, \
87 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
88 silc_server_command_free(cmd); \
92 silc_server_command_send_status_reply(cmd, command, \
93 SILC_STATUS_ERR_TOO_MANY_PARAMS); \
94 silc_server_command_free(cmd); \
99 /* Returns TRUE if the connection is registered. Unregistered connections
100 usually cannot send commands hence the check. */
102 static int silc_server_is_registered(SilcServer server,
103 SilcSocketConnection sock,
104 SilcServerCommandContext cmd,
107 SilcIDListData idata = (SilcIDListData)sock->user_data;
108 if (idata->registered)
111 silc_server_command_send_status_reply(cmd, command,
112 SILC_STATUS_ERR_NOT_REGISTERED);
113 silc_server_command_free(cmd);
117 /* Internal context to hold data when executed command with timeout. */
119 SilcServerCommandContext ctx;
120 SilcServerCommand *cmd;
121 } *SilcServerCommandTimeout;
123 /* Timeout callback to process commands with timeout for client. Client's
124 commands are always executed with timeout. */
126 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
128 SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
129 SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data;
131 /* Update access time */
132 client->last_command = time(NULL);
134 if (!(timeout->cmd->flags & SILC_CF_REG))
135 timeout->cmd->cb(timeout->ctx);
136 else if (silc_server_is_registered(timeout->ctx->server,
140 timeout->cmd->cb(timeout->ctx);
145 /* Processes received command packet. */
147 void silc_server_command_process(SilcServer server,
148 SilcSocketConnection sock,
149 SilcPacketContext *packet)
151 SilcServerCommandContext ctx;
152 SilcServerCommand *cmd;
155 /* Allocate command context. This must be free'd by the
156 command routine receiving it. */
157 ctx = silc_server_command_alloc();
158 ctx->server = server;
159 ctx->sock = silc_socket_dup(sock);
160 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
162 /* Parse the command payload in the packet */
163 ctx->payload = silc_command_payload_parse(packet->buffer);
165 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
166 silc_buffer_free(packet->buffer);
167 silc_packet_context_free(packet);
168 silc_socket_free(ctx->sock);
172 ctx->args = silc_command_get_args(ctx->payload);
174 /* Get the command */
175 command = silc_command_get(ctx->payload);
176 for (cmd = silc_command_list; cmd->cb; cmd++)
177 if (cmd->cmd == command)
181 silc_server_command_send_status_reply(ctx, command,
182 SILC_STATUS_ERR_UNKNOWN_COMMAND);
183 silc_server_command_free(ctx);
187 /* Execute client's commands always with timeout. Normally they are
188 executed with zero (0) timeout but if client is sending command more
189 frequently than once in 2 seconds, then the timeout may be 0 to 2
191 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
192 SilcClientEntry client = (SilcClientEntry)sock->user_data;
193 SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
199 if (client->last_command && (time(NULL) - client->last_command) < 2) {
200 client->fast_command++;
203 client->fast_command = ((client->fast_command - 1) <= 0 ? 0 :
204 client->fast_command--);
208 if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
209 (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
210 silc_task_register(server->timeout_queue, sock->sock,
211 silc_server_command_process_timeout,
213 2 - (time(NULL) - client->last_command), 0,
215 SILC_TASK_PRI_NORMAL);
217 silc_task_register(server->timeout_queue, sock->sock,
218 silc_server_command_process_timeout,
222 SILC_TASK_PRI_NORMAL);
226 /* Execute for server */
228 if (!(cmd->flags & SILC_CF_REG))
230 else if (silc_server_is_registered(server, sock, ctx, cmd->cmd))
234 /* Allocate Command Context */
236 SilcServerCommandContext silc_server_command_alloc()
238 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
243 /* Free's the command context allocated before executing the command */
245 void silc_server_command_free(SilcServerCommandContext ctx)
248 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
250 if (ctx->users < 1) {
252 silc_command_free_payload(ctx->payload);
254 silc_packet_context_free(ctx->packet);
256 silc_socket_free(ctx->sock); /* Decrease reference counter */
261 /* Duplicate Command Context by adding reference counter. The context won't
262 be free'd untill it hits zero. */
264 SilcServerCommandContext
265 silc_server_command_dup(SilcServerCommandContext ctx)
268 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
273 /* Add new pending command to be executed when reply to a command has been
274 received. The `reply_cmd' is the command that will call the `callback'
275 with `context' when reply has been received. If `ident' is non-zero
276 the `callback' will be executed when received reply with command
277 identifier `ident'. */
279 void silc_server_command_pending(SilcServer server,
280 SilcCommand reply_cmd,
282 SilcServerPendingDestructor destructor,
283 SilcCommandCb callback,
286 SilcServerCommandPending *reply;
288 reply = silc_calloc(1, sizeof(*reply));
289 reply->reply_cmd = reply_cmd;
290 reply->ident = ident;
291 reply->context = context;
292 reply->callback = callback;
293 reply->destructor = destructor;
294 silc_dlist_add(server->pending_commands, reply);
297 /* Deletes pending command by reply command type. */
299 void silc_server_command_pending_del(SilcServer server,
300 SilcCommand reply_cmd,
303 SilcServerCommandPending *r;
305 silc_dlist_start(server->pending_commands);
306 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
307 if (r->reply_cmd == reply_cmd && r->ident == ident) {
308 silc_dlist_del(server->pending_commands, r);
314 /* Checks for pending commands and marks callbacks to be called from
315 the command reply function. Returns TRUE if there were pending command. */
317 int silc_server_command_pending_check(SilcServer server,
318 SilcServerCommandReplyContext ctx,
322 SilcServerCommandPending *r;
324 silc_dlist_start(server->pending_commands);
325 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
326 if (r->reply_cmd == command && r->ident == ident) {
327 ctx->context = r->context;
328 ctx->callback = r->callback;
329 ctx->destructor = r->destructor;
338 /* Destructor function for pending callbacks. This is called when using
339 pending commands to free the context given for the pending command. */
341 static void silc_server_command_destructor(void *context)
343 silc_server_command_free((SilcServerCommandContext)context);
346 /* Sends simple status message as command reply packet */
349 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
351 SilcCommandStatus status)
355 SILC_LOG_DEBUG(("Sending command status %d", status));
358 silc_command_reply_payload_encode_va(command, status,
359 silc_command_get_ident(cmd->payload),
361 silc_server_packet_send(cmd->server, cmd->sock,
362 SILC_PACKET_COMMAND_REPLY, 0,
363 buffer->data, buffer->len, FALSE);
364 silc_buffer_free(buffer);
367 /* Sends command status reply with one extra argument. The argument
368 type must be sent as argument. */
371 silc_server_command_send_status_data(SilcServerCommandContext cmd,
373 SilcCommandStatus status,
380 SILC_LOG_DEBUG(("Sending command status %d", status));
383 silc_command_reply_payload_encode_va(command, status,
384 silc_command_get_ident(cmd->payload),
385 1, arg_type, arg, arg_len);
386 silc_server_packet_send(cmd->server, cmd->sock,
387 SILC_PACKET_COMMAND_REPLY, 0,
388 buffer->data, buffer->len, FALSE);
389 silc_buffer_free(buffer);
392 /******************************************************************************
396 ******************************************************************************/
399 silc_server_command_whois_parse(SilcServerCommandContext cmd,
400 SilcClientID ***client_id,
401 uint32 *client_id_count,
409 uint32 argc = silc_argument_get_arg_num(cmd->args);
412 /* If client ID is in the command it must be used instead of nickname */
413 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
415 /* No ID, get the nickname@server string and parse it. */
416 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
418 if (strchr(tmp, '@')) {
419 len = strcspn(tmp, "@");
420 *nickname = silc_calloc(len + 1, sizeof(char));
421 memcpy(*nickname, tmp, len);
422 *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
423 memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
425 *nickname = strdup(tmp);
428 silc_server_command_send_status_reply(cmd, command,
429 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
433 /* Command includes ID, we must use that. Also check whether the command
434 has more than one ID set - take them all. */
436 *client_id = silc_calloc(1, sizeof(**client_id));
437 (*client_id)[0] = silc_id_payload_parse_id(tmp, len);
438 if ((*client_id)[0] == NULL) {
439 silc_free(*client_id);
442 *client_id_count = 1;
444 /* Take all ID's from the command packet */
446 for (k = 1, i = 1; i < argc; i++) {
447 tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
449 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
450 (*client_id_count + 1));
451 (*client_id)[k] = silc_id_payload_parse_id(tmp, len);
452 if ((*client_id)[k] == NULL) {
453 /* Cleanup all and fail */
454 for (i = 0; i < *client_id_count; i++)
455 silc_free((*client_id)[i]);
456 silc_free(*client_id);
459 (*client_id_count)++;
465 /* Command includes ID, use that */
468 /* Get the max count of reply messages allowed */
469 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
479 silc_server_command_whois_check(SilcServerCommandContext cmd,
480 SilcClientEntry *clients,
481 uint32 clients_count)
483 SilcServer server = cmd->server;
485 SilcClientEntry entry;
487 for (i = 0; i < clients_count; i++) {
490 if (!entry || entry->data.registered == FALSE)
493 if (!entry->nickname || !entry->username || !entry->userinfo) {
500 old_ident = silc_command_get_ident(cmd->payload);
501 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
502 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
504 /* Send WHOIS command */
505 silc_server_packet_send(server, entry->router->connection,
506 SILC_PACKET_COMMAND, cmd->packet->flags,
507 tmpbuf->data, tmpbuf->len, TRUE);
509 /* Reprocess this packet after received reply */
510 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
511 silc_command_get_ident(cmd->payload),
512 silc_server_command_destructor,
513 silc_server_command_whois,
514 silc_server_command_dup(cmd));
517 silc_command_set_ident(cmd->payload, old_ident);
519 silc_buffer_free(tmpbuf);
528 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
529 SilcClientEntry *clients,
530 uint32 clients_count,
533 SilcServer server = cmd->server;
536 SilcBuffer packet, idp, channels;
537 SilcClientEntry entry;
538 SilcCommandStatus status;
539 uint16 ident = silc_command_get_ident(cmd->payload);
540 char nh[128], uh[128];
541 unsigned char idle[4], mode[4];
542 SilcSocketConnection hsock;
545 for (i = 0; i < clients_count; i++)
546 if (clients[i]->data.registered)
549 status = SILC_STATUS_OK;
551 status = SILC_STATUS_LIST_START;
553 for (i = 0, k = 0; i < clients_count; i++) {
556 if (entry->data.registered == FALSE) {
557 if (clients_count == 1) {
558 SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
559 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
560 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
561 2, idp->data, idp->len);
562 silc_buffer_free(idp);
568 status = SILC_STATUS_LIST_ITEM;
570 if (clients_count > 1 && k == clients_count - 1)
571 status = SILC_STATUS_LIST_END;
573 if (count && k - 1 == count)
574 status = SILC_STATUS_LIST_END;
576 if (count && k - 1 > count)
579 /* Sanity check, however these should never fail. However, as
580 this sanity check has been added here they have failed. */
581 if (!entry->nickname || !entry->username || !entry->userinfo)
584 /* Send WHOIS reply */
585 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
586 tmp = silc_argument_get_first_arg(cmd->args, NULL);
588 memset(uh, 0, sizeof(uh));
589 memset(nh, 0, sizeof(nh));
590 memset(idle, 0, sizeof(idle));
592 strncat(nh, entry->nickname, strlen(entry->nickname));
593 if (!strchr(entry->nickname, '@')) {
595 if (entry->servername) {
596 strncat(nh, entry->servername, strlen(entry->servername));
598 len = entry->router ? strlen(entry->router->server_name) :
599 strlen(server->server_name);
600 strncat(nh, entry->router ? entry->router->server_name :
601 server->server_name, len);
605 strncat(uh, entry->username, strlen(entry->username));
606 if (!strchr(entry->username, '@')) {
608 hsock = (SilcSocketConnection)entry->connection;
609 len = strlen(hsock->hostname);
610 strncat(uh, hsock->hostname, len);
613 channels = silc_server_get_client_channel_list(server, entry);
615 SILC_PUT32_MSB(entry->mode, mode);
617 if (entry->connection) {
618 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
622 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
624 2, idp->data, idp->len,
628 strlen(entry->userinfo),
634 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
636 2, idp->data, idp->len,
640 strlen(entry->userinfo),
644 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
645 0, packet->data, packet->len, FALSE);
647 silc_buffer_free(packet);
648 silc_buffer_free(idp);
650 silc_buffer_free(channels);
657 silc_server_command_whois_from_client(SilcServerCommandContext cmd)
659 SilcServer server = cmd->server;
660 char *nick = NULL, *server_name = NULL;
662 SilcClientEntry *clients = NULL, entry;
663 SilcClientID **client_id = NULL;
664 uint32 client_id_count = 0, clients_count = 0;
667 /* Protocol dictates that we must always send the received WHOIS request
668 to our router if we are normal server, so let's do it now unless we
669 are standalone. We will not send any replies to the client until we
670 have received reply from the router. */
671 if (server->server_type == SILC_SERVER && !cmd->pending &&
672 !server->standalone) {
676 old_ident = silc_command_get_ident(cmd->payload);
677 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
678 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
680 /* Send WHOIS command to our router */
681 silc_server_packet_send(server, (SilcSocketConnection)
682 server->router->connection,
683 SILC_PACKET_COMMAND, cmd->packet->flags,
684 tmpbuf->data, tmpbuf->len, TRUE);
686 /* Reprocess this packet after received reply from router */
687 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
688 silc_command_get_ident(cmd->payload),
689 silc_server_command_destructor,
690 silc_server_command_whois,
691 silc_server_command_dup(cmd));
694 silc_command_set_ident(cmd->payload, old_ident);
696 silc_buffer_free(tmpbuf);
701 /* We are ready to process the command request. Let's search for the
702 requested client and send reply to the requesting client. */
704 /* Parse the whois request */
705 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
706 &nick, &server_name, &count,
710 /* Get all clients matching that ID or nickname from local list */
711 if (client_id_count) {
712 /* Check all Client ID's received in the command packet */
713 for (i = 0; i < client_id_count; i++) {
714 entry = silc_idlist_find_client_by_id(server->local_list,
717 clients = silc_realloc(clients, sizeof(*clients) *
718 (clients_count + 1));
719 clients[clients_count++] = entry;
723 if (!silc_idlist_get_clients_by_hash(server->local_list,
724 nick, server->md5hash,
725 &clients, &clients_count))
726 silc_idlist_get_clients_by_nickname(server->local_list,
728 &clients, &clients_count);
731 /* Check global list as well */
732 if (client_id_count) {
733 /* Check all Client ID's received in the command packet */
734 for (i = 0; i < client_id_count; i++) {
735 entry = silc_idlist_find_client_by_id(server->global_list,
738 clients = silc_realloc(clients, sizeof(*clients) *
739 (clients_count + 1));
740 clients[clients_count++] = entry;
744 if (!silc_idlist_get_clients_by_hash(server->global_list,
745 nick, server->md5hash,
746 &clients, &clients_count))
747 silc_idlist_get_clients_by_nickname(server->global_list,
749 &clients, &clients_count);
753 /* Such client(s) really does not exist in the SILC network. */
754 if (!client_id_count) {
755 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
756 SILC_STATUS_ERR_NO_SUCH_NICK,
757 3, nick, strlen(nick));
759 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
760 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
761 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
762 2, idp->data, idp->len);
763 silc_buffer_free(idp);
768 /* Router always finds the client entry if it exists in the SILC network.
769 However, it might be incomplete entry and does not include all the
770 mandatory fields that WHOIS command reply requires. Check for these and
771 make query from the server who owns the client if some fields are
773 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
778 /* Send the command reply to the client */
779 silc_server_command_whois_send_reply(cmd, clients, clients_count,
783 if (client_id_count) {
784 for (i = 0; i < client_id_count; i++)
785 silc_free(client_id[i]);
786 silc_free(client_id);
793 silc_free(server_name);
799 silc_server_command_whois_from_server(SilcServerCommandContext cmd)
801 SilcServer server = cmd->server;
802 char *nick = NULL, *server_name = NULL;
804 SilcClientEntry *clients = NULL, entry;
805 SilcClientID **client_id = NULL;
806 uint32 client_id_count = 0, clients_count = 0;
809 /* Parse the whois request */
810 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
811 &nick, &server_name, &count,
815 /* Process the command request. Let's search for the requested client and
816 send reply to the requesting server. */
818 if (client_id_count) {
819 /* Check all Client ID's received in the command packet */
820 for (i = 0; i < client_id_count; i++) {
821 entry = silc_idlist_find_client_by_id(server->local_list,
824 clients = silc_realloc(clients, sizeof(*clients) *
825 (clients_count + 1));
826 clients[clients_count++] = entry;
830 if (!silc_idlist_get_clients_by_hash(server->local_list,
831 nick, server->md5hash,
832 &clients, &clients_count))
833 silc_idlist_get_clients_by_nickname(server->local_list,
835 &clients, &clients_count);
838 /* If we are router we will check our global list as well. */
839 if (server->server_type == SILC_ROUTER) {
840 if (client_id_count) {
841 /* Check all Client ID's received in the command packet */
842 for (i = 0; i < client_id_count; i++) {
843 entry = silc_idlist_find_client_by_id(server->global_list,
846 clients = silc_realloc(clients, sizeof(*clients) *
847 (clients_count + 1));
848 clients[clients_count++] = entry;
852 if (!silc_idlist_get_clients_by_hash(server->global_list,
853 nick, server->md5hash,
854 &clients, &clients_count))
855 silc_idlist_get_clients_by_nickname(server->global_list,
857 &clients, &clients_count);
862 /* Such a client really does not exist in the SILC network. */
863 if (!client_id_count) {
864 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
865 SILC_STATUS_ERR_NO_SUCH_NICK,
866 3, nick, strlen(nick));
868 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
869 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
870 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
871 2, idp->data, idp->len);
872 silc_buffer_free(idp);
877 /* Router always finds the client entry if it exists in the SILC network.
878 However, it might be incomplete entry and does not include all the
879 mandatory fields that WHOIS command reply requires. Check for these and
880 make query from the server who owns the client if some fields are
882 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
887 /* Send the command reply to the client */
888 silc_server_command_whois_send_reply(cmd, clients, clients_count,
892 if (client_id_count) {
893 for (i = 0; i < client_id_count; i++)
894 silc_free(client_id[i]);
895 silc_free(client_id);
902 silc_free(server_name);
907 /* Server side of command WHOIS. Processes user's query and sends found
908 results as command replies back to the client. */
910 SILC_SERVER_CMD_FUNC(whois)
912 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
915 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOIS, cmd, 1, 3328);
917 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
918 ret = silc_server_command_whois_from_client(cmd);
919 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
920 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
921 ret = silc_server_command_whois_from_server(cmd);
924 silc_server_command_free(cmd);
927 /******************************************************************************
931 ******************************************************************************/
934 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
942 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
944 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
945 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
949 /* Get the nickname@server string and parse it. */
950 if (strchr(tmp, '@')) {
951 len = strcspn(tmp, "@");
952 *nickname = silc_calloc(len + 1, sizeof(char));
953 memcpy(*nickname, tmp, len);
954 *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
955 memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
957 *nickname = strdup(tmp);
959 /* Get the max count of reply messages allowed */
960 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
970 silc_server_command_whowas_check(SilcServerCommandContext cmd,
971 SilcClientEntry *clients,
972 uint32 clients_count)
974 SilcServer server = cmd->server;
976 SilcClientEntry entry;
978 for (i = 0; i < clients_count; i++) {
981 if (!entry->nickname || !entry->username) {
988 old_ident = silc_command_get_ident(cmd->payload);
989 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
990 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
992 /* Send WHOWAS command */
993 silc_server_packet_send(server, entry->router->connection,
994 SILC_PACKET_COMMAND, cmd->packet->flags,
995 tmpbuf->data, tmpbuf->len, TRUE);
997 /* Reprocess this packet after received reply */
998 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
999 silc_command_get_ident(cmd->payload),
1000 silc_server_command_destructor,
1001 silc_server_command_whowas,
1002 silc_server_command_dup(cmd));
1003 cmd->pending = TRUE;
1005 silc_command_set_ident(cmd->payload, old_ident);
1007 silc_buffer_free(tmpbuf);
1016 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1017 SilcClientEntry *clients,
1018 uint32 clients_count)
1020 SilcServer server = cmd->server;
1022 int i, count = 0, len;
1023 SilcBuffer packet, idp;
1024 SilcClientEntry entry = NULL;
1025 SilcCommandStatus status;
1026 uint16 ident = silc_command_get_ident(cmd->payload);
1028 char nh[256], uh[256];
1030 status = SILC_STATUS_OK;
1031 if (clients_count > 1)
1032 status = SILC_STATUS_LIST_START;
1034 for (i = 0; i < clients_count; i++) {
1037 /* We will take only clients that are not valid anymore. They are the
1038 ones that are not registered anymore but still have a ID. They
1039 have disconnected us, and thus valid for WHOWAS. */
1040 if (entry->data.registered == TRUE)
1042 if (entry->id == NULL)
1045 if (count && i - 1 == count)
1050 if (clients_count > 2)
1051 status = SILC_STATUS_LIST_ITEM;
1053 if (clients_count > 1 && i == clients_count - 1)
1054 status = SILC_STATUS_LIST_END;
1056 /* Sanity check, however these should never fail. However, as
1057 this sanity check has been added here they have failed. */
1058 if (!entry->nickname || !entry->username)
1061 /* Send WHOWAS reply */
1062 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1063 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1065 memset(uh, 0, sizeof(uh));
1066 memset(nh, 0, sizeof(nh));
1068 strncat(nh, entry->nickname, strlen(entry->nickname));
1069 if (!strchr(entry->nickname, '@')) {
1070 strncat(nh, "@", 1);
1071 if (entry->servername) {
1072 strncat(nh, entry->servername, strlen(entry->servername));
1074 len = entry->router ? strlen(entry->router->server_name) :
1075 strlen(server->server_name);
1076 strncat(nh, entry->router ? entry->router->server_name :
1077 server->server_name, len);
1081 strncat(uh, entry->username, strlen(entry->username));
1082 if (!strchr(entry->username, '@')) {
1083 strncat(uh, "@", 1);
1084 strcat(uh, "*private*");
1087 if (entry->userinfo)
1089 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1091 2, idp->data, idp->len,
1095 strlen(entry->userinfo));
1098 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1100 2, idp->data, idp->len,
1104 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1105 0, packet->data, packet->len, FALSE);
1107 silc_buffer_free(packet);
1108 silc_buffer_free(idp);
1111 if (found == FALSE && entry)
1112 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1113 SILC_STATUS_ERR_NO_SUCH_NICK,
1115 strlen(entry->nickname));
1119 silc_server_command_whowas_from_client(SilcServerCommandContext cmd)
1121 SilcServer server = cmd->server;
1122 char *nick = NULL, *server_name = NULL;
1124 SilcClientEntry *clients = NULL;
1125 uint32 clients_count = 0;
1128 /* Protocol dictates that we must always send the received WHOWAS request
1129 to our router if we are normal server, so let's do it now unless we
1130 are standalone. We will not send any replies to the client until we
1131 have received reply from the router. */
1132 if (server->server_type == SILC_SERVER &&
1133 !cmd->pending && !server->standalone) {
1137 old_ident = silc_command_get_ident(cmd->payload);
1138 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1139 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1141 /* Send WHOWAS command to our router */
1142 silc_server_packet_send(server, (SilcSocketConnection)
1143 server->router->connection,
1144 SILC_PACKET_COMMAND, cmd->packet->flags,
1145 tmpbuf->data, tmpbuf->len, TRUE);
1147 /* Reprocess this packet after received reply from router */
1148 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1149 silc_command_get_ident(cmd->payload),
1150 silc_server_command_destructor,
1151 silc_server_command_whowas,
1152 silc_server_command_dup(cmd));
1153 cmd->pending = TRUE;
1155 silc_command_set_ident(cmd->payload, old_ident);
1157 silc_buffer_free(tmpbuf);
1162 /* We are ready to process the command request. Let's search for the
1163 requested client and send reply to the requesting client. */
1165 /* Parse the whowas request */
1166 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1169 /* Get all clients matching that nickname from local list */
1170 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1172 &clients, &clients_count))
1173 silc_idlist_get_clients_by_hash(server->local_list,
1174 nick, server->md5hash,
1175 &clients, &clients_count);
1177 /* Check global list as well */
1178 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1180 &clients, &clients_count))
1181 silc_idlist_get_clients_by_hash(server->global_list,
1182 nick, server->md5hash,
1183 &clients, &clients_count);
1185 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1190 /* Send the command reply to the client */
1191 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1199 silc_free(server_name);
1205 silc_server_command_whowas_from_server(SilcServerCommandContext cmd)
1207 SilcServer server = cmd->server;
1208 char *nick = NULL, *server_name = NULL;
1210 SilcClientEntry *clients = NULL;
1211 uint32 clients_count = 0;
1214 /* Parse the whowas request */
1215 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1218 /* Process the command request. Let's search for the requested client and
1219 send reply to the requesting server. */
1221 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1223 &clients, &clients_count))
1224 silc_idlist_get_clients_by_hash(server->local_list,
1225 nick, server->md5hash,
1226 &clients, &clients_count);
1228 /* If we are router we will check our global list as well. */
1229 if (server->server_type == SILC_ROUTER) {
1230 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1232 &clients, &clients_count))
1233 silc_idlist_get_clients_by_hash(server->global_list,
1234 nick, server->md5hash,
1235 &clients, &clients_count);
1239 /* Such a client really does not exist in the SILC network. */
1240 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1241 SILC_STATUS_ERR_NO_SUCH_NICK,
1242 3, nick, strlen(nick));
1246 /* Send the command reply to the client */
1247 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1255 silc_free(server_name);
1260 /* Server side of command WHOWAS. */
1262 SILC_SERVER_CMD_FUNC(whowas)
1264 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1267 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1269 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1270 ret = silc_server_command_whowas_from_client(cmd);
1271 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
1272 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1273 ret = silc_server_command_whowas_from_server(cmd);
1276 silc_server_command_free(cmd);
1279 /******************************************************************************
1283 ******************************************************************************/
1285 /* Checks that all mandatory fields are present. If not then send WHOIS
1286 request to the server who owns the client. We use WHOIS because we want
1287 to get as much information as possible at once. */
1290 silc_server_command_identify_check(SilcServerCommandContext cmd,
1291 SilcClientEntry *clients,
1292 uint32 clients_count)
1294 SilcServer server = cmd->server;
1296 SilcClientEntry entry;
1298 for (i = 0; i < clients_count; i++) {
1301 if (!entry || entry->data.registered == FALSE)
1304 if (!entry->nickname) {
1311 old_ident = silc_command_get_ident(cmd->payload);
1312 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1313 silc_command_set_command(cmd->payload, SILC_COMMAND_WHOIS);
1314 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1316 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1317 now anyway so make it a good one. */
1318 silc_server_packet_send(server, entry->router->connection,
1319 SILC_PACKET_COMMAND, cmd->packet->flags,
1320 tmpbuf->data, tmpbuf->len, TRUE);
1322 /* Reprocess this packet after received reply */
1323 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1324 silc_command_get_ident(cmd->payload),
1325 silc_server_command_destructor,
1326 silc_server_command_identify,
1327 silc_server_command_dup(cmd));
1329 cmd->pending = TRUE;
1331 /* Put old data back to the Command Payload we just changed */
1332 silc_command_set_ident(cmd->payload, old_ident);
1333 silc_command_set_command(cmd->payload, SILC_COMMAND_IDENTIFY);
1335 silc_buffer_free(tmpbuf);
1344 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1345 SilcClientEntry *clients,
1346 uint32 clients_count,
1349 SilcServer server = cmd->server;
1352 SilcBuffer packet, idp;
1353 SilcClientEntry entry;
1354 SilcCommandStatus status;
1355 uint16 ident = silc_command_get_ident(cmd->payload);
1356 char nh[256], uh[256];
1357 SilcSocketConnection hsock;
1360 for (i = 0; i < clients_count; i++)
1361 if (clients[i]->data.registered)
1364 status = SILC_STATUS_OK;
1366 status = SILC_STATUS_LIST_START;
1368 for (i = 0, k = 0; i < clients_count; i++) {
1371 if (entry->data.registered == FALSE) {
1372 if (clients_count == 1) {
1373 SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1374 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1375 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1376 2, idp->data, idp->len);
1377 silc_buffer_free(idp);
1383 status = SILC_STATUS_LIST_ITEM;
1385 if (clients_count > 1 && k == clients_count - 1)
1386 status = SILC_STATUS_LIST_END;
1388 if (count && k - 1 == count)
1389 status = SILC_STATUS_LIST_END;
1391 if (count && k - 1 > count)
1394 /* Send IDENTIFY reply */
1395 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1396 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1398 memset(uh, 0, sizeof(uh));
1399 memset(nh, 0, sizeof(nh));
1401 strncat(nh, entry->nickname, strlen(entry->nickname));
1402 if (!strchr(entry->nickname, '@')) {
1403 strncat(nh, "@", 1);
1404 if (entry->servername) {
1405 strncat(nh, entry->servername, strlen(entry->servername));
1407 len = entry->router ? strlen(entry->router->server_name) :
1408 strlen(server->server_name);
1409 strncat(nh, entry->router ? entry->router->server_name :
1410 server->server_name, len);
1414 if (!entry->username) {
1415 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1417 2, idp->data, idp->len,
1420 strncat(uh, entry->username, strlen(entry->username));
1421 if (!strchr(entry->username, '@')) {
1422 strncat(uh, "@", 1);
1423 hsock = (SilcSocketConnection)entry->connection;
1424 len = strlen(hsock->hostname);
1425 strncat(uh, hsock->hostname, len);
1428 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1430 2, idp->data, idp->len,
1435 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1436 0, packet->data, packet->len, FALSE);
1438 silc_buffer_free(packet);
1439 silc_buffer_free(idp);
1446 silc_server_command_identify_from_client(SilcServerCommandContext cmd)
1448 SilcServer server = cmd->server;
1449 char *nick = NULL, *server_name = NULL;
1451 SilcClientEntry *clients = NULL, entry;
1452 SilcClientID **client_id = NULL;
1453 uint32 client_id_count = 0, clients_count = 0;
1456 /* Protocol dictates that we must always send the received IDENTIFY request
1457 to our router if we are normal server, so let's do it now unless we
1458 are standalone. We will not send any replies to the client until we
1459 have received reply from the router. */
1460 if (server->server_type == SILC_SERVER &&
1461 !cmd->pending && !server->standalone) {
1465 old_ident = silc_command_get_ident(cmd->payload);
1466 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1467 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1469 /* Send IDENTIFY command to our router */
1470 silc_server_packet_send(server, (SilcSocketConnection)
1471 server->router->connection,
1472 SILC_PACKET_COMMAND, cmd->packet->flags,
1473 tmpbuf->data, tmpbuf->len, TRUE);
1475 /* Reprocess this packet after received reply from router */
1476 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1477 silc_command_get_ident(cmd->payload),
1478 silc_server_command_destructor,
1479 silc_server_command_identify,
1480 silc_server_command_dup(cmd));
1481 cmd->pending = TRUE;
1483 silc_command_set_ident(cmd->payload, old_ident);
1485 silc_buffer_free(tmpbuf);
1490 /* We are ready to process the command request. Let's search for the
1491 requested client and send reply to the requesting client. */
1493 /* Parse the IDENTIFY request */
1494 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1495 &nick, &server_name, &count,
1496 SILC_COMMAND_IDENTIFY))
1499 /* Get all clients matching that ID or nickname from local list */
1500 if (client_id_count) {
1501 /* Check all Client ID's received in the command packet */
1502 for (i = 0; i < client_id_count; i++) {
1503 entry = silc_idlist_find_client_by_id(server->local_list,
1504 client_id[i], NULL);
1506 clients = silc_realloc(clients, sizeof(*clients) *
1507 (clients_count + 1));
1508 clients[clients_count++] = entry;
1512 if (!silc_idlist_get_clients_by_hash(server->local_list,
1513 nick, server->md5hash,
1514 &clients, &clients_count))
1515 silc_idlist_get_clients_by_nickname(server->local_list,
1517 &clients, &clients_count);
1520 /* Check global list as well */
1521 if (client_id_count) {
1522 /* Check all Client ID's received in the command packet */
1523 for (i = 0; i < client_id_count; i++) {
1524 entry = silc_idlist_find_client_by_id(server->global_list,
1525 client_id[i], NULL);
1527 clients = silc_realloc(clients, sizeof(*clients) *
1528 (clients_count + 1));
1529 clients[clients_count++] = entry;
1533 if (!silc_idlist_get_clients_by_hash(server->global_list,
1534 nick, server->md5hash,
1535 &clients, &clients_count))
1536 silc_idlist_get_clients_by_nickname(server->global_list,
1538 &clients, &clients_count);
1542 /* Such a client really does not exist in the SILC network. */
1543 if (!client_id_count) {
1544 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1545 SILC_STATUS_ERR_NO_SUCH_NICK,
1546 3, nick, strlen(nick));
1548 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1549 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1550 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1551 2, idp->data, idp->len);
1552 silc_buffer_free(idp);
1557 /* Check that all mandatory fields are present and request those data
1558 from the server who owns the client if necessary. */
1559 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1564 /* Send the command reply to the client */
1565 silc_server_command_identify_send_reply(cmd, clients, clients_count,
1569 if (client_id_count) {
1570 for (i = 0; i < client_id_count; i++)
1571 silc_free(client_id[i]);
1572 silc_free(client_id);
1579 silc_free(server_name);
1585 silc_server_command_identify_from_server(SilcServerCommandContext cmd)
1587 SilcServer server = cmd->server;
1588 char *nick = NULL, *server_name = NULL;
1590 SilcClientEntry *clients = NULL, entry;
1591 SilcClientID **client_id = NULL;
1592 uint32 client_id_count = 0, clients_count = 0;
1595 /* Parse the IDENTIFY request */
1596 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1597 &nick, &server_name, &count,
1598 SILC_COMMAND_IDENTIFY))
1601 /* Process the command request. Let's search for the requested client and
1602 send reply to the requesting server. */
1604 if (client_id_count) {
1605 /* Check all Client ID's received in the command packet */
1606 for (i = 0; i < client_id_count; i++) {
1607 entry = silc_idlist_find_client_by_id(server->local_list,
1608 client_id[i], NULL);
1610 clients = silc_realloc(clients, sizeof(*clients) *
1611 (clients_count + 1));
1612 clients[clients_count++] = entry;
1616 if (!silc_idlist_get_clients_by_hash(server->local_list,
1617 nick, server->md5hash,
1618 &clients, &clients_count))
1619 silc_idlist_get_clients_by_nickname(server->local_list,
1621 &clients, &clients_count);
1624 /* If we are router we will check our global list as well. */
1625 if (server->server_type == SILC_ROUTER) {
1626 if (client_id_count) {
1627 /* Check all Client ID's received in the command packet */
1628 for (i = 0; i < client_id_count; i++) {
1629 entry = silc_idlist_find_client_by_id(server->global_list,
1630 client_id[i], NULL);
1632 clients = silc_realloc(clients, sizeof(*clients) *
1633 (clients_count + 1));
1634 clients[clients_count++] = entry;
1638 if (!silc_idlist_get_clients_by_hash(server->global_list,
1639 nick, server->md5hash,
1640 &clients, &clients_count))
1641 silc_idlist_get_clients_by_nickname(server->global_list,
1643 &clients, &clients_count);
1648 /* Such a client really does not exist in the SILC network. */
1649 if (!client_id_count) {
1650 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1651 SILC_STATUS_ERR_NO_SUCH_NICK,
1652 3, nick, strlen(nick));
1654 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1655 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1656 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1657 2, idp->data, idp->len);
1658 silc_buffer_free(idp);
1663 /* Check that all mandatory fields are present and request those data
1664 from the server who owns the client if necessary. */
1665 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1670 /* Send the command reply */
1671 silc_server_command_identify_send_reply(cmd, clients, clients_count, count);
1674 if (client_id_count) {
1675 for (i = 0; i < client_id_count; i++)
1676 silc_free(client_id[i]);
1677 silc_free(client_id);
1684 silc_free(server_name);
1689 SILC_SERVER_CMD_FUNC(identify)
1691 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1694 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1696 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1697 ret = silc_server_command_identify_from_client(cmd);
1698 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) |
1699 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1700 ret = silc_server_command_identify_from_server(cmd);
1703 silc_server_command_free(cmd);
1706 /* Checks string for bad characters and returns TRUE if they are found. */
1708 static int silc_server_command_bad_chars(char *nick)
1710 if (strchr(nick, '\\')) return TRUE;
1711 if (strchr(nick, '\"')) return TRUE;
1712 if (strchr(nick, '´')) return TRUE;
1713 if (strchr(nick, '`')) return TRUE;
1714 if (strchr(nick, '\'')) return TRUE;
1715 if (strchr(nick, '*')) return TRUE;
1716 if (strchr(nick, '/')) return TRUE;
1717 if (strchr(nick, '@')) return TRUE;
1722 /* Server side of command NICK. Sets nickname for user. Setting
1723 nickname causes generation of a new client ID for the client. The
1724 new client ID is sent to the client after changing the nickname. */
1726 SILC_SERVER_CMD_FUNC(nick)
1728 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1729 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1730 SilcServer server = cmd->server;
1731 SilcBuffer packet, nidp, oidp;
1732 SilcClientID *new_id;
1734 uint16 ident = silc_command_get_ident(cmd->payload);
1736 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1739 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NICK, cmd, 1, 1);
1741 /* Check nickname */
1742 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1743 if (silc_server_command_bad_chars(nick) == TRUE) {
1744 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1745 SILC_STATUS_ERR_BAD_NICKNAME);
1749 if (strlen(nick) > 128)
1752 /* Create new Client ID */
1753 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
1754 cmd->server->md5hash, nick,
1757 /* Send notify about nickname change to our router. We send the new
1758 ID and ask to replace it with the old one. If we are router the
1759 packet is broadcasted. Send NICK_CHANGE notify. */
1760 if (!server->standalone)
1761 silc_server_send_notify_nick_change(server, server->router->connection,
1762 server->server_type == SILC_SERVER ?
1763 FALSE : TRUE, client->id,
1764 new_id, SILC_ID_CLIENT_LEN);
1766 /* Remove old cache entry */
1767 silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
1770 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1774 memset(client->id, 0, SILC_ID_CLIENT_LEN);
1775 silc_free(client->id);
1778 /* Save the nickname as this client is our local client */
1779 if (client->nickname)
1780 silc_free(client->nickname);
1782 client->nickname = strdup(nick);
1783 client->id = new_id;
1785 /* Update client cache */
1786 silc_idcache_add(server->local_list->clients, client->nickname,
1787 strlen(client->nickname), SILC_ID_CLIENT, client->id,
1788 (void *)client, TRUE, FALSE);
1790 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1792 /* Send NICK_CHANGE notify to the client's channels */
1793 silc_server_send_notify_on_channels(server, NULL, client,
1794 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1795 oidp->data, oidp->len,
1796 nidp->data, nidp->len);
1798 /* Send the new Client ID as reply command back to client */
1799 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
1800 SILC_STATUS_OK, ident, 1,
1801 2, nidp->data, nidp->len);
1802 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1803 0, packet->data, packet->len, FALSE);
1805 silc_buffer_free(packet);
1806 silc_buffer_free(nidp);
1807 silc_buffer_free(oidp);
1810 silc_server_command_free(cmd);
1813 /* Sends the LIST command reply */
1816 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
1817 SilcChannelEntry *lch,
1819 SilcChannelEntry *gch,
1823 SilcBuffer packet, idp;
1824 SilcChannelEntry entry;
1825 SilcCommandStatus status;
1826 uint16 ident = silc_command_get_ident(cmd->payload);
1828 unsigned char usercount[4];
1831 for (i = 0; i < lch_count; i++)
1832 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
1834 for (i = 0; i < gch_count; i++)
1835 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
1838 status = SILC_STATUS_OK;
1839 if ((lch_count + gch_count) > 1)
1840 status = SILC_STATUS_LIST_START;
1843 for (i = 0; i < lch_count; i++) {
1850 status = SILC_STATUS_LIST_ITEM;
1852 if (i == lch_count - 1 && gch_count)
1854 if (lch_count > 1 && i == lch_count - 1)
1855 status = SILC_STATUS_LIST_END;
1857 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1859 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
1860 topic = "*private*";
1861 memset(usercount, 0, sizeof(usercount));
1863 topic = entry->topic;
1864 users = silc_list_count(entry->user_list);
1865 SILC_PUT32_MSB(users, usercount);
1868 /* Send the reply */
1871 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1873 2, idp->data, idp->len,
1874 3, entry->channel_name,
1875 strlen(entry->channel_name),
1876 4, topic, strlen(topic),
1880 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1882 2, idp->data, idp->len,
1883 3, entry->channel_name,
1884 strlen(entry->channel_name),
1886 silc_server_packet_send(cmd->server, cmd->sock,
1887 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
1888 packet->len, FALSE);
1889 silc_buffer_free(packet);
1890 silc_buffer_free(idp);
1893 status = i ? SILC_STATUS_LIST_ITEM : SILC_STATUS_OK;
1896 for (i = 0; i < gch_count; i++) {
1903 status = SILC_STATUS_LIST_ITEM;
1905 if (gch_count > 1 && i == lch_count - 1)
1906 status = SILC_STATUS_LIST_END;
1908 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1910 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
1911 topic = "*private*";
1912 memset(usercount, 0, sizeof(usercount));
1914 topic = entry->topic;
1915 users = silc_list_count(entry->user_list);
1916 SILC_PUT32_MSB(users, usercount);
1919 /* Send the reply */
1922 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1924 2, idp->data, idp->len,
1925 3, entry->channel_name,
1926 strlen(entry->channel_name),
1927 4, topic, strlen(topic),
1931 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1933 2, idp->data, idp->len,
1934 3, entry->channel_name,
1935 strlen(entry->channel_name),
1937 silc_server_packet_send(cmd->server, cmd->sock,
1938 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
1939 packet->len, FALSE);
1940 silc_buffer_free(packet);
1941 silc_buffer_free(idp);
1945 /* Server side of LIST command. This lists the channel of the requested
1946 server. Secret channels are not listed. */
1948 SILC_SERVER_CMD_FUNC(list)
1950 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1951 SilcServer server = cmd->server;
1952 SilcChannelID *channel_id = NULL;
1955 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
1956 uint32 lch_count = 0, gch_count = 0;
1958 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LIST, cmd, 0, 2);
1960 /* Get Channel ID */
1961 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1963 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1965 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
1966 SILC_STATUS_ERR_NO_CHANNEL_ID);
1971 /* Get the channels from local list */
1972 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
1975 /* Get the channels from global list if we are router */
1976 if (server->server_type == SILC_ROUTER)
1977 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
1980 /* Send the reply */
1981 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
1982 gchannels, gch_count);
1985 silc_server_command_free(cmd);
1988 /* Server side of TOPIC command. Sets topic for channel and/or returns
1989 current topic to client. */
1991 SILC_SERVER_CMD_FUNC(topic)
1993 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1994 SilcServer server = cmd->server;
1995 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1996 SilcChannelID *channel_id;
1997 SilcChannelEntry channel;
1998 SilcChannelClientEntry chl;
1999 SilcBuffer packet, idp;
2001 uint32 argc, tmp_len;
2002 uint16 ident = silc_command_get_ident(cmd->payload);
2004 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
2006 argc = silc_argument_get_arg_num(cmd->args);
2008 /* Get Channel ID */
2009 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2011 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2012 SILC_STATUS_ERR_NO_CHANNEL_ID);
2015 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2017 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2018 SILC_STATUS_ERR_NO_CHANNEL_ID);
2022 /* Check whether the channel exists */
2023 channel = silc_idlist_find_channel_by_id(server->local_list,
2026 channel = silc_idlist_find_channel_by_id(server->global_list,
2029 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2030 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2037 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2039 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2040 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2044 if (strlen(tmp) > 256) {
2045 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2046 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2050 /* See whether has rights to change topic */
2051 silc_list_start(channel->user_list);
2052 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2053 if (chl->client == client)
2056 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2057 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2058 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2059 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2064 /* Set the topic for channel */
2066 silc_free(channel->topic);
2067 channel->topic = strdup(tmp);
2069 /* Send TOPIC_SET notify type to the network */
2070 if (!server->standalone)
2071 silc_server_send_notify_topic_set(server, server->router->connection,
2072 server->server_type == SILC_ROUTER ?
2073 TRUE : FALSE, channel, client->id,
2074 SILC_ID_CLIENT_LEN, channel->topic);
2076 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2078 /* Send notify about topic change to all clients on the channel */
2079 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2080 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2081 idp->data, idp->len,
2082 channel->topic, strlen(channel->topic));
2083 silc_buffer_free(idp);
2086 /* Send the topic to client as reply packet */
2087 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2089 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2090 SILC_STATUS_OK, ident, 2,
2091 2, idp->data, idp->len,
2093 strlen(channel->topic));
2095 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2096 SILC_STATUS_OK, ident, 1,
2097 2, idp->data, idp->len);
2098 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2099 0, packet->data, packet->len, FALSE);
2101 silc_buffer_free(packet);
2102 silc_buffer_free(idp);
2103 silc_free(channel_id);
2106 silc_server_command_free(cmd);
2109 /* Server side of INVITE command. Invites some client to join some channel.
2110 This command is also used to manage the invite list of the channel. */
2112 SILC_SERVER_CMD_FUNC(invite)
2114 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2115 SilcServer server = cmd->server;
2116 SilcSocketConnection sock = cmd->sock, dest_sock;
2117 SilcChannelClientEntry chl;
2118 SilcClientEntry sender, dest;
2119 SilcClientID *dest_id = NULL;
2120 SilcChannelEntry channel;
2121 SilcChannelID *channel_id = NULL;
2122 SilcIDListData idata;
2123 SilcBuffer idp, idp2, packet;
2124 unsigned char *tmp, *add, *del;
2126 uint16 ident = silc_command_get_ident(cmd->payload);
2128 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 4);
2130 /* Get Channel ID */
2131 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2133 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2134 SILC_STATUS_ERR_NO_CHANNEL_ID);
2137 channel_id = silc_id_payload_parse_id(tmp, len);
2139 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2140 SILC_STATUS_ERR_NO_CHANNEL_ID);
2144 /* Get the channel entry */
2145 channel = silc_idlist_find_channel_by_id(server->local_list,
2148 channel = silc_idlist_find_channel_by_id(server->global_list,
2151 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2152 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2157 /* Check whether the sender of this command is on the channel. */
2158 sender = (SilcClientEntry)sock->user_data;
2159 if (!silc_server_client_on_channel(sender, channel)) {
2160 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2161 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2165 /* Check whether the channel is invite-only channel. If yes then the
2166 sender of this command must be at least channel operator. */
2167 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2168 silc_list_start(channel->user_list);
2169 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2170 if (chl->client == sender) {
2171 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2172 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2173 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2180 /* Get destination client ID */
2181 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2185 dest_id = silc_id_payload_parse_id(tmp, len);
2187 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2188 SILC_STATUS_ERR_NO_CLIENT_ID);
2192 /* Get the client entry */
2193 dest = silc_server_get_client_resolve(server, dest_id);
2195 if (server->server_type == SILC_ROUTER) {
2196 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2197 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2201 /* The client info is being resolved. Reprocess this packet after
2202 receiving the reply to the query. */
2203 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2205 silc_server_command_destructor,
2206 silc_server_command_invite,
2207 silc_server_command_dup(cmd));
2208 cmd->pending = TRUE;
2209 silc_free(channel_id);
2214 /* Check whether the requested client is already on the channel. */
2215 if (silc_server_client_on_channel(dest, channel)) {
2216 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2217 SILC_STATUS_ERR_USER_ON_CHANNEL);
2221 /* Get route to the client */
2222 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2224 memset(invite, 0, sizeof(invite));
2225 strncat(invite, dest->nickname, strlen(dest->nickname));
2226 strncat(invite, "!", 1);
2227 strncat(invite, dest->username, strlen(dest->username));
2228 if (!strchr(dest->username, '@')) {
2229 strncat(invite, "@", 1);
2230 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2233 len = strlen(invite);
2234 if (!channel->invite_list)
2235 channel->invite_list = silc_calloc(len + 2,
2236 sizeof(*channel->invite_list));
2238 channel->invite_list = silc_realloc(channel->invite_list,
2239 sizeof(*channel->invite_list) *
2241 strlen(channel->invite_list) + 2));
2242 strncat(channel->invite_list, invite, len);
2243 strncat(channel->invite_list, ",", 1);
2245 /* Send notify to the client that is invited to the channel */
2246 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2247 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2248 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2250 SILC_NOTIFY_TYPE_INVITE, 3,
2251 idp->data, idp->len,
2252 channel->channel_name,
2253 strlen(channel->channel_name),
2254 idp2->data, idp2->len);
2255 silc_buffer_free(idp);
2256 silc_buffer_free(idp2);
2259 /* Add the client to the invite list of the channel */
2260 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2262 if (!channel->invite_list)
2263 channel->invite_list = silc_calloc(len + 2,
2264 sizeof(*channel->invite_list));
2266 channel->invite_list = silc_realloc(channel->invite_list,
2267 sizeof(*channel->invite_list) *
2269 strlen(channel->invite_list) + 2));
2270 if (add[len - 1] == ',')
2271 add[len - 1] = '\0';
2273 strncat(channel->invite_list, add, len);
2274 strncat(channel->invite_list, ",", 1);
2277 /* Get the invite to be removed and remove it from the list */
2278 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2279 if (del && channel->invite_list) {
2280 char *start, *end, *n;
2282 if (!strncmp(channel->invite_list, del,
2283 strlen(channel->invite_list) - 1)) {
2284 silc_free(channel->invite_list);
2285 channel->invite_list = NULL;
2287 start = strstr(channel->invite_list, del);
2288 if (start && strlen(start) >= len) {
2290 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2291 strncat(n, channel->invite_list, start - channel->invite_list);
2292 strncat(n, end + 1, ((channel->invite_list +
2293 strlen(channel->invite_list)) - end) - 1);
2294 silc_free(channel->invite_list);
2295 channel->invite_list = n;
2300 /* Send notify to the primary router */
2301 if (!server->standalone)
2302 silc_server_send_notify_invite(server, server->router->connection,
2303 server->server_type == SILC_ROUTER ?
2304 TRUE : FALSE, channel,
2305 sender->id, SILC_ID_CLIENT_LEN,
2308 /* Send command reply */
2309 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2310 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2311 SILC_STATUS_OK, ident, 2,
2313 3, channel->invite_list,
2314 channel->invite_list ?
2315 strlen(channel->invite_list) :
2317 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2318 packet->data, packet->len, FALSE);
2319 silc_buffer_free(packet);
2325 silc_free(channel_id);
2326 silc_server_command_free(cmd);
2331 SilcSocketConnection sock;
2335 /* Quits connection to client. This gets called if client won't
2336 close the connection even when it has issued QUIT command. */
2338 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2340 QuitInternal q = (QuitInternal)context;
2342 /* Free all client specific data, such as client entry and entires
2343 on channels this client may be on. */
2344 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2346 q->sock->user_data = NULL;
2348 /* Close the connection on our side */
2349 silc_server_close_connection(q->server, q->sock);
2351 silc_free(q->signoff);
2355 /* Quits SILC session. This is the normal way to disconnect client. */
2357 SILC_SERVER_CMD_FUNC(quit)
2359 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2360 SilcServer server = cmd->server;
2361 SilcSocketConnection sock = cmd->sock;
2363 unsigned char *tmp = NULL;
2366 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_QUIT, cmd, 0, 1);
2368 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2371 /* Get destination ID */
2372 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2376 q = silc_calloc(1, sizeof(*q));
2379 q->signoff = tmp ? strdup(tmp) : NULL;
2381 /* We quit the connection with little timeout */
2382 silc_task_register(server->timeout_queue, sock->sock,
2383 silc_server_command_quit_cb, (void *)q,
2384 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2387 silc_server_command_free(cmd);
2390 /* Server side of command KILL. This command is used by router operator
2391 to remove an client from the SILC Network temporarily. */
2393 SILC_SERVER_CMD_FUNC(kill)
2395 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2396 SilcServer server = cmd->server;
2397 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2398 SilcClientEntry remote_client;
2399 SilcClientID *client_id;
2400 unsigned char *tmp, *comment;
2401 uint32 tmp_len, tmp_len2;
2403 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_KILL, cmd, 1, 2);
2405 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2408 /* KILL command works only on router */
2409 if (server->server_type != SILC_ROUTER) {
2410 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2411 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2415 /* Check whether client has the permissions. */
2416 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2417 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2418 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2422 /* Get the client ID */
2423 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2425 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2426 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2429 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2431 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2432 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2436 /* Get the client entry */
2437 remote_client = silc_idlist_find_client_by_id(server->local_list,
2439 if (!remote_client) {
2440 remote_client = silc_idlist_find_client_by_id(server->global_list,
2442 if (!remote_client) {
2443 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2444 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2450 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2454 /* Send reply to the sender */
2455 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2458 /* Send the KILL notify packets. First send it to the channel, then
2459 to our primary router and then directly to the client who is being
2460 killed right now. */
2462 /* Send KILLED notify to the channels. It is not sent to the client
2463 as it will be sent differently destined directly to the client and not
2465 silc_server_send_notify_on_channels(server, remote_client,
2466 remote_client, SILC_NOTIFY_TYPE_KILLED,
2469 comment, comment ? tmp_len2 : 0);
2471 /* Send KILLED notify to primary route */
2472 if (!server->standalone)
2473 silc_server_send_notify_killed(server, server->router->connection, TRUE,
2474 remote_client->id, SILC_ID_CLIENT_LEN,
2477 /* Send KILLED notify to the client directly */
2478 silc_server_send_notify_killed(server, remote_client->connection ?
2479 remote_client->connection :
2480 remote_client->router->connection, FALSE,
2481 remote_client->id, SILC_ID_CLIENT_LEN,
2484 /* Remove the client from all channels. This generates new keys to the
2485 channels as well. */
2486 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2489 /* Remove the client entry, If it is locally connected then we will also
2490 disconnect the client here */
2491 if (remote_client->data.registered && remote_client->connection) {
2492 /* Remove locally conneted client */
2493 SilcSocketConnection sock = remote_client->connection;
2494 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2495 silc_server_close_connection(server, sock);
2497 /* Remove remote client */
2498 if (!silc_idlist_del_client(server->global_list, remote_client))
2499 silc_idlist_del_client(server->local_list, remote_client);
2503 silc_server_command_free(cmd);
2506 /* Server side of command INFO. This sends information about us to
2507 the client. If client requested specific server we will send the
2508 command to that server. */
2510 SILC_SERVER_CMD_FUNC(info)
2512 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2513 SilcServer server = cmd->server;
2514 SilcBuffer packet, idp;
2517 char *dest_server, *server_info = NULL, *server_name;
2518 uint16 ident = silc_command_get_ident(cmd->payload);
2519 SilcServerEntry entry = NULL;
2520 SilcServerID *server_id = NULL;
2522 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 0, 2);
2524 /* Get server name */
2525 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2528 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2530 server_id = silc_id_payload_parse_id(tmp, tmp_len);
2532 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2533 SILC_STATUS_ERR_NO_SERVER_ID);
2539 /* Check whether we have this server cached */
2540 entry = silc_idlist_find_server_by_id(server->local_list,
2543 entry = silc_idlist_find_server_by_id(server->global_list,
2545 if (!entry && server->server_type == SILC_ROUTER) {
2546 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2547 SILC_STATUS_ERR_NO_SUCH_SERVER);
2553 if ((!dest_server && !server_id) ||
2554 (dest_server && !cmd->pending &&
2555 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2556 /* Send our reply */
2557 char info_string[256];
2559 memset(info_string, 0, sizeof(info_string));
2560 snprintf(info_string, sizeof(info_string),
2561 "location: %s server: %s admin: %s <%s>",
2562 server->config->admin_info->location,
2563 server->config->admin_info->server_type,
2564 server->config->admin_info->admin_name,
2565 server->config->admin_info->admin_email);
2567 server_info = info_string;
2568 entry = server->id_entry;
2570 /* Check whether we have this server cached */
2571 if (!entry && dest_server) {
2572 entry = silc_idlist_find_server_by_name(server->global_list,
2575 entry = silc_idlist_find_server_by_name(server->local_list,
2580 if (!cmd->pending &&
2581 server->server_type == SILC_ROUTER && entry && !entry->server_info) {
2582 /* Send to the server */
2586 old_ident = silc_command_get_ident(cmd->payload);
2587 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2588 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2590 silc_server_packet_send(server, entry->connection,
2591 SILC_PACKET_COMMAND, cmd->packet->flags,
2592 tmpbuf->data, tmpbuf->len, TRUE);
2594 /* Reprocess this packet after received reply from router */
2595 silc_server_command_pending(server, SILC_COMMAND_INFO,
2596 silc_command_get_ident(cmd->payload),
2597 silc_server_command_destructor,
2598 silc_server_command_info,
2599 silc_server_command_dup(cmd));
2600 cmd->pending = TRUE;
2601 silc_command_set_ident(cmd->payload, old_ident);
2602 silc_buffer_free(tmpbuf);
2606 if (!entry && !cmd->pending && !server->standalone) {
2607 /* Send to the primary router */
2611 old_ident = silc_command_get_ident(cmd->payload);
2612 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2613 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2615 silc_server_packet_send(server, server->router->connection,
2616 SILC_PACKET_COMMAND, cmd->packet->flags,
2617 tmpbuf->data, tmpbuf->len, TRUE);
2619 /* Reprocess this packet after received reply from router */
2620 silc_server_command_pending(server, SILC_COMMAND_INFO,
2621 silc_command_get_ident(cmd->payload),
2622 silc_server_command_destructor,
2623 silc_server_command_info,
2624 silc_server_command_dup(cmd));
2625 cmd->pending = TRUE;
2626 silc_command_set_ident(cmd->payload, old_ident);
2627 silc_buffer_free(tmpbuf);
2633 silc_free(server_id);
2636 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2637 SILC_STATUS_ERR_NO_SUCH_SERVER);
2641 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2643 server_info = entry->server_info;
2644 server_name = entry->server_name;
2646 /* Send the reply */
2647 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2648 SILC_STATUS_OK, ident, 3,
2649 2, idp->data, idp->len,
2651 strlen(server_name),
2653 strlen(server_info));
2654 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2655 packet->data, packet->len, FALSE);
2657 silc_buffer_free(packet);
2658 silc_buffer_free(idp);
2661 silc_server_command_free(cmd);
2664 /* Server side of command PING. This just replies to the ping. */
2666 SILC_SERVER_CMD_FUNC(ping)
2668 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2669 SilcServer server = cmd->server;
2674 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
2677 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2679 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2680 SILC_STATUS_ERR_NO_SERVER_ID);
2683 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2687 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
2688 /* Send our reply */
2689 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2692 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2693 SILC_STATUS_ERR_NO_SUCH_SERVER);
2700 silc_server_command_free(cmd);
2703 /* Internal routine to join channel. The channel sent to this function
2704 has been either created or resolved from ID lists. This joins the sent
2705 client to the channel. */
2707 static void silc_server_command_join_channel(SilcServer server,
2708 SilcServerCommandContext cmd,
2709 SilcChannelEntry channel,
2710 SilcClientID *client_id,
2714 SilcSocketConnection sock = cmd->sock;
2716 uint32 tmp_len, user_count;
2717 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
2718 SilcClientEntry client;
2719 SilcChannelClientEntry chl;
2720 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
2721 uint16 ident = silc_command_get_ident(cmd->payload);
2724 SILC_LOG_DEBUG(("Start"));
2729 /* Get the client entry */
2730 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2731 client = (SilcClientEntry)sock->user_data;
2733 client = silc_idlist_find_client_by_id(server->local_list, client_id,
2740 * Check channel modes
2743 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2744 strncat(check, client->nickname, strlen(client->nickname));
2745 if (!strchr(client->nickname, '@')) {
2746 strncat(check, "@", 1);
2747 strncat(check, server->server_name, strlen(server->server_name));
2749 strncat(check, "!", 1);
2750 strncat(check, client->username, strlen(client->username));
2751 if (!strchr(client->username, '@')) {
2752 strncat(check, "@", 1);
2753 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
2757 /* Check invite list if channel is invite-only channel */
2758 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
2759 channel->mode & SILC_CHANNEL_MODE_INVITE) {
2760 if (!channel->invite_list) {
2761 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2762 SILC_STATUS_ERR_NOT_INVITED);
2766 if (!silc_string_match(channel->invite_list, check)) {
2767 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2768 SILC_STATUS_ERR_NOT_INVITED);
2773 /* Check ban list if it exists. If the client's nickname, server,
2774 username and/or hostname is in the ban list the access to the
2775 channel is denied. */
2776 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && channel->ban_list) {
2777 if (silc_string_match(channel->ban_list, check)) {
2778 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2779 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
2784 /* Get passphrase */
2785 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2787 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
2788 memcpy(passphrase, tmp, tmp_len);
2791 /* Check the channel passphrase if set. */
2792 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2793 if (!passphrase || memcmp(channel->passphrase, passphrase,
2794 strlen(channel->passphrase))) {
2795 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2796 SILC_STATUS_ERR_BAD_PASSWORD);
2801 /* Check user count limit if set. */
2802 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
2803 if (silc_list_count(channel->user_list) + 1 >
2804 channel->user_limit) {
2805 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2806 SILC_STATUS_ERR_CHANNEL_IS_FULL);
2812 * Client is allowed to join to the channel. Make it happen.
2815 /* Check whether the client already is on the channel */
2816 if (silc_server_client_on_channel(client, channel)) {
2817 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2818 SILC_STATUS_ERR_USER_ON_CHANNEL);
2822 /* Generate new channel key as protocol dictates */
2823 if ((!created && silc_list_count(channel->user_list) > 0) ||
2824 !channel->channel_key)
2825 silc_server_create_channel_key(server, channel, 0);
2827 /* Send the channel key. This is broadcasted to the channel but is not
2828 sent to the client who is joining to the channel. */
2829 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
2830 silc_server_send_channel_key(server, NULL, channel,
2831 server->server_type == SILC_ROUTER ?
2832 FALSE : !server->standalone);
2834 /* Join the client to the channel by adding it to channel's user list.
2835 Add also the channel to client entry's channels list for fast cross-
2837 chl = silc_calloc(1, sizeof(*chl));
2839 chl->client = client;
2840 chl->channel = channel;
2841 silc_list_add(channel->user_list, chl);
2842 silc_list_add(client->channels, chl);
2844 /* Get users on the channel */
2845 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
2848 /* Encode Client ID Payload of the original client who wants to join */
2849 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2851 /* Encode command reply packet */
2852 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2853 SILC_PUT32_MSB(channel->mode, mode);
2854 SILC_PUT32_MSB(created, tmp2);
2855 SILC_PUT32_MSB(user_count, tmp3);
2857 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
2858 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
2859 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
2860 strlen(channel->channel_key->
2862 channel->channel_key->cipher->name,
2863 channel->key_len / 8, channel->key);
2868 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2869 SILC_STATUS_OK, ident, 13,
2870 2, channel->channel_name,
2871 strlen(channel->channel_name),
2872 3, chidp->data, chidp->len,
2873 4, clidp->data, clidp->len,
2876 7, keyp ? keyp->data : NULL,
2877 keyp ? keyp->len : 0,
2878 8, channel->ban_list,
2880 strlen(channel->ban_list) : 0,
2881 9, channel->invite_list,
2882 channel->invite_list ?
2883 strlen(channel->invite_list) : 0,
2886 strlen(channel->topic) : 0,
2887 11, channel->hmac->hmac->name,
2888 strlen(channel->hmac->hmac->name),
2890 13, user_list->data, user_list->len,
2891 14, mode_list->data,
2894 /* Send command reply */
2895 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
2896 reply->data, reply->len, FALSE);
2898 if (!cmd->pending) {
2899 /* Send JOIN notify to locally connected clients on the channel */
2900 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2901 SILC_NOTIFY_TYPE_JOIN, 2,
2902 clidp->data, clidp->len,
2903 chidp->data, chidp->len);
2905 /* Send JOIN notify packet to our primary router */
2906 if (!server->standalone)
2907 silc_server_send_notify_join(server, server->router->connection,
2908 server->server_type == SILC_ROUTER ?
2909 TRUE : FALSE, channel, client->id,
2910 SILC_ID_CLIENT_LEN);
2913 silc_buffer_free(reply);
2914 silc_buffer_free(clidp);
2915 silc_buffer_free(chidp);
2916 silc_buffer_free(keyp);
2917 silc_buffer_free(user_list);
2918 silc_buffer_free(mode_list);
2922 silc_free(passphrase);
2925 /* Server side of command JOIN. Joins client into requested channel. If
2926 the channel does not exist it will be created. */
2928 SILC_SERVER_CMD_FUNC(join)
2930 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2931 SilcServer server = cmd->server;
2933 char *tmp, *channel_name = NULL, *cipher, *hmac;
2934 SilcChannelEntry channel;
2936 int created = FALSE;
2937 SilcClientID *client_id;
2939 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
2941 /* Get channel name */
2942 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2944 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2945 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2950 if (strlen(channel_name) > 256)
2951 channel_name[255] = '\0';
2953 if (silc_server_command_bad_chars(channel_name) == TRUE) {
2954 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2955 SILC_STATUS_ERR_BAD_CHANNEL);
2956 silc_free(channel_name);
2960 /* Get Client ID of the client who is joining to the channel */
2961 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2963 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2964 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2967 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2969 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2970 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2974 /* Get cipher and hmac name */
2975 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2976 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2978 /* See if the channel exists */
2979 channel = silc_idlist_find_channel_by_name(server->local_list,
2980 channel_name, NULL);
2982 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2983 /* If this is coming from client the Client ID in the command packet must
2984 be same as the client's ID. */
2985 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2986 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2987 if (SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
2988 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2989 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2994 if (!channel || !channel->id) {
2995 /* Channel not found */
2997 /* If we are standalone server we don't have a router, we just create
2998 the channel by ourselves. */
2999 if (server->standalone) {
3000 channel = silc_server_create_new_channel(server, server->id, cipher,
3001 hmac, channel_name, TRUE);
3003 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3004 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3008 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3013 /* The channel does not exist on our server. If we are normal server
3014 we will send JOIN command to our router which will handle the
3015 joining procedure (either creates the channel if it doesn't exist
3016 or joins the client to it). */
3017 if (server->server_type == SILC_SERVER) {
3021 old_ident = silc_command_get_ident(cmd->payload);
3022 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3023 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3025 /* Send JOIN command to our router */
3026 silc_server_packet_send(server, (SilcSocketConnection)
3027 server->router->connection,
3028 SILC_PACKET_COMMAND, cmd->packet->flags,
3029 tmpbuf->data, tmpbuf->len, TRUE);
3031 /* Reprocess this packet after received reply from router */
3032 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3033 silc_command_get_ident(cmd->payload),
3034 silc_server_command_destructor,
3035 silc_server_command_join,
3036 silc_server_command_dup(cmd));
3037 cmd->pending = TRUE;
3041 /* We are router and the channel does not seem exist so we will check
3042 our global list as well for the channel. */
3043 channel = silc_idlist_find_channel_by_name(server->global_list,
3044 channel_name, NULL);
3046 /* Channel really does not exist, create it */
3047 channel = silc_server_create_new_channel(server, server->id, cipher,
3048 hmac, channel_name, TRUE);
3050 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3051 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3055 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3062 /* Channel not found */
3064 /* If the command came from router and/or we are normal server then
3065 something went wrong with the joining as the channel was not found.
3066 We can't do anything else but ignore this. */
3067 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3068 server->server_type == SILC_SERVER)
3071 /* We are router and the channel does not seem exist so we will check
3072 our global list as well for the channel. */
3073 channel = silc_idlist_find_channel_by_name(server->global_list,
3074 channel_name, NULL);
3076 /* Channel really does not exist, create it */
3077 channel = silc_server_create_new_channel(server, server->id, cipher,
3078 hmac, channel_name, TRUE);
3080 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3081 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3085 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3091 /* If the channel does not have global users and is also empty it means the
3092 channel was created globally (by our router) and the client will be the
3093 channel founder and operator. */
3094 if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
3095 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3096 created = TRUE; /* Created globally by our router */
3099 /* Join to the channel */
3100 silc_server_command_join_channel(server, cmd, channel, client_id,
3103 silc_free(client_id);
3106 silc_server_command_free(cmd);
3109 /* Server side of command MOTD. Sends server's current "message of the
3110 day" to the client. */
3112 SILC_SERVER_CMD_FUNC(motd)
3114 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3115 SilcServer server = cmd->server;
3116 SilcBuffer packet, idp;
3117 char *motd, *dest_server;
3119 uint16 ident = silc_command_get_ident(cmd->payload);
3121 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 1);
3123 /* Get server name */
3124 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3126 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3127 SILC_STATUS_ERR_NO_SUCH_SERVER);
3131 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3134 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3136 if (server->config && server->config->motd &&
3137 server->config->motd->motd_file) {
3139 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
3144 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3145 SILC_STATUS_OK, ident, 2,
3151 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3152 SILC_STATUS_OK, ident, 1,
3156 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3157 packet->data, packet->len, FALSE);
3158 silc_buffer_free(packet);
3159 silc_buffer_free(idp);
3161 SilcServerEntry entry;
3163 /* Check whether we have this server cached */
3164 entry = silc_idlist_find_server_by_name(server->global_list,
3167 entry = silc_idlist_find_server_by_name(server->local_list,
3171 if (server->server_type == SILC_ROUTER && !cmd->pending &&
3172 entry && !entry->motd) {
3173 /* Send to the server */
3177 old_ident = silc_command_get_ident(cmd->payload);
3178 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3179 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3181 silc_server_packet_send(server, entry->connection,
3182 SILC_PACKET_COMMAND, cmd->packet->flags,
3183 tmpbuf->data, tmpbuf->len, TRUE);
3185 /* Reprocess this packet after received reply from router */
3186 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3187 silc_command_get_ident(cmd->payload),
3188 silc_server_command_destructor,
3189 silc_server_command_motd,
3190 silc_server_command_dup(cmd));
3191 cmd->pending = TRUE;
3192 silc_command_set_ident(cmd->payload, old_ident);
3193 silc_buffer_free(tmpbuf);
3197 if (!entry && !cmd->pending && !server->standalone) {
3198 /* Send to the primary router */
3202 old_ident = silc_command_get_ident(cmd->payload);
3203 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3204 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3206 silc_server_packet_send(server, server->router->connection,
3207 SILC_PACKET_COMMAND, cmd->packet->flags,
3208 tmpbuf->data, tmpbuf->len, TRUE);
3210 /* Reprocess this packet after received reply from router */
3211 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3212 silc_command_get_ident(cmd->payload),
3213 silc_server_command_destructor,
3214 silc_server_command_motd,
3215 silc_server_command_dup(cmd));
3216 cmd->pending = TRUE;
3217 silc_command_set_ident(cmd->payload, old_ident);
3218 silc_buffer_free(tmpbuf);
3223 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3224 SILC_STATUS_ERR_NO_SUCH_SERVER);
3228 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3231 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3232 SILC_STATUS_OK, ident, 2,
3235 strlen(entry->motd));
3237 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3238 SILC_STATUS_OK, ident, 1,
3241 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3242 packet->data, packet->len, FALSE);
3243 silc_buffer_free(packet);
3244 silc_buffer_free(idp);
3248 silc_server_command_free(cmd);
3251 /* Server side of command UMODE. Client can use this command to set/unset
3252 user mode. Client actually cannot set itself to be as server/router
3253 operator so this can be used only to unset the modes. */
3255 SILC_SERVER_CMD_FUNC(umode)
3257 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3258 SilcServer server = cmd->server;
3259 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3261 unsigned char *tmp_mask;
3263 uint16 ident = silc_command_get_ident(cmd->payload);
3265 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3268 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_UMODE, cmd, 2, 2);
3270 /* Get the client's mode mask */
3271 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3273 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3274 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3277 SILC_GET32_MSB(mask, tmp_mask);
3283 if (mask & SILC_UMODE_SERVER_OPERATOR) {
3284 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR)) {
3285 /* Cannot operator mode */
3286 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3287 SILC_STATUS_ERR_PERM_DENIED);
3291 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
3292 /* Remove the server operator rights */
3293 client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3296 if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3297 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
3298 /* Cannot operator mode */
3299 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3300 SILC_STATUS_ERR_PERM_DENIED);
3304 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
3305 /* Remove the router operator rights */
3306 client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3309 if (mask & SILC_UMODE_GONE) {
3310 client->mode |= SILC_UMODE_GONE;
3312 if (client->mode & SILC_UMODE_GONE)
3313 /* Remove the gone status */
3314 client->mode &= ~SILC_UMODE_GONE;
3317 /* Send UMODE change to primary router */
3318 if (!server->standalone)
3319 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3320 client->id, SILC_ID_CLIENT_LEN,
3323 /* Send command reply to sender */
3324 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3325 SILC_STATUS_OK, ident, 1,
3327 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3328 packet->data, packet->len, FALSE);
3329 silc_buffer_free(packet);
3332 silc_server_command_free(cmd);
3335 /* Checks that client has rights to add or remove channel modes. If any
3336 of the checks fails FALSE is returned. */
3338 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3339 SilcChannelClientEntry client,
3342 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3343 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3345 /* Check whether has rights to change anything */
3346 if (!is_op && !is_fo)
3349 /* Check whether has rights to change everything */
3353 /* We know that client is channel operator, check that they are not
3354 changing anything that requires channel founder rights. Rest of the
3355 modes are available automatically for channel operator. */
3357 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3358 if (is_op && !is_fo)
3361 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3362 if (is_op && !is_fo)
3367 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3368 if (is_op && !is_fo)
3371 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3372 if (is_op && !is_fo)
3377 if (mode & SILC_CHANNEL_MODE_CIPHER) {
3378 if (is_op && !is_fo)
3381 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3382 if (is_op && !is_fo)
3387 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3388 if (is_op && !is_fo)
3391 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3392 if (is_op && !is_fo)
3400 /* Server side command of CMODE. Changes channel mode */
3402 SILC_SERVER_CMD_FUNC(cmode)
3404 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3405 SilcServer server = cmd->server;
3406 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3407 SilcIDListData idata = (SilcIDListData)client;
3408 SilcChannelID *channel_id;
3409 SilcChannelEntry channel;
3410 SilcChannelClientEntry chl;
3411 SilcBuffer packet, cidp;
3412 unsigned char *tmp, *tmp_id, *tmp_mask;
3413 char *cipher = NULL, *hmac = NULL;
3414 uint32 mode_mask, tmp_len, tmp_len2;
3415 uint16 ident = silc_command_get_ident(cmd->payload);
3417 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CMODE, cmd, 2, 7);
3419 /* Get Channel ID */
3420 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3422 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3423 SILC_STATUS_ERR_NO_CHANNEL_ID);
3426 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3428 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3429 SILC_STATUS_ERR_NO_CHANNEL_ID);
3433 /* Get the channel mode mask */
3434 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3436 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3437 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3440 SILC_GET32_MSB(mode_mask, tmp_mask);
3442 /* Get channel entry */
3443 channel = silc_idlist_find_channel_by_id(server->local_list,
3446 channel = silc_idlist_find_channel_by_id(server->global_list,
3449 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3450 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3455 /* Check whether this client is on the channel */
3456 if (!silc_server_client_on_channel(client, channel)) {
3457 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3458 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3462 /* Get entry to the channel user list */
3463 silc_list_start(channel->user_list);
3464 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
3465 if (chl->client == client)
3468 /* Check that client has rights to change any requested channel modes */
3469 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3470 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3471 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3476 * Check the modes. Modes that requires nothing special operation are
3480 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3481 /* Channel uses private keys to protect traffic. Client(s) has set the
3482 key locally they want to use, server does not know that key. */
3483 /* Nothing interesting to do here */
3485 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3486 /* The mode is removed and we need to generate and distribute
3487 new channel key. Clients are not using private channel keys
3488 anymore after this. */
3490 /* Re-generate channel key */
3491 silc_server_create_channel_key(server, channel, 0);
3493 /* Send the channel key. This sends it to our local clients and if
3494 we are normal server to our router as well. */
3495 silc_server_send_channel_key(server, NULL, channel,
3496 server->server_type == SILC_ROUTER ?
3497 FALSE : !server->standalone);
3499 cipher = channel->channel_key->cipher->name;
3500 hmac = channel->hmac->hmac->name;
3504 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3505 /* User limit is set on channel */
3508 /* Get user limit */
3509 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3511 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3512 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3513 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3517 SILC_GET32_MSB(user_limit, tmp);
3518 channel->user_limit = user_limit;
3521 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3522 /* User limit mode is unset. Remove user limit */
3523 channel->user_limit = 0;
3526 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3527 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3528 /* Passphrase has been set to channel */
3530 /* Get the passphrase */
3531 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3533 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3534 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3538 /* Save the passphrase */
3539 channel->passphrase = strdup(tmp);
3542 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3543 /* Passphrase mode is unset. remove the passphrase */
3544 if (channel->passphrase) {
3545 silc_free(channel->passphrase);
3546 channel->passphrase = NULL;
3551 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3552 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3553 /* Cipher to use protect the traffic */
3556 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3558 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3559 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3563 /* Delete old cipher and allocate the new one */
3564 silc_cipher_free(channel->channel_key);
3565 if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
3566 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3567 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3571 /* Re-generate channel key */
3572 silc_server_create_channel_key(server, channel, 0);
3574 /* Send the channel key. This sends it to our local clients and if
3575 we are normal server to our router as well. */
3576 silc_server_send_channel_key(server, NULL, channel,
3577 server->server_type == SILC_ROUTER ?
3578 FALSE : !server->standalone);
3581 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3582 /* Cipher mode is unset. Remove the cipher and revert back to
3584 cipher = channel->cipher;
3586 /* Delete old cipher and allocate default one */
3587 silc_cipher_free(channel->channel_key);
3588 if (!silc_cipher_alloc(cipher ? cipher : "aes-256-cbc",
3589 &channel->channel_key)) {
3590 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3591 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3595 /* Re-generate channel key */
3596 silc_server_create_channel_key(server, channel, 0);
3598 /* Send the channel key. This sends it to our local clients and if
3599 we are normal server to our router as well. */
3600 silc_server_send_channel_key(server, NULL, channel,
3601 server->server_type == SILC_ROUTER ?
3602 FALSE : !server->standalone);
3606 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3607 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3608 /* HMAC to use protect the traffic */
3609 unsigned char hash[32];
3612 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3614 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3615 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3619 /* Delete old hmac and allocate the new one */
3620 silc_hmac_free(channel->hmac);
3621 if (!silc_hmac_alloc(hmac, NULL, &channel->hmac)) {
3622 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3623 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3627 /* Set the HMAC key out of current channel key. The client must do
3629 silc_hash_make(channel->hmac->hash, channel->key, channel->key_len / 8,
3631 silc_hmac_set_key(channel->hmac, hash,
3632 silc_hash_len(channel->hmac->hash));
3633 memset(hash, 0, sizeof(hash));
3636 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
3637 /* Hmac mode is unset. Remove the hmac and revert back to
3639 unsigned char hash[32];
3640 hmac = channel->hmac_name;
3642 /* Delete old hmac and allocate default one */
3643 silc_hmac_free(channel->hmac);
3644 if (!silc_hmac_alloc(hmac ? hmac : "hmac-sha1-96", NULL,
3646 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3647 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3651 /* Set the HMAC key out of current channel key. The client must do
3653 silc_hash_make(channel->hmac->hash, channel->key, channel->key_len / 8,
3655 silc_hmac_set_key(channel->hmac, hash,
3656 silc_hash_len(channel->hmac->hash));
3657 memset(hash, 0, sizeof(hash));
3661 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3662 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3663 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
3664 /* Set the founder authentication */
3665 SilcAuthPayload auth;
3667 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
3669 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3670 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3674 auth = silc_auth_payload_parse(tmp, tmp_len);
3676 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3677 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3681 /* Save the public key */
3682 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
3683 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
3686 channel->founder_method = silc_auth_get_method(auth);
3688 if (channel->founder_method == SILC_AUTH_PASSWORD) {
3689 tmp = silc_auth_get_data(auth, &tmp_len);
3690 channel->founder_passwd =
3691 silc_calloc(tmp_len + 1, sizeof(*channel->founder_passwd));
3692 memcpy(channel->founder_passwd, tmp, tmp_len);
3693 channel->founder_passwd_len = tmp_len;
3696 silc_auth_payload_free(auth);
3700 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3701 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3702 if (channel->founder_key)
3703 silc_pkcs_public_key_free(channel->founder_key);
3704 if (channel->founder_passwd) {
3705 silc_free(channel->founder_passwd);
3706 channel->founder_passwd = NULL;
3712 /* Finally, set the mode */
3713 channel->mode = mode_mask;
3715 /* Send CMODE_CHANGE notify */
3716 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3717 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3718 SILC_NOTIFY_TYPE_CMODE_CHANGE, 4,
3719 cidp->data, cidp->len,
3721 cipher, cipher ? strlen(cipher) : 0,
3722 hmac, hmac ? strlen(hmac) : 0);
3724 /* Set CMODE notify type to network */
3725 if (!server->standalone)
3726 silc_server_send_notify_cmode(server, server->router->connection,
3727 server->server_type == SILC_ROUTER ?
3728 TRUE : FALSE, channel,
3729 mode_mask, client->id, SILC_ID_CLIENT,
3733 /* Send command reply to sender */
3734 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3735 SILC_STATUS_OK, ident, 1,
3737 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3738 packet->data, packet->len, FALSE);
3740 silc_buffer_free(packet);
3741 silc_free(channel_id);
3745 silc_server_command_free(cmd);
3748 /* Server side of CUMODE command. Changes client's mode on a channel. */
3750 SILC_SERVER_CMD_FUNC(cumode)
3752 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3753 SilcServer server = cmd->server;
3754 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3755 SilcIDListData idata = (SilcIDListData)client;
3756 SilcChannelID *channel_id;
3757 SilcClientID *client_id;
3758 SilcChannelEntry channel;
3759 SilcClientEntry target_client;
3760 SilcChannelClientEntry chl;
3761 SilcBuffer packet, idp;
3762 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
3763 uint32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
3765 uint16 ident = silc_command_get_ident(cmd->payload);
3767 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 4);
3769 /* Get Channel ID */
3770 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3772 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3773 SILC_STATUS_ERR_NO_CHANNEL_ID);
3776 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
3778 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3779 SILC_STATUS_ERR_NO_CHANNEL_ID);
3783 /* Get channel entry */
3784 channel = silc_idlist_find_channel_by_id(server->local_list,
3787 channel = silc_idlist_find_channel_by_id(server->global_list,
3790 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3791 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3796 /* Check whether sender is on the channel */
3797 if (!silc_server_client_on_channel(client, channel)) {
3798 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3799 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3803 /* Check that client has rights to change other's rights */
3804 silc_list_start(channel->user_list);
3805 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3806 if (chl->client == client) {
3807 sender_mask = chl->mode;
3812 /* Get the target client's channel mode mask */
3813 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3815 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3816 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3819 SILC_GET32_MSB(target_mask, tmp_mask);
3821 /* Get target Client ID */
3822 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3824 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3825 SILC_STATUS_ERR_NO_CLIENT_ID);
3828 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
3830 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3831 SILC_STATUS_ERR_NO_CLIENT_ID);
3835 /* Get target client's entry */
3836 target_client = silc_idlist_find_client_by_id(server->local_list,
3838 if (!target_client) {
3839 target_client = silc_idlist_find_client_by_id(server->global_list,
3843 if (target_client != client &&
3844 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
3845 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
3846 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3847 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3851 /* Check whether target client is on the channel */
3852 if (target_client != client) {
3853 if (!silc_server_client_on_channel(target_client, channel)) {
3854 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3855 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
3859 /* Get entry to the channel user list */
3860 silc_list_start(channel->user_list);
3861 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
3862 if (chl->client == target_client)
3870 /* If the target client is founder, no one else can change their mode
3872 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
3873 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3874 SILC_STATUS_ERR_NOT_YOU);
3878 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
3879 /* The client tries to claim the founder rights. */
3880 unsigned char *tmp_auth;
3881 uint32 tmp_auth_len, auth_len;
3884 if (target_client != client) {
3885 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3886 SILC_STATUS_ERR_NOT_YOU);
3890 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
3891 !channel->founder_key) {
3892 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3893 SILC_STATUS_ERR_NOT_YOU);
3897 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
3899 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3900 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3904 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
3905 (void *)channel->founder_passwd : (void *)channel->founder_key);
3906 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
3907 channel->founder_passwd_len : 0);
3909 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
3910 channel->founder_method, auth, auth_len,
3911 idata->hash, client->id, SILC_ID_CLIENT)) {
3912 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3913 SILC_STATUS_ERR_AUTH_FAILED);
3917 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
3920 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3921 if (target_client == client) {
3922 /* Remove channel founder rights from itself */
3923 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3926 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3927 SILC_STATUS_ERR_NOT_YOU);
3933 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
3934 /* Promote to operator */
3935 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3936 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3937 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3938 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3939 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3943 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
3947 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
3948 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3949 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3950 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3951 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3955 /* Demote to normal user */
3956 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
3961 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3962 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3964 /* Send notify to channel, notify only if mode was actually changed. */
3966 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3967 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3968 idp->data, idp->len,
3972 /* Set CUMODE notify type to network */
3973 if (!server->standalone)
3974 silc_server_send_notify_cumode(server, server->router->connection,
3975 server->server_type == SILC_ROUTER ?
3976 TRUE : FALSE, channel,
3977 target_mask, client->id,
3978 SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
3980 SILC_ID_CLIENT_LEN);
3983 /* Send command reply to sender */
3984 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
3985 SILC_STATUS_OK, ident, 2,
3987 3, tmp_id, tmp_len);
3988 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3989 packet->data, packet->len, FALSE);
3991 silc_buffer_free(packet);
3992 silc_free(channel_id);
3993 silc_free(client_id);
3994 silc_buffer_free(idp);
3997 silc_server_command_free(cmd);
4000 /* Server side of KICK command. Kicks client out of channel. */
4002 SILC_SERVER_CMD_FUNC(kick)
4004 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4005 SilcServer server = cmd->server;
4006 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4007 SilcClientEntry target_client;
4008 SilcChannelID *channel_id;
4009 SilcClientID *client_id;
4010 SilcChannelEntry channel;
4011 SilcChannelClientEntry chl;
4014 unsigned char *tmp, *comment;
4016 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 3);
4018 /* Get Channel ID */
4019 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4021 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4022 SILC_STATUS_ERR_NO_CHANNEL_ID);
4025 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
4027 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4028 SILC_STATUS_ERR_NO_CHANNEL_ID);
4032 /* Get channel entry */
4033 channel = silc_idlist_find_channel_by_id(server->local_list,
4036 channel = silc_idlist_find_channel_by_id(server->local_list,
4039 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4040 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4045 /* Check whether sender is on the channel */
4046 if (!silc_server_client_on_channel(client, channel)) {
4047 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4048 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4052 /* Check that the kicker is channel operator or channel founder */
4053 silc_list_start(channel->user_list);
4054 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
4055 if (chl->client == client) {
4056 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4057 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4058 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4065 /* Get target Client ID */
4066 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4068 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4069 SILC_STATUS_ERR_NO_CLIENT_ID);
4072 client_id = silc_id_payload_parse_id(tmp, tmp_len);
4074 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4075 SILC_STATUS_ERR_NO_CLIENT_ID);
4079 /* Get target client's entry */
4080 target_client = silc_idlist_find_client_by_id(server->local_list,
4082 if (!target_client) {
4083 target_client = silc_idlist_find_client_by_id(server->global_list,
4087 /* Check that the target client is not channel founder. Channel founder
4088 cannot be kicked from the channel. */
4089 silc_list_start(channel->user_list);
4090 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
4091 if (chl->client == target_client) {
4092 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4093 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4094 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4101 /* Check whether target client is on the channel */
4102 if (!silc_server_client_on_channel(target_client, channel)) {
4103 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4104 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4110 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4114 /* Send command reply to sender */
4115 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4118 /* Send KICKED notify to local clients on the channel */
4119 idp = silc_id_payload_encode(target_client->id, SILC_ID_CLIENT);
4120 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4121 SILC_NOTIFY_TYPE_KICKED,
4123 idp->data, idp->len,
4124 comment, comment ? strlen(comment) : 0);
4125 silc_buffer_free(idp);
4127 /* Remove the client from the channel. If the channel does not exist
4128 after removing the client then the client kicked itself off the channel
4129 and we don't have to send anything after that. */
4130 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4131 target_client, FALSE))
4134 /* Send KICKED notify to primary route */
4135 if (!server->standalone)
4136 silc_server_send_notify_kicked(server, server->router->connection,
4137 server->server_type == SILC_ROUTER ?
4138 TRUE : FALSE, channel,
4139 target_client->id, SILC_ID_CLIENT_LEN,
4142 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4143 /* Re-generate channel key */
4144 silc_server_create_channel_key(server, channel, 0);
4146 /* Send the channel key to the channel. The key of course is not sent
4147 to the client who was kicked off the channel. */
4148 silc_server_send_channel_key(server, target_client->connection, channel,
4149 server->server_type == SILC_ROUTER ?
4150 FALSE : !server->standalone);
4154 silc_server_command_free(cmd);
4157 /* Server side of OPER command. Client uses this comand to obtain server
4158 operator privileges to this server/router. */
4160 SILC_SERVER_CMD_FUNC(oper)
4162 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4163 SilcServer server = cmd->server;
4164 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4165 unsigned char *username, *auth;
4167 SilcServerConfigSectionAdminConnection *admin;
4168 SilcIDListData idata = (SilcIDListData)client;
4170 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_OPER, cmd, 1, 2);
4172 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4175 /* Get the username */
4176 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4178 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4179 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4183 /* Get the admin configuration */
4184 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4185 username, client->nickname);
4187 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4188 username, client->nickname);
4190 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4191 SILC_STATUS_ERR_AUTH_FAILED);
4196 /* Get the authentication payload */
4197 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4199 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4200 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4204 /* Verify the authentication data */
4205 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4206 admin->auth_data, admin->auth_data_len,
4207 idata->hash, client->id, SILC_ID_CLIENT)) {
4208 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4209 SILC_STATUS_ERR_AUTH_FAILED);
4213 /* Client is now server operator */
4214 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4216 /* Send UMODE change to primary router */
4217 if (!server->standalone)
4218 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4219 client->id, SILC_ID_CLIENT_LEN,
4222 /* Send reply to the sender */
4223 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4227 silc_server_command_free(cmd);
4230 /* Server side of SILCOPER command. Client uses this comand to obtain router
4231 operator privileges to this router. */
4233 SILC_SERVER_CMD_FUNC(silcoper)
4235 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4236 SilcServer server = cmd->server;
4237 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4238 unsigned char *username, *auth;
4240 SilcServerConfigSectionAdminConnection *admin;
4241 SilcIDListData idata = (SilcIDListData)client;
4243 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4245 if (server->server_type == SILC_SERVER)
4248 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4251 /* Get the username */
4252 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4254 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4255 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4259 /* Get the admin configuration */
4260 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4261 username, client->nickname);
4263 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4264 username, client->nickname);
4266 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4267 SILC_STATUS_ERR_AUTH_FAILED);
4272 /* Get the authentication payload */
4273 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4275 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4276 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4280 /* Verify the authentication data */
4281 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4282 admin->auth_data, admin->auth_data_len,
4283 idata->hash, client->id, SILC_ID_CLIENT)) {
4284 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4285 SILC_STATUS_ERR_AUTH_FAILED);
4289 /* Client is now router operator */
4290 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4292 /* Send UMODE change to primary router */
4293 if (!server->standalone)
4294 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4295 client->id, SILC_ID_CLIENT_LEN,
4298 /* Send reply to the sender */
4299 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4303 silc_server_command_free(cmd);
4306 /* Server side command of CONNECT. Connects us to the specified remote
4307 server or router. */
4309 SILC_SERVER_CMD_FUNC(connect)
4311 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4312 SilcServer server = cmd->server;
4313 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4314 unsigned char *tmp, *host;
4316 uint32 port = SILC_PORT;
4318 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CONNECT, cmd, 1, 2);
4320 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4323 /* Check whether client has the permissions. */
4324 if (client->mode == SILC_UMODE_NONE) {
4325 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4326 SILC_STATUS_ERR_NO_SERVER_PRIV);
4330 if (server->server_type == SILC_ROUTER &&
4331 client->mode & SILC_UMODE_SERVER_OPERATOR) {
4332 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4333 SILC_STATUS_ERR_NO_ROUTER_PRIV);
4337 /* Get the remote server */
4338 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4340 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4341 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4346 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4348 SILC_GET32_MSB(port, tmp);
4350 /* Create the connection. It is done with timeout and is async. */
4351 silc_server_create_connection(server, host, port);
4353 /* Send reply to the sender */
4354 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4358 silc_server_command_free(cmd);
4361 /* Server side of command BAN. This is used to manage the ban list of the
4362 channel. To add clients and remove clients from the ban list. */
4364 SILC_SERVER_CMD_FUNC(ban)
4366 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4367 SilcServer server = cmd->server;
4368 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4370 SilcChannelEntry channel;
4371 SilcChannelClientEntry chl;
4372 SilcChannelID *channel_id = NULL;
4373 unsigned char *id, *add, *del;
4374 uint32 id_len, tmp_len;
4375 uint16 ident = silc_command_get_ident(cmd->payload);
4377 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4380 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_BAN, cmd, 0, 3);
4382 /* Get Channel ID */
4383 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4385 channel_id = silc_id_payload_parse_id(id, id_len);
4387 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4388 SILC_STATUS_ERR_NO_CHANNEL_ID);
4393 /* Get channel entry. The server must know about the channel since the
4394 client is expected to be on the channel. */
4395 channel = silc_idlist_find_channel_by_id(server->local_list,
4398 channel = silc_idlist_find_channel_by_id(server->global_list,
4401 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4402 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4407 /* Check whether this client is on the channel */
4408 if (!silc_server_client_on_channel(client, channel)) {
4409 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4410 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4414 /* Get entry to the channel user list */
4415 silc_list_start(channel->user_list);
4416 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
4417 if (chl->client == client)
4420 /* The client must be at least channel operator. */
4421 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4422 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4423 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4427 /* Get the new ban and add it to the ban list */
4428 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4430 if (!channel->ban_list)
4431 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4433 channel->ban_list = silc_realloc(channel->ban_list,
4434 sizeof(*channel->ban_list) *
4436 strlen(channel->ban_list) + 2));
4437 if (add[tmp_len - 1] == ',')
4438 add[tmp_len - 1] = '\0';
4440 strncat(channel->ban_list, add, tmp_len);
4441 strncat(channel->ban_list, ",", 1);
4444 /* Get the ban to be removed and remove it from the list */
4445 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4446 if (del && channel->ban_list) {
4447 char *start, *end, *n;
4449 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4450 silc_free(channel->ban_list);
4451 channel->ban_list = NULL;
4453 start = strstr(channel->ban_list, del);
4454 if (start && strlen(start) >= tmp_len) {
4455 end = start + tmp_len;
4456 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4457 strncat(n, channel->ban_list, start - channel->ban_list);
4458 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4460 silc_free(channel->ban_list);
4461 channel->ban_list = n;
4466 /* Send the BAN notify type to our primary router. */
4467 if (!server->standalone && (add || del))
4468 silc_server_send_notify_ban(server, server->router->connection,
4469 server->server_type == SILC_ROUTER ?
4470 TRUE : FALSE, channel, add, del);
4472 /* Send the reply back to the client */
4473 if (channel->ban_list)
4475 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4476 SILC_STATUS_OK, ident, 2,
4478 3, channel->ban_list,
4479 strlen(channel->ban_list) - 1);
4482 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4483 SILC_STATUS_OK, ident, 1,
4486 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4487 packet->data, packet->len, FALSE);
4489 silc_buffer_free(packet);
4493 silc_free(channel_id);
4494 silc_server_command_free(cmd);
4497 /* Server side command of CLOSE. Closes connection to a specified server. */
4499 SILC_SERVER_CMD_FUNC(close)
4501 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4502 SilcServer server = cmd->server;
4503 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4504 SilcServerEntry server_entry;
4505 SilcSocketConnection sock;
4508 unsigned char *name;
4509 uint32 port = SILC_PORT;
4511 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CLOSE, cmd, 1, 2);
4513 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4516 /* Check whether client has the permissions. */
4517 if (client->mode == SILC_UMODE_NONE) {
4518 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4519 SILC_STATUS_ERR_NO_SERVER_PRIV);
4523 /* Get the remote server */
4524 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4526 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4527 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4532 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4534 SILC_GET32_MSB(port, tmp);
4536 server_entry = silc_idlist_find_server_by_conn(server->local_list,
4538 if (!server_entry) {
4539 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4540 SILC_STATUS_ERR_NO_SERVER_ID);
4544 /* Send reply to the sender */
4545 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4548 /* Close the connection to the server */
4549 sock = (SilcSocketConnection)server_entry->connection;
4550 silc_server_free_sock_user_data(server, sock);
4551 silc_server_close_connection(server, sock);
4554 silc_server_command_free(cmd);
4557 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4558 active connections. */
4560 SILC_SERVER_CMD_FUNC(shutdown)
4562 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4563 SilcServer server = cmd->server;
4564 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4566 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4568 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4571 /* Check whether client has the permission. */
4572 if (client->mode == SILC_UMODE_NONE) {
4573 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4574 SILC_STATUS_ERR_NO_SERVER_PRIV);
4578 /* Send reply to the sender */
4579 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4582 /* Then, gracefully, or not, bring the server down. */
4583 silc_server_stop(server);
4587 silc_server_command_free(cmd);
4590 /* Server side command of LEAVE. Removes client from a channel. */
4592 SILC_SERVER_CMD_FUNC(leave)
4594 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4595 SilcServer server = cmd->server;
4596 SilcSocketConnection sock = cmd->sock;
4597 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4598 SilcChannelID *id = NULL;
4599 SilcChannelEntry channel;
4603 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
4605 /* Get Channel ID */
4606 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4608 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4609 SILC_STATUS_ERR_NO_CHANNEL_ID);
4612 id = silc_id_payload_parse_id(tmp, len);
4614 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4615 SILC_STATUS_ERR_NO_CHANNEL_ID);
4619 /* Get channel entry */
4620 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4622 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4624 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4625 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4630 /* Check whether this client is on the channel */
4631 if (!silc_server_client_on_channel(id_entry, channel)) {
4632 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4633 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4637 /* Notify routers that they should remove this client from their list
4638 of clients on the channel. Send LEAVE notify type. */
4639 if (!server->standalone)
4640 silc_server_send_notify_leave(server, server->router->connection,
4641 server->server_type == SILC_ROUTER ?
4642 TRUE : FALSE, channel, id_entry->id,
4643 SILC_ID_CLIENT_LEN);
4645 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4648 /* Remove client from channel */
4649 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4651 /* If the channel does not exist anymore we won't send anything */
4654 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4655 /* Re-generate channel key */
4656 silc_server_create_channel_key(server, channel, 0);
4658 /* Send the channel key */
4659 silc_server_send_channel_key(server, NULL, channel,
4660 server->server_type == SILC_ROUTER ?
4661 FALSE : !server->standalone);
4667 silc_server_command_free(cmd);
4670 /* Server side of command USERS. Resolves clients and their USERS currently
4671 joined on the requested channel. The list of Client ID's and their modes
4672 on the channel is sent back. */
4674 SILC_SERVER_CMD_FUNC(users)
4676 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4677 SilcServer server = cmd->server;
4678 SilcChannelEntry channel;
4681 unsigned char *channel_id;
4682 uint32 channel_id_len;
4683 SilcBuffer client_id_list;
4684 SilcBuffer client_mode_list;
4685 unsigned char lc[4];
4686 uint32 list_count = 0;
4687 uint16 ident = silc_command_get_ident(cmd->payload);
4689 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
4691 /* Get Channel ID */
4692 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4694 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4695 SILC_STATUS_ERR_NO_CHANNEL_ID);
4698 id = silc_id_payload_parse_id(channel_id, channel_id_len);
4700 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4701 SILC_STATUS_ERR_NO_CHANNEL_ID);
4705 /* If we are server and we don't know about this channel we will send
4706 the command to our router. If we know about the channel then we also
4707 have the list of users already. */
4708 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4710 if (server->server_type == SILC_SERVER && !server->standalone &&
4714 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
4715 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4717 /* Send USERS command */
4718 silc_server_packet_send(server, server->router->connection,
4719 SILC_PACKET_COMMAND, cmd->packet->flags,
4720 tmpbuf->data, tmpbuf->len, TRUE);
4722 /* Reprocess this packet after received reply */
4723 silc_server_command_pending(server, SILC_COMMAND_USERS,
4724 silc_command_get_ident(cmd->payload),
4725 silc_server_command_destructor,
4726 silc_server_command_users,
4727 silc_server_command_dup(cmd));
4728 cmd->pending = TRUE;
4729 silc_command_set_ident(cmd->payload, ident);
4731 silc_buffer_free(tmpbuf);
4736 /* We are router and we will check the global list as well. */
4737 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4739 /* Channel really does not exist */
4740 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4741 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4746 /* Get the users list */
4747 silc_server_get_users_on_channel(server, channel, &client_id_list,
4748 &client_mode_list, &list_count);
4751 SILC_PUT32_MSB(list_count, lc);
4754 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
4755 SILC_STATUS_OK, ident, 4,
4756 2, channel_id, channel_id_len,
4758 4, client_id_list->data,
4759 client_id_list->len,
4760 5, client_mode_list->data,
4761 client_mode_list->len);
4762 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4763 packet->data, packet->len, FALSE);
4765 silc_buffer_free(packet);
4766 silc_buffer_free(client_id_list);
4767 silc_buffer_free(client_mode_list);
4771 silc_server_command_free(cmd);
4774 /* Server side of command GETKEY. This fetches the client's public key
4775 from the server where to the client is connected. */
4777 SILC_SERVER_CMD_FUNC(getkey)
4779 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4780 SilcServer server = cmd->server;
4782 SilcClientEntry client;
4783 SilcServerEntry server_entry;
4784 SilcClientID *client_id = NULL;
4785 SilcServerID *server_id = NULL;
4786 SilcIDPayload idp = NULL;
4787 uint16 ident = silc_command_get_ident(cmd->payload);
4793 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4795 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4796 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4799 idp = silc_id_payload_parse_data(tmp, tmp_len);
4801 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4802 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4806 id_type = silc_id_payload_get_type(idp);
4807 if (id_type == SILC_ID_CLIENT) {
4808 client_id = silc_id_payload_get_id(idp);
4810 /* If the client is not found from local list there is no chance it
4811 would be locally connected client so send the command further. */
4812 client = silc_idlist_find_client_by_id(server->local_list,
4815 if ((!client && !cmd->pending && !server->standalone) ||
4816 (client && !client->connection)) {
4819 SilcSocketConnection dest_sock;
4821 dest_sock = silc_server_get_client_route(server, NULL, 0,
4826 old_ident = silc_command_get_ident(cmd->payload);
4827 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
4828 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4830 silc_server_packet_send(server, dest_sock,
4831 SILC_PACKET_COMMAND, cmd->packet->flags,
4832 tmpbuf->data, tmpbuf->len, TRUE);
4834 /* Reprocess this packet after received reply from router */
4835 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
4836 silc_command_get_ident(cmd->payload),
4837 silc_server_command_destructor,
4838 silc_server_command_getkey,
4839 silc_server_command_dup(cmd));
4840 cmd->pending = TRUE;
4842 silc_command_set_ident(cmd->payload, old_ident);
4843 silc_buffer_free(tmpbuf);
4847 if (!client && cmd->pending) {
4848 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4849 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
4853 /* The client is locally connected, just get the public key and
4855 tmp = silc_pkcs_public_key_encode(client->data.public_key, &tmp_len);
4856 pk = silc_buffer_alloc(4 + tmp_len);
4857 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
4858 silc_buffer_format(pk,
4859 SILC_STR_UI_SHORT(tmp_len),
4860 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
4861 SILC_STR_UI_XNSTRING(tmp, tmp_len),
4865 } else if (id_type == SILC_ID_SERVER) {
4866 server_id = silc_id_payload_get_id(idp);
4868 /* If the server is not found from local list there is no chance it
4869 would be locally connected server so send the command further. */
4870 server_entry = silc_idlist_find_server_by_id(server->local_list,
4873 if ((!server_entry && !cmd->pending && !server->standalone) ||
4874 (server_entry && !server_entry->connection)) {
4878 old_ident = silc_command_get_ident(cmd->payload);
4879 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
4880 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4882 silc_server_packet_send(server, server->router->connection,
4883 SILC_PACKET_COMMAND, cmd->packet->flags,
4884 tmpbuf->data, tmpbuf->len, TRUE);
4886 /* Reprocess this packet after received reply from router */
4887 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
4888 silc_command_get_ident(cmd->payload),
4889 silc_server_command_destructor,
4890 silc_server_command_getkey,
4891 silc_server_command_dup(cmd));
4892 cmd->pending = TRUE;
4894 silc_command_set_ident(cmd->payload, old_ident);
4895 silc_buffer_free(tmpbuf);
4899 if (!server_entry && cmd->pending) {
4900 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4901 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
4905 /* The client is locally connected, just get the public key and
4907 tmp = silc_pkcs_public_key_encode(server_entry->data.public_key, &tmp_len);
4908 pk = silc_buffer_alloc(4 + tmp_len);
4909 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
4910 silc_buffer_format(pk,
4911 SILC_STR_UI_SHORT(tmp_len),
4912 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
4913 SILC_STR_UI_XNSTRING(tmp, tmp_len),
4920 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4921 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
4922 SILC_STATUS_OK, ident, 2,
4924 3, pk->data, pk->len);
4925 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4926 packet->data, packet->len, FALSE);
4927 silc_buffer_free(packet);
4928 silc_buffer_free(pk);
4932 silc_id_payload_free(idp);
4933 silc_free(client_id);
4934 silc_free(server_id);
4935 silc_server_command_free(cmd);