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,
1766 /* Remove old cache entry */
1767 silc_idcache_del_by_context(server->local_list->clients, client);
1769 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1773 silc_free(client->id);
1775 /* Save the nickname as this client is our local client */
1776 if (client->nickname)
1777 silc_free(client->nickname);
1779 client->nickname = strdup(nick);
1780 client->id = new_id;
1782 /* Update client cache */
1783 silc_idcache_add(server->local_list->clients, client->nickname,
1784 client->id, (void *)client, FALSE);
1786 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1788 /* Send NICK_CHANGE notify to the client's channels */
1789 silc_server_send_notify_on_channels(server, NULL, client,
1790 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1791 oidp->data, oidp->len,
1792 nidp->data, nidp->len);
1794 /* Send the new Client ID as reply command back to client */
1795 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
1796 SILC_STATUS_OK, ident, 1,
1797 2, nidp->data, nidp->len);
1798 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1799 0, packet->data, packet->len, FALSE);
1801 silc_buffer_free(packet);
1802 silc_buffer_free(nidp);
1803 silc_buffer_free(oidp);
1806 silc_server_command_free(cmd);
1809 /* Sends the LIST command reply */
1812 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
1813 SilcChannelEntry *lch,
1815 SilcChannelEntry *gch,
1819 SilcBuffer packet, idp;
1820 SilcChannelEntry entry;
1821 SilcCommandStatus status;
1822 uint16 ident = silc_command_get_ident(cmd->payload);
1824 unsigned char usercount[4];
1827 for (i = 0; i < lch_count; i++)
1828 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
1830 for (i = 0; i < gch_count; i++)
1831 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
1834 status = SILC_STATUS_OK;
1835 if ((lch_count + gch_count) > 1)
1836 status = SILC_STATUS_LIST_START;
1839 for (i = 0; i < lch_count; i++) {
1846 status = SILC_STATUS_LIST_ITEM;
1848 if (i == lch_count - 1 && gch_count)
1850 if (lch_count > 1 && i == lch_count - 1)
1851 status = SILC_STATUS_LIST_END;
1853 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1855 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
1856 topic = "*private*";
1857 memset(usercount, 0, sizeof(usercount));
1859 topic = entry->topic;
1860 users = silc_list_count(entry->user_list);
1861 SILC_PUT32_MSB(users, usercount);
1864 /* Send the reply */
1867 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1869 2, idp->data, idp->len,
1870 3, entry->channel_name,
1871 strlen(entry->channel_name),
1872 4, topic, strlen(topic),
1876 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1878 2, idp->data, idp->len,
1879 3, entry->channel_name,
1880 strlen(entry->channel_name),
1882 silc_server_packet_send(cmd->server, cmd->sock,
1883 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
1884 packet->len, FALSE);
1885 silc_buffer_free(packet);
1886 silc_buffer_free(idp);
1889 status = i ? SILC_STATUS_LIST_ITEM : SILC_STATUS_OK;
1892 for (i = 0; i < gch_count; i++) {
1899 status = SILC_STATUS_LIST_ITEM;
1901 if (gch_count > 1 && i == lch_count - 1)
1902 status = SILC_STATUS_LIST_END;
1904 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1906 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
1907 topic = "*private*";
1908 memset(usercount, 0, sizeof(usercount));
1910 topic = entry->topic;
1911 users = silc_list_count(entry->user_list);
1912 SILC_PUT32_MSB(users, usercount);
1915 /* Send the reply */
1918 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1920 2, idp->data, idp->len,
1921 3, entry->channel_name,
1922 strlen(entry->channel_name),
1923 4, topic, strlen(topic),
1927 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1929 2, idp->data, idp->len,
1930 3, entry->channel_name,
1931 strlen(entry->channel_name),
1933 silc_server_packet_send(cmd->server, cmd->sock,
1934 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
1935 packet->len, FALSE);
1936 silc_buffer_free(packet);
1937 silc_buffer_free(idp);
1941 /* Server side of LIST command. This lists the channel of the requested
1942 server. Secret channels are not listed. */
1944 SILC_SERVER_CMD_FUNC(list)
1946 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1947 SilcServer server = cmd->server;
1948 SilcChannelID *channel_id = NULL;
1951 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
1952 uint32 lch_count = 0, gch_count = 0;
1954 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LIST, cmd, 0, 2);
1956 /* Get Channel ID */
1957 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1959 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1961 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
1962 SILC_STATUS_ERR_NO_CHANNEL_ID);
1967 /* Get the channels from local list */
1968 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
1971 /* Get the channels from global list if we are router */
1972 if (server->server_type == SILC_ROUTER)
1973 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
1976 /* Send the reply */
1977 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
1978 gchannels, gch_count);
1981 silc_server_command_free(cmd);
1984 /* Server side of TOPIC command. Sets topic for channel and/or returns
1985 current topic to client. */
1987 SILC_SERVER_CMD_FUNC(topic)
1989 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1990 SilcServer server = cmd->server;
1991 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1992 SilcChannelID *channel_id;
1993 SilcChannelEntry channel;
1994 SilcChannelClientEntry chl;
1995 SilcBuffer packet, idp;
1997 uint32 argc, tmp_len;
1998 uint16 ident = silc_command_get_ident(cmd->payload);
2000 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
2002 argc = silc_argument_get_arg_num(cmd->args);
2004 /* Get Channel ID */
2005 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2007 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2008 SILC_STATUS_ERR_NO_CHANNEL_ID);
2011 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2013 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2014 SILC_STATUS_ERR_NO_CHANNEL_ID);
2018 /* Check whether the channel exists */
2019 channel = silc_idlist_find_channel_by_id(server->local_list,
2022 channel = silc_idlist_find_channel_by_id(server->global_list,
2025 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2026 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2033 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2035 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2036 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2040 if (strlen(tmp) > 256) {
2041 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2042 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2046 /* See whether has rights to change topic */
2047 silc_list_start(channel->user_list);
2048 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2049 if (chl->client == client)
2052 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2053 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2054 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2055 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2060 /* Set the topic for channel */
2062 silc_free(channel->topic);
2063 channel->topic = strdup(tmp);
2065 /* Send TOPIC_SET notify type to the network */
2066 if (!server->standalone)
2067 silc_server_send_notify_topic_set(server, server->router->connection,
2068 server->server_type == SILC_ROUTER ?
2069 TRUE : FALSE, channel, client->id,
2072 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2074 /* Send notify about topic change to all clients on the channel */
2075 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2076 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2077 idp->data, idp->len,
2078 channel->topic, strlen(channel->topic));
2079 silc_buffer_free(idp);
2082 /* Send the topic to client as reply packet */
2083 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2085 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2086 SILC_STATUS_OK, ident, 2,
2087 2, idp->data, idp->len,
2089 strlen(channel->topic));
2091 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2092 SILC_STATUS_OK, ident, 1,
2093 2, idp->data, idp->len);
2094 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2095 0, packet->data, packet->len, FALSE);
2097 silc_buffer_free(packet);
2098 silc_buffer_free(idp);
2099 silc_free(channel_id);
2102 silc_server_command_free(cmd);
2105 /* Server side of INVITE command. Invites some client to join some channel.
2106 This command is also used to manage the invite list of the channel. */
2108 SILC_SERVER_CMD_FUNC(invite)
2110 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2111 SilcServer server = cmd->server;
2112 SilcSocketConnection sock = cmd->sock, dest_sock;
2113 SilcChannelClientEntry chl;
2114 SilcClientEntry sender, dest;
2115 SilcClientID *dest_id = NULL;
2116 SilcChannelEntry channel;
2117 SilcChannelID *channel_id = NULL;
2118 SilcIDListData idata;
2119 SilcBuffer idp, idp2, packet;
2120 unsigned char *tmp, *add, *del;
2122 uint16 ident = silc_command_get_ident(cmd->payload);
2124 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 4);
2126 /* Get Channel ID */
2127 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2129 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2130 SILC_STATUS_ERR_NO_CHANNEL_ID);
2133 channel_id = silc_id_payload_parse_id(tmp, len);
2135 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2136 SILC_STATUS_ERR_NO_CHANNEL_ID);
2140 /* Get the channel entry */
2141 channel = silc_idlist_find_channel_by_id(server->local_list,
2144 channel = silc_idlist_find_channel_by_id(server->global_list,
2147 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2148 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2153 /* Check whether the sender of this command is on the channel. */
2154 sender = (SilcClientEntry)sock->user_data;
2155 if (!silc_server_client_on_channel(sender, channel)) {
2156 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2157 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2161 /* Check whether the channel is invite-only channel. If yes then the
2162 sender of this command must be at least channel operator. */
2163 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2164 silc_list_start(channel->user_list);
2165 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2166 if (chl->client == sender) {
2167 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2168 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2169 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2176 /* Get destination client ID */
2177 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2181 dest_id = silc_id_payload_parse_id(tmp, len);
2183 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2184 SILC_STATUS_ERR_NO_CLIENT_ID);
2188 /* Get the client entry */
2189 dest = silc_server_get_client_resolve(server, dest_id);
2191 if (server->server_type == SILC_ROUTER) {
2192 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2193 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2197 /* The client info is being resolved. Reprocess this packet after
2198 receiving the reply to the query. */
2199 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2201 silc_server_command_destructor,
2202 silc_server_command_invite,
2203 silc_server_command_dup(cmd));
2204 cmd->pending = TRUE;
2205 silc_free(channel_id);
2210 /* Check whether the requested client is already on the channel. */
2211 if (silc_server_client_on_channel(dest, channel)) {
2212 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2213 SILC_STATUS_ERR_USER_ON_CHANNEL);
2217 /* Get route to the client */
2218 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2220 memset(invite, 0, sizeof(invite));
2221 strncat(invite, dest->nickname, strlen(dest->nickname));
2222 strncat(invite, "!", 1);
2223 strncat(invite, dest->username, strlen(dest->username));
2224 if (!strchr(dest->username, '@')) {
2225 strncat(invite, "@", 1);
2226 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2229 len = strlen(invite);
2230 if (!channel->invite_list)
2231 channel->invite_list = silc_calloc(len + 2,
2232 sizeof(*channel->invite_list));
2234 channel->invite_list = silc_realloc(channel->invite_list,
2235 sizeof(*channel->invite_list) *
2237 strlen(channel->invite_list) + 2));
2238 strncat(channel->invite_list, invite, len);
2239 strncat(channel->invite_list, ",", 1);
2241 /* Send notify to the client that is invited to the channel */
2242 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2243 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2244 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2246 SILC_NOTIFY_TYPE_INVITE, 3,
2247 idp->data, idp->len,
2248 channel->channel_name,
2249 strlen(channel->channel_name),
2250 idp2->data, idp2->len);
2251 silc_buffer_free(idp);
2252 silc_buffer_free(idp2);
2255 /* Add the client to the invite list of the channel */
2256 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2258 if (!channel->invite_list)
2259 channel->invite_list = silc_calloc(len + 2,
2260 sizeof(*channel->invite_list));
2262 channel->invite_list = silc_realloc(channel->invite_list,
2263 sizeof(*channel->invite_list) *
2265 strlen(channel->invite_list) + 2));
2266 if (add[len - 1] == ',')
2267 add[len - 1] = '\0';
2269 strncat(channel->invite_list, add, len);
2270 strncat(channel->invite_list, ",", 1);
2273 /* Get the invite to be removed and remove it from the list */
2274 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2275 if (del && channel->invite_list) {
2276 char *start, *end, *n;
2278 if (!strncmp(channel->invite_list, del,
2279 strlen(channel->invite_list) - 1)) {
2280 silc_free(channel->invite_list);
2281 channel->invite_list = NULL;
2283 start = strstr(channel->invite_list, del);
2284 if (start && strlen(start) >= len) {
2286 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2287 strncat(n, channel->invite_list, start - channel->invite_list);
2288 strncat(n, end + 1, ((channel->invite_list +
2289 strlen(channel->invite_list)) - end) - 1);
2290 silc_free(channel->invite_list);
2291 channel->invite_list = n;
2296 /* Send notify to the primary router */
2297 if (!server->standalone)
2298 silc_server_send_notify_invite(server, server->router->connection,
2299 server->server_type == SILC_ROUTER ?
2300 TRUE : FALSE, channel,
2301 sender->id, add, del);
2303 /* Send command reply */
2304 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2305 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2306 SILC_STATUS_OK, ident, 2,
2308 3, channel->invite_list,
2309 channel->invite_list ?
2310 strlen(channel->invite_list) :
2312 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2313 packet->data, packet->len, FALSE);
2314 silc_buffer_free(packet);
2320 silc_free(channel_id);
2321 silc_server_command_free(cmd);
2326 SilcSocketConnection sock;
2330 /* Quits connection to client. This gets called if client won't
2331 close the connection even when it has issued QUIT command. */
2333 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2335 QuitInternal q = (QuitInternal)context;
2337 /* Free all client specific data, such as client entry and entires
2338 on channels this client may be on. */
2339 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2341 q->sock->user_data = NULL;
2343 /* Close the connection on our side */
2344 silc_server_close_connection(q->server, q->sock);
2346 silc_free(q->signoff);
2350 /* Quits SILC session. This is the normal way to disconnect client. */
2352 SILC_SERVER_CMD_FUNC(quit)
2354 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2355 SilcServer server = cmd->server;
2356 SilcSocketConnection sock = cmd->sock;
2358 unsigned char *tmp = NULL;
2361 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_QUIT, cmd, 0, 1);
2363 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2366 /* Get destination ID */
2367 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2371 q = silc_calloc(1, sizeof(*q));
2374 q->signoff = tmp ? strdup(tmp) : NULL;
2376 /* We quit the connection with little timeout */
2377 silc_task_register(server->timeout_queue, sock->sock,
2378 silc_server_command_quit_cb, (void *)q,
2379 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2382 silc_server_command_free(cmd);
2385 /* Server side of command KILL. This command is used by router operator
2386 to remove an client from the SILC Network temporarily. */
2388 SILC_SERVER_CMD_FUNC(kill)
2390 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2391 SilcServer server = cmd->server;
2392 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2393 SilcClientEntry remote_client;
2394 SilcClientID *client_id;
2395 unsigned char *tmp, *comment;
2396 uint32 tmp_len, tmp_len2;
2398 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_KILL, cmd, 1, 2);
2400 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2403 /* KILL command works only on router */
2404 if (server->server_type != SILC_ROUTER) {
2405 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2406 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2410 /* Check whether client has the permissions. */
2411 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2412 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2413 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2417 /* Get the client ID */
2418 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2420 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2421 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2424 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2426 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2427 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2431 /* Get the client entry */
2432 remote_client = silc_idlist_find_client_by_id(server->local_list,
2434 if (!remote_client) {
2435 remote_client = silc_idlist_find_client_by_id(server->global_list,
2437 if (!remote_client) {
2438 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2439 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2445 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2449 /* Send reply to the sender */
2450 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2453 /* Send the KILL notify packets. First send it to the channel, then
2454 to our primary router and then directly to the client who is being
2455 killed right now. */
2457 /* Send KILLED notify to the channels. It is not sent to the client
2458 as it will be sent differently destined directly to the client and not
2460 silc_server_send_notify_on_channels(server, remote_client,
2461 remote_client, SILC_NOTIFY_TYPE_KILLED,
2464 comment, comment ? tmp_len2 : 0);
2466 /* Send KILLED notify to primary route */
2467 if (!server->standalone)
2468 silc_server_send_notify_killed(server, server->router->connection, TRUE,
2469 remote_client->id, comment);
2471 /* Send KILLED notify to the client directly */
2472 silc_server_send_notify_killed(server, remote_client->connection ?
2473 remote_client->connection :
2474 remote_client->router->connection, FALSE,
2475 remote_client->id, comment);
2477 /* Remove the client from all channels. This generates new keys to the
2478 channels as well. */
2479 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2482 /* Remove the client entry, If it is locally connected then we will also
2483 disconnect the client here */
2484 if (remote_client->data.registered && remote_client->connection) {
2485 /* Remove locally conneted client */
2486 SilcSocketConnection sock = remote_client->connection;
2487 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2488 silc_server_close_connection(server, sock);
2490 /* Remove remote client */
2491 if (!silc_idlist_del_client(server->global_list, remote_client))
2492 silc_idlist_del_client(server->local_list, remote_client);
2496 silc_server_command_free(cmd);
2499 /* Server side of command INFO. This sends information about us to
2500 the client. If client requested specific server we will send the
2501 command to that server. */
2503 SILC_SERVER_CMD_FUNC(info)
2505 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2506 SilcServer server = cmd->server;
2507 SilcBuffer packet, idp;
2510 char *dest_server, *server_info = NULL, *server_name;
2511 uint16 ident = silc_command_get_ident(cmd->payload);
2512 SilcServerEntry entry = NULL;
2513 SilcServerID *server_id = NULL;
2515 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 0, 2);
2517 /* Get server name */
2518 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2521 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2523 server_id = silc_id_payload_parse_id(tmp, tmp_len);
2525 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2526 SILC_STATUS_ERR_NO_SERVER_ID);
2532 /* Check whether we have this server cached */
2533 entry = silc_idlist_find_server_by_id(server->local_list,
2536 entry = silc_idlist_find_server_by_id(server->global_list,
2538 if (!entry && server->server_type == SILC_ROUTER) {
2539 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2540 SILC_STATUS_ERR_NO_SUCH_SERVER);
2546 if ((!dest_server && !server_id) ||
2547 (dest_server && !cmd->pending &&
2548 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2549 /* Send our reply */
2550 char info_string[256];
2552 memset(info_string, 0, sizeof(info_string));
2553 snprintf(info_string, sizeof(info_string),
2554 "location: %s server: %s admin: %s <%s>",
2555 server->config->admin_info->location,
2556 server->config->admin_info->server_type,
2557 server->config->admin_info->admin_name,
2558 server->config->admin_info->admin_email);
2560 server_info = info_string;
2561 entry = server->id_entry;
2563 /* Check whether we have this server cached */
2564 if (!entry && dest_server) {
2565 entry = silc_idlist_find_server_by_name(server->global_list,
2568 entry = silc_idlist_find_server_by_name(server->local_list,
2573 if (!cmd->pending &&
2574 server->server_type == SILC_ROUTER && entry && !entry->server_info) {
2575 /* Send to the server */
2579 old_ident = silc_command_get_ident(cmd->payload);
2580 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2581 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2583 silc_server_packet_send(server, entry->connection,
2584 SILC_PACKET_COMMAND, cmd->packet->flags,
2585 tmpbuf->data, tmpbuf->len, TRUE);
2587 /* Reprocess this packet after received reply from router */
2588 silc_server_command_pending(server, SILC_COMMAND_INFO,
2589 silc_command_get_ident(cmd->payload),
2590 silc_server_command_destructor,
2591 silc_server_command_info,
2592 silc_server_command_dup(cmd));
2593 cmd->pending = TRUE;
2594 silc_command_set_ident(cmd->payload, old_ident);
2595 silc_buffer_free(tmpbuf);
2599 if (!entry && !cmd->pending && !server->standalone) {
2600 /* Send to the primary router */
2604 old_ident = silc_command_get_ident(cmd->payload);
2605 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2606 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2608 silc_server_packet_send(server, server->router->connection,
2609 SILC_PACKET_COMMAND, cmd->packet->flags,
2610 tmpbuf->data, tmpbuf->len, TRUE);
2612 /* Reprocess this packet after received reply from router */
2613 silc_server_command_pending(server, SILC_COMMAND_INFO,
2614 silc_command_get_ident(cmd->payload),
2615 silc_server_command_destructor,
2616 silc_server_command_info,
2617 silc_server_command_dup(cmd));
2618 cmd->pending = TRUE;
2619 silc_command_set_ident(cmd->payload, old_ident);
2620 silc_buffer_free(tmpbuf);
2626 silc_free(server_id);
2629 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2630 SILC_STATUS_ERR_NO_SUCH_SERVER);
2634 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2636 server_info = entry->server_info;
2637 server_name = entry->server_name;
2639 /* Send the reply */
2640 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2641 SILC_STATUS_OK, ident, 3,
2642 2, idp->data, idp->len,
2644 strlen(server_name),
2646 strlen(server_info));
2647 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2648 packet->data, packet->len, FALSE);
2650 silc_buffer_free(packet);
2651 silc_buffer_free(idp);
2654 silc_server_command_free(cmd);
2657 /* Server side of command PING. This just replies to the ping. */
2659 SILC_SERVER_CMD_FUNC(ping)
2661 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2662 SilcServer server = cmd->server;
2667 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
2670 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2672 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2673 SILC_STATUS_ERR_NO_SERVER_ID);
2676 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2680 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2681 /* Send our reply */
2682 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2685 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2686 SILC_STATUS_ERR_NO_SUCH_SERVER);
2693 silc_server_command_free(cmd);
2696 /* Internal routine to join channel. The channel sent to this function
2697 has been either created or resolved from ID lists. This joins the sent
2698 client to the channel. */
2700 static void silc_server_command_join_channel(SilcServer server,
2701 SilcServerCommandContext cmd,
2702 SilcChannelEntry channel,
2703 SilcClientID *client_id,
2707 SilcSocketConnection sock = cmd->sock;
2709 uint32 tmp_len, user_count;
2710 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
2711 SilcClientEntry client;
2712 SilcChannelClientEntry chl;
2713 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
2714 uint16 ident = silc_command_get_ident(cmd->payload);
2717 SILC_LOG_DEBUG(("Start"));
2722 /* Get the client entry */
2723 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2724 client = (SilcClientEntry)sock->user_data;
2726 client = silc_idlist_find_client_by_id(server->local_list, client_id,
2733 * Check channel modes
2736 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2737 strncat(check, client->nickname, strlen(client->nickname));
2738 if (!strchr(client->nickname, '@')) {
2739 strncat(check, "@", 1);
2740 strncat(check, server->server_name, strlen(server->server_name));
2742 strncat(check, "!", 1);
2743 strncat(check, client->username, strlen(client->username));
2744 if (!strchr(client->username, '@')) {
2745 strncat(check, "@", 1);
2746 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
2750 /* Check invite list if channel is invite-only channel */
2751 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
2752 channel->mode & SILC_CHANNEL_MODE_INVITE) {
2753 if (!channel->invite_list) {
2754 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2755 SILC_STATUS_ERR_NOT_INVITED);
2759 if (!silc_string_match(channel->invite_list, check)) {
2760 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2761 SILC_STATUS_ERR_NOT_INVITED);
2766 /* Check ban list if it exists. If the client's nickname, server,
2767 username and/or hostname is in the ban list the access to the
2768 channel is denied. */
2769 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && channel->ban_list) {
2770 if (silc_string_match(channel->ban_list, check)) {
2771 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2772 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
2777 /* Get passphrase */
2778 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2780 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
2781 memcpy(passphrase, tmp, tmp_len);
2784 /* Check the channel passphrase if set. */
2785 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2786 if (!passphrase || memcmp(channel->passphrase, passphrase,
2787 strlen(channel->passphrase))) {
2788 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2789 SILC_STATUS_ERR_BAD_PASSWORD);
2794 /* Check user count limit if set. */
2795 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
2796 if (silc_list_count(channel->user_list) + 1 >
2797 channel->user_limit) {
2798 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2799 SILC_STATUS_ERR_CHANNEL_IS_FULL);
2805 * Client is allowed to join to the channel. Make it happen.
2808 /* Check whether the client already is on the channel */
2809 if (silc_server_client_on_channel(client, channel)) {
2810 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2811 SILC_STATUS_ERR_USER_ON_CHANNEL);
2815 /* Generate new channel key as protocol dictates */
2816 if ((!created && silc_list_count(channel->user_list) > 0) ||
2817 !channel->channel_key)
2818 silc_server_create_channel_key(server, channel, 0);
2820 /* Send the channel key. This is broadcasted to the channel but is not
2821 sent to the client who is joining to the channel. */
2822 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
2823 silc_server_send_channel_key(server, NULL, channel,
2824 server->server_type == SILC_ROUTER ?
2825 FALSE : !server->standalone);
2827 /* Join the client to the channel by adding it to channel's user list.
2828 Add also the channel to client entry's channels list for fast cross-
2830 chl = silc_calloc(1, sizeof(*chl));
2832 chl->client = client;
2833 chl->channel = channel;
2834 silc_list_add(channel->user_list, chl);
2835 silc_list_add(client->channels, chl);
2837 /* Get users on the channel */
2838 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
2841 /* Encode Client ID Payload of the original client who wants to join */
2842 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2844 /* Encode command reply packet */
2845 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2846 SILC_PUT32_MSB(channel->mode, mode);
2847 SILC_PUT32_MSB(created, tmp2);
2848 SILC_PUT32_MSB(user_count, tmp3);
2850 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
2851 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
2852 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
2853 strlen(channel->channel_key->
2855 channel->channel_key->cipher->name,
2856 channel->key_len / 8, channel->key);
2861 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2862 SILC_STATUS_OK, ident, 13,
2863 2, channel->channel_name,
2864 strlen(channel->channel_name),
2865 3, chidp->data, chidp->len,
2866 4, clidp->data, clidp->len,
2869 7, keyp ? keyp->data : NULL,
2870 keyp ? keyp->len : 0,
2871 8, channel->ban_list,
2873 strlen(channel->ban_list) : 0,
2874 9, channel->invite_list,
2875 channel->invite_list ?
2876 strlen(channel->invite_list) : 0,
2879 strlen(channel->topic) : 0,
2880 11, channel->hmac->hmac->name,
2881 strlen(channel->hmac->hmac->name),
2883 13, user_list->data, user_list->len,
2884 14, mode_list->data,
2887 /* Send command reply */
2888 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
2889 reply->data, reply->len, FALSE);
2891 if (!cmd->pending) {
2892 /* Send JOIN notify to locally connected clients on the channel */
2893 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2894 SILC_NOTIFY_TYPE_JOIN, 2,
2895 clidp->data, clidp->len,
2896 chidp->data, chidp->len);
2898 /* Send JOIN notify packet to our primary router */
2899 if (!server->standalone)
2900 silc_server_send_notify_join(server, server->router->connection,
2901 server->server_type == SILC_ROUTER ?
2902 TRUE : FALSE, channel, client->id);
2905 silc_buffer_free(reply);
2906 silc_buffer_free(clidp);
2907 silc_buffer_free(chidp);
2908 silc_buffer_free(keyp);
2909 silc_buffer_free(user_list);
2910 silc_buffer_free(mode_list);
2914 silc_free(passphrase);
2917 /* Server side of command JOIN. Joins client into requested channel. If
2918 the channel does not exist it will be created. */
2920 SILC_SERVER_CMD_FUNC(join)
2922 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2923 SilcServer server = cmd->server;
2925 char *tmp, *channel_name = NULL, *cipher, *hmac;
2926 SilcChannelEntry channel;
2928 int created = FALSE;
2929 SilcClientID *client_id;
2931 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
2933 /* Get channel name */
2934 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2936 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2937 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2942 if (strlen(channel_name) > 256)
2943 channel_name[255] = '\0';
2945 if (silc_server_command_bad_chars(channel_name) == TRUE) {
2946 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2947 SILC_STATUS_ERR_BAD_CHANNEL);
2948 silc_free(channel_name);
2952 /* Get Client ID of the client who is joining to the channel */
2953 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2955 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2956 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2959 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2961 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2962 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2966 /* Get cipher and hmac name */
2967 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2968 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2970 /* See if the channel exists */
2971 channel = silc_idlist_find_channel_by_name(server->local_list,
2972 channel_name, NULL);
2974 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2975 /* If this is coming from client the Client ID in the command packet must
2976 be same as the client's ID. */
2977 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2978 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2979 if (!SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
2980 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2981 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2986 if (!channel || !channel->id) {
2987 /* Channel not found */
2989 /* If we are standalone server we don't have a router, we just create
2990 the channel by ourselves. */
2991 if (server->standalone) {
2992 channel = silc_server_create_new_channel(server, server->id, cipher,
2993 hmac, channel_name, TRUE);
2995 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2996 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3000 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3005 /* The channel does not exist on our server. If we are normal server
3006 we will send JOIN command to our router which will handle the
3007 joining procedure (either creates the channel if it doesn't exist
3008 or joins the client to it). */
3009 if (server->server_type == SILC_SERVER) {
3013 old_ident = silc_command_get_ident(cmd->payload);
3014 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3015 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3017 /* Send JOIN command to our router */
3018 silc_server_packet_send(server, (SilcSocketConnection)
3019 server->router->connection,
3020 SILC_PACKET_COMMAND, cmd->packet->flags,
3021 tmpbuf->data, tmpbuf->len, TRUE);
3023 /* Reprocess this packet after received reply from router */
3024 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3025 silc_command_get_ident(cmd->payload),
3026 silc_server_command_destructor,
3027 silc_server_command_join,
3028 silc_server_command_dup(cmd));
3029 cmd->pending = TRUE;
3033 /* We are router and the channel does not seem exist so we will check
3034 our global list as well for the channel. */
3035 channel = silc_idlist_find_channel_by_name(server->global_list,
3036 channel_name, NULL);
3038 /* Channel really does not exist, create it */
3039 channel = silc_server_create_new_channel(server, server->id, cipher,
3040 hmac, channel_name, TRUE);
3042 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3043 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3047 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3054 /* Channel not found */
3056 /* If the command came from router and/or we are normal server then
3057 something went wrong with the joining as the channel was not found.
3058 We can't do anything else but ignore this. */
3059 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3060 server->server_type == SILC_SERVER)
3063 /* We are router and the channel does not seem exist so we will check
3064 our global list as well for the channel. */
3065 channel = silc_idlist_find_channel_by_name(server->global_list,
3066 channel_name, NULL);
3068 /* Channel really does not exist, create it */
3069 channel = silc_server_create_new_channel(server, server->id, cipher,
3070 hmac, channel_name, TRUE);
3072 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3073 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3077 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3083 /* If the channel does not have global users and is also empty it means the
3084 channel was created globally (by our router) and the client will be the
3085 channel founder and operator. */
3086 if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
3087 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3088 created = TRUE; /* Created globally by our router */
3091 /* Join to the channel */
3092 silc_server_command_join_channel(server, cmd, channel, client_id,
3095 silc_free(client_id);
3098 silc_server_command_free(cmd);
3101 /* Server side of command MOTD. Sends server's current "message of the
3102 day" to the client. */
3104 SILC_SERVER_CMD_FUNC(motd)
3106 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3107 SilcServer server = cmd->server;
3108 SilcBuffer packet, idp;
3109 char *motd, *dest_server;
3111 uint16 ident = silc_command_get_ident(cmd->payload);
3113 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 1);
3115 /* Get server name */
3116 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3118 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3119 SILC_STATUS_ERR_NO_SUCH_SERVER);
3123 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3126 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3128 if (server->config && server->config->motd &&
3129 server->config->motd->motd_file) {
3131 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
3136 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3137 SILC_STATUS_OK, ident, 2,
3143 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3144 SILC_STATUS_OK, ident, 1,
3148 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3149 packet->data, packet->len, FALSE);
3150 silc_buffer_free(packet);
3151 silc_buffer_free(idp);
3153 SilcServerEntry entry;
3155 /* Check whether we have this server cached */
3156 entry = silc_idlist_find_server_by_name(server->global_list,
3159 entry = silc_idlist_find_server_by_name(server->local_list,
3163 if (server->server_type == SILC_ROUTER && !cmd->pending &&
3164 entry && !entry->motd) {
3165 /* Send to the server */
3169 old_ident = silc_command_get_ident(cmd->payload);
3170 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3171 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3173 silc_server_packet_send(server, entry->connection,
3174 SILC_PACKET_COMMAND, cmd->packet->flags,
3175 tmpbuf->data, tmpbuf->len, TRUE);
3177 /* Reprocess this packet after received reply from router */
3178 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3179 silc_command_get_ident(cmd->payload),
3180 silc_server_command_destructor,
3181 silc_server_command_motd,
3182 silc_server_command_dup(cmd));
3183 cmd->pending = TRUE;
3184 silc_command_set_ident(cmd->payload, old_ident);
3185 silc_buffer_free(tmpbuf);
3189 if (!entry && !cmd->pending && !server->standalone) {
3190 /* Send to the primary router */
3194 old_ident = silc_command_get_ident(cmd->payload);
3195 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3196 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3198 silc_server_packet_send(server, server->router->connection,
3199 SILC_PACKET_COMMAND, cmd->packet->flags,
3200 tmpbuf->data, tmpbuf->len, TRUE);
3202 /* Reprocess this packet after received reply from router */
3203 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3204 silc_command_get_ident(cmd->payload),
3205 silc_server_command_destructor,
3206 silc_server_command_motd,
3207 silc_server_command_dup(cmd));
3208 cmd->pending = TRUE;
3209 silc_command_set_ident(cmd->payload, old_ident);
3210 silc_buffer_free(tmpbuf);
3215 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3216 SILC_STATUS_ERR_NO_SUCH_SERVER);
3220 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3223 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3224 SILC_STATUS_OK, ident, 2,
3227 strlen(entry->motd));
3229 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3230 SILC_STATUS_OK, ident, 1,
3233 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3234 packet->data, packet->len, FALSE);
3235 silc_buffer_free(packet);
3236 silc_buffer_free(idp);
3240 silc_server_command_free(cmd);
3243 /* Server side of command UMODE. Client can use this command to set/unset
3244 user mode. Client actually cannot set itself to be as server/router
3245 operator so this can be used only to unset the modes. */
3247 SILC_SERVER_CMD_FUNC(umode)
3249 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3250 SilcServer server = cmd->server;
3251 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3253 unsigned char *tmp_mask;
3255 uint16 ident = silc_command_get_ident(cmd->payload);
3257 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3260 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_UMODE, cmd, 2, 2);
3262 /* Get the client's mode mask */
3263 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3265 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3266 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3269 SILC_GET32_MSB(mask, tmp_mask);
3275 if (mask & SILC_UMODE_SERVER_OPERATOR) {
3276 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR)) {
3277 /* Cannot operator mode */
3278 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3279 SILC_STATUS_ERR_PERM_DENIED);
3283 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
3284 /* Remove the server operator rights */
3285 client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3288 if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3289 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
3290 /* Cannot operator mode */
3291 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3292 SILC_STATUS_ERR_PERM_DENIED);
3296 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
3297 /* Remove the router operator rights */
3298 client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3301 if (mask & SILC_UMODE_GONE) {
3302 client->mode |= SILC_UMODE_GONE;
3304 if (client->mode & SILC_UMODE_GONE)
3305 /* Remove the gone status */
3306 client->mode &= ~SILC_UMODE_GONE;
3309 /* Send UMODE change to primary router */
3310 if (!server->standalone)
3311 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3312 client->id, client->mode);
3314 /* Send command reply to sender */
3315 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3316 SILC_STATUS_OK, ident, 1,
3318 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3319 packet->data, packet->len, FALSE);
3320 silc_buffer_free(packet);
3323 silc_server_command_free(cmd);
3326 /* Checks that client has rights to add or remove channel modes. If any
3327 of the checks fails FALSE is returned. */
3329 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3330 SilcChannelClientEntry client,
3333 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3334 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3336 /* Check whether has rights to change anything */
3337 if (!is_op && !is_fo)
3340 /* Check whether has rights to change everything */
3344 /* We know that client is channel operator, check that they are not
3345 changing anything that requires channel founder rights. Rest of the
3346 modes are available automatically for channel operator. */
3348 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3349 if (is_op && !is_fo)
3352 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3353 if (is_op && !is_fo)
3358 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3359 if (is_op && !is_fo)
3362 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3363 if (is_op && !is_fo)
3368 if (mode & SILC_CHANNEL_MODE_CIPHER) {
3369 if (is_op && !is_fo)
3372 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3373 if (is_op && !is_fo)
3378 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3379 if (is_op && !is_fo)
3382 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3383 if (is_op && !is_fo)
3391 /* Server side command of CMODE. Changes channel mode */
3393 SILC_SERVER_CMD_FUNC(cmode)
3395 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3396 SilcServer server = cmd->server;
3397 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3398 SilcIDListData idata = (SilcIDListData)client;
3399 SilcChannelID *channel_id;
3400 SilcChannelEntry channel;
3401 SilcChannelClientEntry chl;
3402 SilcBuffer packet, cidp;
3403 unsigned char *tmp, *tmp_id, *tmp_mask;
3404 char *cipher = NULL, *hmac = NULL;
3405 uint32 mode_mask, tmp_len, tmp_len2;
3406 uint16 ident = silc_command_get_ident(cmd->payload);
3408 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CMODE, cmd, 2, 7);
3410 /* Get Channel ID */
3411 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3413 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3414 SILC_STATUS_ERR_NO_CHANNEL_ID);
3417 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3419 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3420 SILC_STATUS_ERR_NO_CHANNEL_ID);
3424 /* Get the channel mode mask */
3425 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3427 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3428 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3431 SILC_GET32_MSB(mode_mask, tmp_mask);
3433 /* Get channel entry */
3434 channel = silc_idlist_find_channel_by_id(server->local_list,
3437 channel = silc_idlist_find_channel_by_id(server->global_list,
3440 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3441 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3446 /* Check whether this client is on the channel */
3447 if (!silc_server_client_on_channel(client, channel)) {
3448 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3449 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3453 /* Get entry to the channel user list */
3454 silc_list_start(channel->user_list);
3455 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
3456 if (chl->client == client)
3459 /* Check that client has rights to change any requested channel modes */
3460 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3461 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3462 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3467 * Check the modes. Modes that requires nothing special operation are
3471 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3472 /* Channel uses private keys to protect traffic. Client(s) has set the
3473 key locally they want to use, server does not know that key. */
3474 /* Nothing interesting to do here */
3476 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3477 /* The mode is removed and we need to generate and distribute
3478 new channel key. Clients are not using private channel keys
3479 anymore after this. */
3481 /* Re-generate channel key */
3482 silc_server_create_channel_key(server, channel, 0);
3484 /* Send the channel key. This sends it to our local clients and if
3485 we are normal server to our router as well. */
3486 silc_server_send_channel_key(server, NULL, channel,
3487 server->server_type == SILC_ROUTER ?
3488 FALSE : !server->standalone);
3490 cipher = channel->channel_key->cipher->name;
3491 hmac = channel->hmac->hmac->name;
3495 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3496 /* User limit is set on channel */
3499 /* Get user limit */
3500 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3502 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3503 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3504 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3508 SILC_GET32_MSB(user_limit, tmp);
3509 channel->user_limit = user_limit;
3512 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3513 /* User limit mode is unset. Remove user limit */
3514 channel->user_limit = 0;
3517 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3518 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3519 /* Passphrase has been set to channel */
3521 /* Get the passphrase */
3522 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3524 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3525 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3529 /* Save the passphrase */
3530 channel->passphrase = strdup(tmp);
3533 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3534 /* Passphrase mode is unset. remove the passphrase */
3535 if (channel->passphrase) {
3536 silc_free(channel->passphrase);
3537 channel->passphrase = NULL;
3542 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3543 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3544 /* Cipher to use protect the traffic */
3547 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3549 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3550 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3554 /* Delete old cipher and allocate the new one */
3555 silc_cipher_free(channel->channel_key);
3556 if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
3557 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3558 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3562 /* Re-generate channel key */
3563 silc_server_create_channel_key(server, channel, 0);
3565 /* Send the channel key. This sends it to our local clients and if
3566 we are normal server to our router as well. */
3567 silc_server_send_channel_key(server, NULL, channel,
3568 server->server_type == SILC_ROUTER ?
3569 FALSE : !server->standalone);
3572 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3573 /* Cipher mode is unset. Remove the cipher and revert back to
3575 cipher = channel->cipher;
3577 /* Delete old cipher and allocate default one */
3578 silc_cipher_free(channel->channel_key);
3579 if (!silc_cipher_alloc(cipher ? cipher : "aes-256-cbc",
3580 &channel->channel_key)) {
3581 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3582 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3586 /* Re-generate channel key */
3587 silc_server_create_channel_key(server, channel, 0);
3589 /* Send the channel key. This sends it to our local clients and if
3590 we are normal server to our router as well. */
3591 silc_server_send_channel_key(server, NULL, channel,
3592 server->server_type == SILC_ROUTER ?
3593 FALSE : !server->standalone);
3597 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3598 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3599 /* HMAC to use protect the traffic */
3600 unsigned char hash[32];
3603 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3605 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3606 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3610 /* Delete old hmac and allocate the new one */
3611 silc_hmac_free(channel->hmac);
3612 if (!silc_hmac_alloc(hmac, NULL, &channel->hmac)) {
3613 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3614 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3618 /* Set the HMAC key out of current channel key. The client must do
3620 silc_hash_make(channel->hmac->hash, channel->key, channel->key_len / 8,
3622 silc_hmac_set_key(channel->hmac, hash,
3623 silc_hash_len(channel->hmac->hash));
3624 memset(hash, 0, sizeof(hash));
3627 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
3628 /* Hmac mode is unset. Remove the hmac and revert back to
3630 unsigned char hash[32];
3631 hmac = channel->hmac_name;
3633 /* Delete old hmac and allocate default one */
3634 silc_hmac_free(channel->hmac);
3635 if (!silc_hmac_alloc(hmac ? hmac : "hmac-sha1-96", NULL,
3637 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3638 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3642 /* Set the HMAC key out of current channel key. The client must do
3644 silc_hash_make(channel->hmac->hash, channel->key, channel->key_len / 8,
3646 silc_hmac_set_key(channel->hmac, hash,
3647 silc_hash_len(channel->hmac->hash));
3648 memset(hash, 0, sizeof(hash));
3652 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3653 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3654 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
3655 /* Set the founder authentication */
3656 SilcAuthPayload auth;
3658 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
3660 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3661 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3665 auth = silc_auth_payload_parse(tmp, tmp_len);
3667 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3668 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3672 /* Save the public key */
3673 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
3674 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
3677 channel->founder_method = silc_auth_get_method(auth);
3679 if (channel->founder_method == SILC_AUTH_PASSWORD) {
3680 tmp = silc_auth_get_data(auth, &tmp_len);
3681 channel->founder_passwd =
3682 silc_calloc(tmp_len + 1, sizeof(*channel->founder_passwd));
3683 memcpy(channel->founder_passwd, tmp, tmp_len);
3684 channel->founder_passwd_len = tmp_len;
3687 silc_auth_payload_free(auth);
3691 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3692 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3693 if (channel->founder_key)
3694 silc_pkcs_public_key_free(channel->founder_key);
3695 if (channel->founder_passwd) {
3696 silc_free(channel->founder_passwd);
3697 channel->founder_passwd = NULL;
3703 /* Finally, set the mode */
3704 channel->mode = mode_mask;
3706 /* Send CMODE_CHANGE notify */
3707 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3708 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3709 SILC_NOTIFY_TYPE_CMODE_CHANGE, 4,
3710 cidp->data, cidp->len,
3712 cipher, cipher ? strlen(cipher) : 0,
3713 hmac, hmac ? strlen(hmac) : 0);
3715 /* Set CMODE notify type to network */
3716 if (!server->standalone)
3717 silc_server_send_notify_cmode(server, server->router->connection,
3718 server->server_type == SILC_ROUTER ?
3719 TRUE : FALSE, channel,
3720 mode_mask, client->id, SILC_ID_CLIENT,
3723 /* Send command reply to sender */
3724 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3725 SILC_STATUS_OK, ident, 1,
3727 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3728 packet->data, packet->len, FALSE);
3730 silc_buffer_free(packet);
3731 silc_free(channel_id);
3735 silc_server_command_free(cmd);
3738 /* Server side of CUMODE command. Changes client's mode on a channel. */
3740 SILC_SERVER_CMD_FUNC(cumode)
3742 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3743 SilcServer server = cmd->server;
3744 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3745 SilcIDListData idata = (SilcIDListData)client;
3746 SilcChannelID *channel_id;
3747 SilcClientID *client_id;
3748 SilcChannelEntry channel;
3749 SilcClientEntry target_client;
3750 SilcChannelClientEntry chl;
3751 SilcBuffer packet, idp;
3752 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
3753 uint32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
3755 uint16 ident = silc_command_get_ident(cmd->payload);
3757 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 4);
3759 /* Get Channel ID */
3760 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3762 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3763 SILC_STATUS_ERR_NO_CHANNEL_ID);
3766 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
3768 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3769 SILC_STATUS_ERR_NO_CHANNEL_ID);
3773 /* Get channel entry */
3774 channel = silc_idlist_find_channel_by_id(server->local_list,
3777 channel = silc_idlist_find_channel_by_id(server->global_list,
3780 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3781 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3786 /* Check whether sender is on the channel */
3787 if (!silc_server_client_on_channel(client, channel)) {
3788 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3789 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3793 /* Check that client has rights to change other's rights */
3794 silc_list_start(channel->user_list);
3795 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3796 if (chl->client == client) {
3797 sender_mask = chl->mode;
3802 /* Get the target client's channel mode mask */
3803 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3805 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3806 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3809 SILC_GET32_MSB(target_mask, tmp_mask);
3811 /* Get target Client ID */
3812 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3814 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3815 SILC_STATUS_ERR_NO_CLIENT_ID);
3818 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
3820 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3821 SILC_STATUS_ERR_NO_CLIENT_ID);
3825 /* Get target client's entry */
3826 target_client = silc_idlist_find_client_by_id(server->local_list,
3828 if (!target_client) {
3829 target_client = silc_idlist_find_client_by_id(server->global_list,
3833 if (target_client != client &&
3834 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
3835 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
3836 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3837 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3841 /* Check whether target client is on the channel */
3842 if (target_client != client) {
3843 if (!silc_server_client_on_channel(target_client, channel)) {
3844 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3845 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
3849 /* Get entry to the channel user list */
3850 silc_list_start(channel->user_list);
3851 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
3852 if (chl->client == target_client)
3860 /* If the target client is founder, no one else can change their mode
3862 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
3863 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3864 SILC_STATUS_ERR_NOT_YOU);
3868 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
3869 /* The client tries to claim the founder rights. */
3870 unsigned char *tmp_auth;
3871 uint32 tmp_auth_len, auth_len;
3874 if (target_client != client) {
3875 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3876 SILC_STATUS_ERR_NOT_YOU);
3880 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
3881 !channel->founder_key) {
3882 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3883 SILC_STATUS_ERR_NOT_YOU);
3887 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
3889 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3890 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3894 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
3895 (void *)channel->founder_passwd : (void *)channel->founder_key);
3896 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
3897 channel->founder_passwd_len : 0);
3899 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
3900 channel->founder_method, auth, auth_len,
3901 idata->hash, client->id, SILC_ID_CLIENT)) {
3902 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3903 SILC_STATUS_ERR_AUTH_FAILED);
3907 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
3910 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3911 if (target_client == client) {
3912 /* Remove channel founder rights from itself */
3913 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3916 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3917 SILC_STATUS_ERR_NOT_YOU);
3923 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
3924 /* Promote to operator */
3925 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3926 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3927 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3928 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3929 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3933 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
3937 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
3938 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3939 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3940 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3941 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3945 /* Demote to normal user */
3946 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
3951 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3952 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3954 /* Send notify to channel, notify only if mode was actually changed. */
3956 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3957 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3958 idp->data, idp->len,
3962 /* Set CUMODE notify type to network */
3963 if (!server->standalone)
3964 silc_server_send_notify_cumode(server, server->router->connection,
3965 server->server_type == SILC_ROUTER ?
3966 TRUE : FALSE, channel,
3967 target_mask, client->id,
3972 /* Send command reply to sender */
3973 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
3974 SILC_STATUS_OK, ident, 2,
3976 3, tmp_id, tmp_len);
3977 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3978 packet->data, packet->len, FALSE);
3980 silc_buffer_free(packet);
3981 silc_free(channel_id);
3982 silc_free(client_id);
3983 silc_buffer_free(idp);
3986 silc_server_command_free(cmd);
3989 /* Server side of KICK command. Kicks client out of channel. */
3991 SILC_SERVER_CMD_FUNC(kick)
3993 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3994 SilcServer server = cmd->server;
3995 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3996 SilcClientEntry target_client;
3997 SilcChannelID *channel_id;
3998 SilcClientID *client_id;
3999 SilcChannelEntry channel;
4000 SilcChannelClientEntry chl;
4003 unsigned char *tmp, *comment;
4005 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 3);
4007 /* Get Channel ID */
4008 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4010 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4011 SILC_STATUS_ERR_NO_CHANNEL_ID);
4014 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
4016 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4017 SILC_STATUS_ERR_NO_CHANNEL_ID);
4021 /* Get channel entry */
4022 channel = silc_idlist_find_channel_by_id(server->local_list,
4025 channel = silc_idlist_find_channel_by_id(server->local_list,
4028 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4029 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4034 /* Check whether sender is on the channel */
4035 if (!silc_server_client_on_channel(client, channel)) {
4036 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4037 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4041 /* Check that the kicker is channel operator or channel founder */
4042 silc_list_start(channel->user_list);
4043 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
4044 if (chl->client == client) {
4045 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4046 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4047 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4054 /* Get target Client ID */
4055 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4057 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4058 SILC_STATUS_ERR_NO_CLIENT_ID);
4061 client_id = silc_id_payload_parse_id(tmp, tmp_len);
4063 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4064 SILC_STATUS_ERR_NO_CLIENT_ID);
4068 /* Get target client's entry */
4069 target_client = silc_idlist_find_client_by_id(server->local_list,
4071 if (!target_client) {
4072 target_client = silc_idlist_find_client_by_id(server->global_list,
4076 /* Check that the target client is not channel founder. Channel founder
4077 cannot be kicked from the channel. */
4078 silc_list_start(channel->user_list);
4079 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
4080 if (chl->client == target_client) {
4081 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4082 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4083 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4090 /* Check whether target client is on the channel */
4091 if (!silc_server_client_on_channel(target_client, channel)) {
4092 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4093 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4099 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4103 /* Send command reply to sender */
4104 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4107 /* Send KICKED notify to local clients on the channel */
4108 idp = silc_id_payload_encode(target_client->id, SILC_ID_CLIENT);
4109 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4110 SILC_NOTIFY_TYPE_KICKED,
4112 idp->data, idp->len,
4113 comment, comment ? strlen(comment) : 0);
4114 silc_buffer_free(idp);
4116 /* Remove the client from the channel. If the channel does not exist
4117 after removing the client then the client kicked itself off the channel
4118 and we don't have to send anything after that. */
4119 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4120 target_client, FALSE))
4123 /* Send KICKED notify to primary route */
4124 if (!server->standalone)
4125 silc_server_send_notify_kicked(server, server->router->connection,
4126 server->server_type == SILC_ROUTER ?
4127 TRUE : FALSE, channel,
4128 target_client->id, comment);
4130 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4131 /* Re-generate channel key */
4132 silc_server_create_channel_key(server, channel, 0);
4134 /* Send the channel key to the channel. The key of course is not sent
4135 to the client who was kicked off the channel. */
4136 silc_server_send_channel_key(server, target_client->connection, channel,
4137 server->server_type == SILC_ROUTER ?
4138 FALSE : !server->standalone);
4142 silc_server_command_free(cmd);
4145 /* Server side of OPER command. Client uses this comand to obtain server
4146 operator privileges to this server/router. */
4148 SILC_SERVER_CMD_FUNC(oper)
4150 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4151 SilcServer server = cmd->server;
4152 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4153 unsigned char *username, *auth;
4155 SilcServerConfigSectionAdminConnection *admin;
4156 SilcIDListData idata = (SilcIDListData)client;
4158 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_OPER, cmd, 1, 2);
4160 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4163 /* Get the username */
4164 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4166 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4167 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4171 /* Get the admin configuration */
4172 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4173 username, client->nickname);
4175 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4176 username, client->nickname);
4178 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4179 SILC_STATUS_ERR_AUTH_FAILED);
4184 /* Get the authentication payload */
4185 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4187 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4188 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4192 /* Verify the authentication data */
4193 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4194 admin->auth_data, admin->auth_data_len,
4195 idata->hash, client->id, SILC_ID_CLIENT)) {
4196 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4197 SILC_STATUS_ERR_AUTH_FAILED);
4201 /* Client is now server operator */
4202 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4204 /* Send UMODE change to primary router */
4205 if (!server->standalone)
4206 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4207 client->id, client->mode);
4209 /* Send reply to the sender */
4210 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4214 silc_server_command_free(cmd);
4217 /* Server side of SILCOPER command. Client uses this comand to obtain router
4218 operator privileges to this router. */
4220 SILC_SERVER_CMD_FUNC(silcoper)
4222 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4223 SilcServer server = cmd->server;
4224 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4225 unsigned char *username, *auth;
4227 SilcServerConfigSectionAdminConnection *admin;
4228 SilcIDListData idata = (SilcIDListData)client;
4230 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4232 if (server->server_type == SILC_SERVER)
4235 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4238 /* Get the username */
4239 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4241 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4242 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4246 /* Get the admin configuration */
4247 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4248 username, client->nickname);
4250 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4251 username, client->nickname);
4253 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4254 SILC_STATUS_ERR_AUTH_FAILED);
4259 /* Get the authentication payload */
4260 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4262 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4263 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4267 /* Verify the authentication data */
4268 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4269 admin->auth_data, admin->auth_data_len,
4270 idata->hash, client->id, SILC_ID_CLIENT)) {
4271 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4272 SILC_STATUS_ERR_AUTH_FAILED);
4276 /* Client is now router operator */
4277 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4279 /* Send UMODE change to primary router */
4280 if (!server->standalone)
4281 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4282 client->id, client->mode);
4284 /* Send reply to the sender */
4285 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4289 silc_server_command_free(cmd);
4292 /* Server side command of CONNECT. Connects us to the specified remote
4293 server or router. */
4295 SILC_SERVER_CMD_FUNC(connect)
4297 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4298 SilcServer server = cmd->server;
4299 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4300 unsigned char *tmp, *host;
4302 uint32 port = SILC_PORT;
4304 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CONNECT, cmd, 1, 2);
4306 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4309 /* Check whether client has the permissions. */
4310 if (client->mode == SILC_UMODE_NONE) {
4311 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4312 SILC_STATUS_ERR_NO_SERVER_PRIV);
4316 if (server->server_type == SILC_ROUTER &&
4317 client->mode & SILC_UMODE_SERVER_OPERATOR) {
4318 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4319 SILC_STATUS_ERR_NO_ROUTER_PRIV);
4323 /* Get the remote server */
4324 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4326 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4327 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4332 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4334 SILC_GET32_MSB(port, tmp);
4336 /* Create the connection. It is done with timeout and is async. */
4337 silc_server_create_connection(server, host, port);
4339 /* Send reply to the sender */
4340 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4344 silc_server_command_free(cmd);
4347 /* Server side of command BAN. This is used to manage the ban list of the
4348 channel. To add clients and remove clients from the ban list. */
4350 SILC_SERVER_CMD_FUNC(ban)
4352 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4353 SilcServer server = cmd->server;
4354 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4356 SilcChannelEntry channel;
4357 SilcChannelClientEntry chl;
4358 SilcChannelID *channel_id = NULL;
4359 unsigned char *id, *add, *del;
4360 uint32 id_len, tmp_len;
4361 uint16 ident = silc_command_get_ident(cmd->payload);
4363 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4366 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_BAN, cmd, 0, 3);
4368 /* Get Channel ID */
4369 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4371 channel_id = silc_id_payload_parse_id(id, id_len);
4373 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4374 SILC_STATUS_ERR_NO_CHANNEL_ID);
4379 /* Get channel entry. The server must know about the channel since the
4380 client is expected to be on the channel. */
4381 channel = silc_idlist_find_channel_by_id(server->local_list,
4384 channel = silc_idlist_find_channel_by_id(server->global_list,
4387 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4388 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4393 /* Check whether this client is on the channel */
4394 if (!silc_server_client_on_channel(client, channel)) {
4395 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4396 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4400 /* Get entry to the channel user list */
4401 silc_list_start(channel->user_list);
4402 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
4403 if (chl->client == client)
4406 /* The client must be at least channel operator. */
4407 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4408 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4409 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4413 /* Get the new ban and add it to the ban list */
4414 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4416 if (!channel->ban_list)
4417 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4419 channel->ban_list = silc_realloc(channel->ban_list,
4420 sizeof(*channel->ban_list) *
4422 strlen(channel->ban_list) + 2));
4423 if (add[tmp_len - 1] == ',')
4424 add[tmp_len - 1] = '\0';
4426 strncat(channel->ban_list, add, tmp_len);
4427 strncat(channel->ban_list, ",", 1);
4430 /* Get the ban to be removed and remove it from the list */
4431 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4432 if (del && channel->ban_list) {
4433 char *start, *end, *n;
4435 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4436 silc_free(channel->ban_list);
4437 channel->ban_list = NULL;
4439 start = strstr(channel->ban_list, del);
4440 if (start && strlen(start) >= tmp_len) {
4441 end = start + tmp_len;
4442 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4443 strncat(n, channel->ban_list, start - channel->ban_list);
4444 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4446 silc_free(channel->ban_list);
4447 channel->ban_list = n;
4452 /* Send the BAN notify type to our primary router. */
4453 if (!server->standalone && (add || del))
4454 silc_server_send_notify_ban(server, server->router->connection,
4455 server->server_type == SILC_ROUTER ?
4456 TRUE : FALSE, channel, add, del);
4458 /* Send the reply back to the client */
4459 if (channel->ban_list)
4461 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4462 SILC_STATUS_OK, ident, 2,
4464 3, channel->ban_list,
4465 strlen(channel->ban_list) - 1);
4468 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4469 SILC_STATUS_OK, ident, 1,
4472 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4473 packet->data, packet->len, FALSE);
4475 silc_buffer_free(packet);
4479 silc_free(channel_id);
4480 silc_server_command_free(cmd);
4483 /* Server side command of CLOSE. Closes connection to a specified server. */
4485 SILC_SERVER_CMD_FUNC(close)
4487 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4488 SilcServer server = cmd->server;
4489 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4490 SilcServerEntry server_entry;
4491 SilcSocketConnection sock;
4494 unsigned char *name;
4495 uint32 port = SILC_PORT;
4497 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CLOSE, cmd, 1, 2);
4499 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4502 /* Check whether client has the permissions. */
4503 if (client->mode == SILC_UMODE_NONE) {
4504 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4505 SILC_STATUS_ERR_NO_SERVER_PRIV);
4509 /* Get the remote server */
4510 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4512 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4513 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4518 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4520 SILC_GET32_MSB(port, tmp);
4522 server_entry = silc_idlist_find_server_by_conn(server->local_list,
4524 if (!server_entry) {
4525 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4526 SILC_STATUS_ERR_NO_SERVER_ID);
4530 /* Send reply to the sender */
4531 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4534 /* Close the connection to the server */
4535 sock = (SilcSocketConnection)server_entry->connection;
4536 silc_server_free_sock_user_data(server, sock);
4537 silc_server_close_connection(server, sock);
4540 silc_server_command_free(cmd);
4543 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4544 active connections. */
4546 SILC_SERVER_CMD_FUNC(shutdown)
4548 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4549 SilcServer server = cmd->server;
4550 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4552 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4554 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4557 /* Check whether client has the permission. */
4558 if (client->mode == SILC_UMODE_NONE) {
4559 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4560 SILC_STATUS_ERR_NO_SERVER_PRIV);
4564 /* Send reply to the sender */
4565 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4568 /* Then, gracefully, or not, bring the server down. */
4569 silc_server_stop(server);
4573 silc_server_command_free(cmd);
4576 /* Server side command of LEAVE. Removes client from a channel. */
4578 SILC_SERVER_CMD_FUNC(leave)
4580 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4581 SilcServer server = cmd->server;
4582 SilcSocketConnection sock = cmd->sock;
4583 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4584 SilcChannelID *id = NULL;
4585 SilcChannelEntry channel;
4589 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
4591 /* Get Channel ID */
4592 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4594 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4595 SILC_STATUS_ERR_NO_CHANNEL_ID);
4598 id = silc_id_payload_parse_id(tmp, len);
4600 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4601 SILC_STATUS_ERR_NO_CHANNEL_ID);
4605 /* Get channel entry */
4606 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4608 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4610 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4611 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4616 /* Check whether this client is on the channel */
4617 if (!silc_server_client_on_channel(id_entry, channel)) {
4618 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4619 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4623 /* Notify routers that they should remove this client from their list
4624 of clients on the channel. Send LEAVE notify type. */
4625 if (!server->standalone)
4626 silc_server_send_notify_leave(server, server->router->connection,
4627 server->server_type == SILC_ROUTER ?
4628 TRUE : FALSE, channel, id_entry->id);
4630 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4633 /* Remove client from channel */
4634 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4636 /* If the channel does not exist anymore we won't send anything */
4639 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4640 /* Re-generate channel key */
4641 silc_server_create_channel_key(server, channel, 0);
4643 /* Send the channel key */
4644 silc_server_send_channel_key(server, NULL, channel,
4645 server->server_type == SILC_ROUTER ?
4646 FALSE : !server->standalone);
4652 silc_server_command_free(cmd);
4655 /* Server side of command USERS. Resolves clients and their USERS currently
4656 joined on the requested channel. The list of Client ID's and their modes
4657 on the channel is sent back. */
4659 SILC_SERVER_CMD_FUNC(users)
4661 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4662 SilcServer server = cmd->server;
4663 SilcChannelEntry channel;
4666 unsigned char *channel_id;
4667 uint32 channel_id_len;
4668 SilcBuffer client_id_list;
4669 SilcBuffer client_mode_list;
4670 unsigned char lc[4];
4671 uint32 list_count = 0;
4672 uint16 ident = silc_command_get_ident(cmd->payload);
4674 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
4676 /* Get Channel ID */
4677 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4679 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4680 SILC_STATUS_ERR_NO_CHANNEL_ID);
4683 id = silc_id_payload_parse_id(channel_id, channel_id_len);
4685 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4686 SILC_STATUS_ERR_NO_CHANNEL_ID);
4690 /* If we are server and we don't know about this channel we will send
4691 the command to our router. If we know about the channel then we also
4692 have the list of users already. */
4693 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4695 if (server->server_type == SILC_SERVER && !server->standalone &&
4699 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
4700 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4702 /* Send USERS command */
4703 silc_server_packet_send(server, server->router->connection,
4704 SILC_PACKET_COMMAND, cmd->packet->flags,
4705 tmpbuf->data, tmpbuf->len, TRUE);
4707 /* Reprocess this packet after received reply */
4708 silc_server_command_pending(server, SILC_COMMAND_USERS,
4709 silc_command_get_ident(cmd->payload),
4710 silc_server_command_destructor,
4711 silc_server_command_users,
4712 silc_server_command_dup(cmd));
4713 cmd->pending = TRUE;
4714 silc_command_set_ident(cmd->payload, ident);
4716 silc_buffer_free(tmpbuf);
4721 /* We are router and we will check the global list as well. */
4722 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4724 /* Channel really does not exist */
4725 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4726 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4731 /* Get the users list */
4732 silc_server_get_users_on_channel(server, channel, &client_id_list,
4733 &client_mode_list, &list_count);
4736 SILC_PUT32_MSB(list_count, lc);
4739 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
4740 SILC_STATUS_OK, ident, 4,
4741 2, channel_id, channel_id_len,
4743 4, client_id_list->data,
4744 client_id_list->len,
4745 5, client_mode_list->data,
4746 client_mode_list->len);
4747 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4748 packet->data, packet->len, FALSE);
4750 silc_buffer_free(packet);
4751 silc_buffer_free(client_id_list);
4752 silc_buffer_free(client_mode_list);
4756 silc_server_command_free(cmd);
4759 /* Server side of command GETKEY. This fetches the client's public key
4760 from the server where to the client is connected. */
4762 SILC_SERVER_CMD_FUNC(getkey)
4764 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4765 SilcServer server = cmd->server;
4767 SilcClientEntry client;
4768 SilcServerEntry server_entry;
4769 SilcClientID *client_id = NULL;
4770 SilcServerID *server_id = NULL;
4771 SilcIDPayload idp = NULL;
4772 uint16 ident = silc_command_get_ident(cmd->payload);
4778 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4780 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4781 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4784 idp = silc_id_payload_parse_data(tmp, tmp_len);
4786 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4787 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4791 id_type = silc_id_payload_get_type(idp);
4792 if (id_type == SILC_ID_CLIENT) {
4793 client_id = silc_id_payload_get_id(idp);
4795 /* If the client is not found from local list there is no chance it
4796 would be locally connected client so send the command further. */
4797 client = silc_idlist_find_client_by_id(server->local_list,
4800 if ((!client && !cmd->pending && !server->standalone) ||
4801 (client && !client->connection)) {
4804 SilcSocketConnection dest_sock;
4806 dest_sock = silc_server_get_client_route(server, NULL, 0,
4811 old_ident = silc_command_get_ident(cmd->payload);
4812 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
4813 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4815 silc_server_packet_send(server, dest_sock,
4816 SILC_PACKET_COMMAND, cmd->packet->flags,
4817 tmpbuf->data, tmpbuf->len, TRUE);
4819 /* Reprocess this packet after received reply from router */
4820 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
4821 silc_command_get_ident(cmd->payload),
4822 silc_server_command_destructor,
4823 silc_server_command_getkey,
4824 silc_server_command_dup(cmd));
4825 cmd->pending = TRUE;
4827 silc_command_set_ident(cmd->payload, old_ident);
4828 silc_buffer_free(tmpbuf);
4832 if (!client && cmd->pending) {
4833 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4834 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
4838 /* The client is locally connected, just get the public key and
4840 tmp = silc_pkcs_public_key_encode(client->data.public_key, &tmp_len);
4841 pk = silc_buffer_alloc(4 + tmp_len);
4842 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
4843 silc_buffer_format(pk,
4844 SILC_STR_UI_SHORT(tmp_len),
4845 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
4846 SILC_STR_UI_XNSTRING(tmp, tmp_len),
4850 } else if (id_type == SILC_ID_SERVER) {
4851 server_id = silc_id_payload_get_id(idp);
4853 /* If the server is not found from local list there is no chance it
4854 would be locally connected server so send the command further. */
4855 server_entry = silc_idlist_find_server_by_id(server->local_list,
4858 if ((!server_entry && !cmd->pending && !server->standalone) ||
4859 (server_entry && !server_entry->connection)) {
4863 old_ident = silc_command_get_ident(cmd->payload);
4864 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
4865 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4867 silc_server_packet_send(server, server->router->connection,
4868 SILC_PACKET_COMMAND, cmd->packet->flags,
4869 tmpbuf->data, tmpbuf->len, TRUE);
4871 /* Reprocess this packet after received reply from router */
4872 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
4873 silc_command_get_ident(cmd->payload),
4874 silc_server_command_destructor,
4875 silc_server_command_getkey,
4876 silc_server_command_dup(cmd));
4877 cmd->pending = TRUE;
4879 silc_command_set_ident(cmd->payload, old_ident);
4880 silc_buffer_free(tmpbuf);
4884 if (!server_entry && cmd->pending) {
4885 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4886 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
4890 /* The client is locally connected, just get the public key and
4892 tmp = silc_pkcs_public_key_encode(server_entry->data.public_key, &tmp_len);
4893 pk = silc_buffer_alloc(4 + tmp_len);
4894 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
4895 silc_buffer_format(pk,
4896 SILC_STR_UI_SHORT(tmp_len),
4897 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
4898 SILC_STR_UI_XNSTRING(tmp, tmp_len),
4905 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4906 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
4907 SILC_STATUS_OK, ident, 2,
4909 3, pk->data, pk->len);
4910 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4911 packet->data, packet->len, FALSE);
4912 silc_buffer_free(packet);
4913 silc_buffer_free(pk);
4917 silc_id_payload_free(idp);
4918 silc_free(client_id);
4919 silc_free(server_id);
4920 silc_server_command_free(cmd);