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_id(server->local_list->clients, SILC_ID_CLIENT,
1770 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1774 silc_free(client->id);
1776 /* Save the nickname as this client is our local client */
1777 if (client->nickname)
1778 silc_free(client->nickname);
1780 client->nickname = strdup(nick);
1781 client->id = new_id;
1783 /* Update client cache */
1784 silc_idcache_add(server->local_list->clients, client->nickname,
1785 strlen(client->nickname), SILC_ID_CLIENT, client->id,
1786 (void *)client, TRUE, FALSE);
1788 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1790 /* Send NICK_CHANGE notify to the client's channels */
1791 silc_server_send_notify_on_channels(server, NULL, client,
1792 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1793 oidp->data, oidp->len,
1794 nidp->data, nidp->len);
1796 /* Send the new Client ID as reply command back to client */
1797 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
1798 SILC_STATUS_OK, ident, 1,
1799 2, nidp->data, nidp->len);
1800 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1801 0, packet->data, packet->len, FALSE);
1803 silc_buffer_free(packet);
1804 silc_buffer_free(nidp);
1805 silc_buffer_free(oidp);
1808 silc_server_command_free(cmd);
1811 /* Sends the LIST command reply */
1814 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
1815 SilcChannelEntry *lch,
1817 SilcChannelEntry *gch,
1821 SilcBuffer packet, idp;
1822 SilcChannelEntry entry;
1823 SilcCommandStatus status;
1824 uint16 ident = silc_command_get_ident(cmd->payload);
1826 unsigned char usercount[4];
1829 for (i = 0; i < lch_count; i++)
1830 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
1832 for (i = 0; i < gch_count; i++)
1833 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
1836 status = SILC_STATUS_OK;
1837 if ((lch_count + gch_count) > 1)
1838 status = SILC_STATUS_LIST_START;
1841 for (i = 0; i < lch_count; i++) {
1848 status = SILC_STATUS_LIST_ITEM;
1850 if (i == lch_count - 1 && gch_count)
1852 if (lch_count > 1 && i == lch_count - 1)
1853 status = SILC_STATUS_LIST_END;
1855 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1857 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
1858 topic = "*private*";
1859 memset(usercount, 0, sizeof(usercount));
1861 topic = entry->topic;
1862 users = silc_list_count(entry->user_list);
1863 SILC_PUT32_MSB(users, usercount);
1866 /* Send the reply */
1869 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1871 2, idp->data, idp->len,
1872 3, entry->channel_name,
1873 strlen(entry->channel_name),
1874 4, topic, strlen(topic),
1878 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1880 2, idp->data, idp->len,
1881 3, entry->channel_name,
1882 strlen(entry->channel_name),
1884 silc_server_packet_send(cmd->server, cmd->sock,
1885 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
1886 packet->len, FALSE);
1887 silc_buffer_free(packet);
1888 silc_buffer_free(idp);
1891 status = i ? SILC_STATUS_LIST_ITEM : SILC_STATUS_OK;
1894 for (i = 0; i < gch_count; i++) {
1901 status = SILC_STATUS_LIST_ITEM;
1903 if (gch_count > 1 && i == lch_count - 1)
1904 status = SILC_STATUS_LIST_END;
1906 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1908 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
1909 topic = "*private*";
1910 memset(usercount, 0, sizeof(usercount));
1912 topic = entry->topic;
1913 users = silc_list_count(entry->user_list);
1914 SILC_PUT32_MSB(users, usercount);
1917 /* Send the reply */
1920 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1922 2, idp->data, idp->len,
1923 3, entry->channel_name,
1924 strlen(entry->channel_name),
1925 4, topic, strlen(topic),
1929 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1931 2, idp->data, idp->len,
1932 3, entry->channel_name,
1933 strlen(entry->channel_name),
1935 silc_server_packet_send(cmd->server, cmd->sock,
1936 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
1937 packet->len, FALSE);
1938 silc_buffer_free(packet);
1939 silc_buffer_free(idp);
1943 /* Server side of LIST command. This lists the channel of the requested
1944 server. Secret channels are not listed. */
1946 SILC_SERVER_CMD_FUNC(list)
1948 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1949 SilcServer server = cmd->server;
1950 SilcChannelID *channel_id = NULL;
1953 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
1954 uint32 lch_count = 0, gch_count = 0;
1956 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LIST, cmd, 0, 2);
1958 /* Get Channel ID */
1959 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1961 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1963 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
1964 SILC_STATUS_ERR_NO_CHANNEL_ID);
1969 /* Get the channels from local list */
1970 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
1973 /* Get the channels from global list if we are router */
1974 if (server->server_type == SILC_ROUTER)
1975 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
1978 /* Send the reply */
1979 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
1980 gchannels, gch_count);
1983 silc_server_command_free(cmd);
1986 /* Server side of TOPIC command. Sets topic for channel and/or returns
1987 current topic to client. */
1989 SILC_SERVER_CMD_FUNC(topic)
1991 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1992 SilcServer server = cmd->server;
1993 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1994 SilcChannelID *channel_id;
1995 SilcChannelEntry channel;
1996 SilcChannelClientEntry chl;
1997 SilcBuffer packet, idp;
1999 uint32 argc, tmp_len;
2000 uint16 ident = silc_command_get_ident(cmd->payload);
2002 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
2004 argc = silc_argument_get_arg_num(cmd->args);
2006 /* Get Channel ID */
2007 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2009 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2010 SILC_STATUS_ERR_NO_CHANNEL_ID);
2013 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2015 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2016 SILC_STATUS_ERR_NO_CHANNEL_ID);
2020 /* Check whether the channel exists */
2021 channel = silc_idlist_find_channel_by_id(server->local_list,
2024 channel = silc_idlist_find_channel_by_id(server->global_list,
2027 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2028 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2035 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2037 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2038 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2042 if (strlen(tmp) > 256) {
2043 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2044 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2048 /* See whether has rights to change topic */
2049 silc_list_start(channel->user_list);
2050 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2051 if (chl->client == client)
2054 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2055 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2056 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2057 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2062 /* Set the topic for channel */
2064 silc_free(channel->topic);
2065 channel->topic = strdup(tmp);
2067 /* Send TOPIC_SET notify type to the network */
2068 if (!server->standalone)
2069 silc_server_send_notify_topic_set(server, server->router->connection,
2070 server->server_type == SILC_ROUTER ?
2071 TRUE : FALSE, channel, client->id,
2074 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2076 /* Send notify about topic change to all clients on the channel */
2077 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2078 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2079 idp->data, idp->len,
2080 channel->topic, strlen(channel->topic));
2081 silc_buffer_free(idp);
2084 /* Send the topic to client as reply packet */
2085 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2087 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2088 SILC_STATUS_OK, ident, 2,
2089 2, idp->data, idp->len,
2091 strlen(channel->topic));
2093 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2094 SILC_STATUS_OK, ident, 1,
2095 2, idp->data, idp->len);
2096 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2097 0, packet->data, packet->len, FALSE);
2099 silc_buffer_free(packet);
2100 silc_buffer_free(idp);
2101 silc_free(channel_id);
2104 silc_server_command_free(cmd);
2107 /* Server side of INVITE command. Invites some client to join some channel.
2108 This command is also used to manage the invite list of the channel. */
2110 SILC_SERVER_CMD_FUNC(invite)
2112 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2113 SilcServer server = cmd->server;
2114 SilcSocketConnection sock = cmd->sock, dest_sock;
2115 SilcChannelClientEntry chl;
2116 SilcClientEntry sender, dest;
2117 SilcClientID *dest_id = NULL;
2118 SilcChannelEntry channel;
2119 SilcChannelID *channel_id = NULL;
2120 SilcIDListData idata;
2121 SilcBuffer idp, idp2, packet;
2122 unsigned char *tmp, *add, *del;
2124 uint16 ident = silc_command_get_ident(cmd->payload);
2126 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 4);
2128 /* Get Channel ID */
2129 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2131 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2132 SILC_STATUS_ERR_NO_CHANNEL_ID);
2135 channel_id = silc_id_payload_parse_id(tmp, len);
2137 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2138 SILC_STATUS_ERR_NO_CHANNEL_ID);
2142 /* Get the channel entry */
2143 channel = silc_idlist_find_channel_by_id(server->local_list,
2146 channel = silc_idlist_find_channel_by_id(server->global_list,
2149 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2150 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2155 /* Check whether the sender of this command is on the channel. */
2156 sender = (SilcClientEntry)sock->user_data;
2157 if (!silc_server_client_on_channel(sender, channel)) {
2158 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2159 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2163 /* Check whether the channel is invite-only channel. If yes then the
2164 sender of this command must be at least channel operator. */
2165 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2166 silc_list_start(channel->user_list);
2167 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2168 if (chl->client == sender) {
2169 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2170 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2171 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2178 /* Get destination client ID */
2179 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2183 dest_id = silc_id_payload_parse_id(tmp, len);
2185 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2186 SILC_STATUS_ERR_NO_CLIENT_ID);
2190 /* Get the client entry */
2191 dest = silc_server_get_client_resolve(server, dest_id);
2193 if (server->server_type == SILC_ROUTER) {
2194 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2195 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2199 /* The client info is being resolved. Reprocess this packet after
2200 receiving the reply to the query. */
2201 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2203 silc_server_command_destructor,
2204 silc_server_command_invite,
2205 silc_server_command_dup(cmd));
2206 cmd->pending = TRUE;
2207 silc_free(channel_id);
2212 /* Check whether the requested client is already on the channel. */
2213 if (silc_server_client_on_channel(dest, channel)) {
2214 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2215 SILC_STATUS_ERR_USER_ON_CHANNEL);
2219 /* Get route to the client */
2220 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2222 memset(invite, 0, sizeof(invite));
2223 strncat(invite, dest->nickname, strlen(dest->nickname));
2224 strncat(invite, "!", 1);
2225 strncat(invite, dest->username, strlen(dest->username));
2226 if (!strchr(dest->username, '@')) {
2227 strncat(invite, "@", 1);
2228 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2231 len = strlen(invite);
2232 if (!channel->invite_list)
2233 channel->invite_list = silc_calloc(len + 2,
2234 sizeof(*channel->invite_list));
2236 channel->invite_list = silc_realloc(channel->invite_list,
2237 sizeof(*channel->invite_list) *
2239 strlen(channel->invite_list) + 2));
2240 strncat(channel->invite_list, invite, len);
2241 strncat(channel->invite_list, ",", 1);
2243 /* Send notify to the client that is invited to the channel */
2244 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2245 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2246 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2248 SILC_NOTIFY_TYPE_INVITE, 3,
2249 idp->data, idp->len,
2250 channel->channel_name,
2251 strlen(channel->channel_name),
2252 idp2->data, idp2->len);
2253 silc_buffer_free(idp);
2254 silc_buffer_free(idp2);
2257 /* Add the client to the invite list of the channel */
2258 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2260 if (!channel->invite_list)
2261 channel->invite_list = silc_calloc(len + 2,
2262 sizeof(*channel->invite_list));
2264 channel->invite_list = silc_realloc(channel->invite_list,
2265 sizeof(*channel->invite_list) *
2267 strlen(channel->invite_list) + 2));
2268 if (add[len - 1] == ',')
2269 add[len - 1] = '\0';
2271 strncat(channel->invite_list, add, len);
2272 strncat(channel->invite_list, ",", 1);
2275 /* Get the invite to be removed and remove it from the list */
2276 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2277 if (del && channel->invite_list) {
2278 char *start, *end, *n;
2280 if (!strncmp(channel->invite_list, del,
2281 strlen(channel->invite_list) - 1)) {
2282 silc_free(channel->invite_list);
2283 channel->invite_list = NULL;
2285 start = strstr(channel->invite_list, del);
2286 if (start && strlen(start) >= len) {
2288 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2289 strncat(n, channel->invite_list, start - channel->invite_list);
2290 strncat(n, end + 1, ((channel->invite_list +
2291 strlen(channel->invite_list)) - end) - 1);
2292 silc_free(channel->invite_list);
2293 channel->invite_list = n;
2298 /* Send notify to the primary router */
2299 if (!server->standalone)
2300 silc_server_send_notify_invite(server, server->router->connection,
2301 server->server_type == SILC_ROUTER ?
2302 TRUE : FALSE, channel,
2303 sender->id, add, del);
2305 /* Send command reply */
2306 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2307 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2308 SILC_STATUS_OK, ident, 2,
2310 3, channel->invite_list,
2311 channel->invite_list ?
2312 strlen(channel->invite_list) :
2314 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2315 packet->data, packet->len, FALSE);
2316 silc_buffer_free(packet);
2322 silc_free(channel_id);
2323 silc_server_command_free(cmd);
2328 SilcSocketConnection sock;
2332 /* Quits connection to client. This gets called if client won't
2333 close the connection even when it has issued QUIT command. */
2335 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2337 QuitInternal q = (QuitInternal)context;
2339 /* Free all client specific data, such as client entry and entires
2340 on channels this client may be on. */
2341 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2343 q->sock->user_data = NULL;
2345 /* Close the connection on our side */
2346 silc_server_close_connection(q->server, q->sock);
2348 silc_free(q->signoff);
2352 /* Quits SILC session. This is the normal way to disconnect client. */
2354 SILC_SERVER_CMD_FUNC(quit)
2356 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2357 SilcServer server = cmd->server;
2358 SilcSocketConnection sock = cmd->sock;
2360 unsigned char *tmp = NULL;
2363 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_QUIT, cmd, 0, 1);
2365 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2368 /* Get destination ID */
2369 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2373 q = silc_calloc(1, sizeof(*q));
2376 q->signoff = tmp ? strdup(tmp) : NULL;
2378 /* We quit the connection with little timeout */
2379 silc_task_register(server->timeout_queue, sock->sock,
2380 silc_server_command_quit_cb, (void *)q,
2381 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2384 silc_server_command_free(cmd);
2387 /* Server side of command KILL. This command is used by router operator
2388 to remove an client from the SILC Network temporarily. */
2390 SILC_SERVER_CMD_FUNC(kill)
2392 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2393 SilcServer server = cmd->server;
2394 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2395 SilcClientEntry remote_client;
2396 SilcClientID *client_id;
2397 unsigned char *tmp, *comment;
2398 uint32 tmp_len, tmp_len2;
2400 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_KILL, cmd, 1, 2);
2402 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2405 /* KILL command works only on router */
2406 if (server->server_type != SILC_ROUTER) {
2407 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2408 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2412 /* Check whether client has the permissions. */
2413 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2414 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2415 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2419 /* Get the client ID */
2420 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2422 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2423 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2426 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2428 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2429 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2433 /* Get the client entry */
2434 remote_client = silc_idlist_find_client_by_id(server->local_list,
2436 if (!remote_client) {
2437 remote_client = silc_idlist_find_client_by_id(server->global_list,
2439 if (!remote_client) {
2440 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2441 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2447 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2451 /* Send reply to the sender */
2452 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2455 /* Send the KILL notify packets. First send it to the channel, then
2456 to our primary router and then directly to the client who is being
2457 killed right now. */
2459 /* Send KILLED notify to the channels. It is not sent to the client
2460 as it will be sent differently destined directly to the client and not
2462 silc_server_send_notify_on_channels(server, remote_client,
2463 remote_client, SILC_NOTIFY_TYPE_KILLED,
2466 comment, comment ? tmp_len2 : 0);
2468 /* Send KILLED notify to primary route */
2469 if (!server->standalone)
2470 silc_server_send_notify_killed(server, server->router->connection, TRUE,
2471 remote_client->id, comment);
2473 /* Send KILLED notify to the client directly */
2474 silc_server_send_notify_killed(server, remote_client->connection ?
2475 remote_client->connection :
2476 remote_client->router->connection, FALSE,
2477 remote_client->id, comment);
2479 /* Remove the client from all channels. This generates new keys to the
2480 channels as well. */
2481 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2484 /* Remove the client entry, If it is locally connected then we will also
2485 disconnect the client here */
2486 if (remote_client->data.registered && remote_client->connection) {
2487 /* Remove locally conneted client */
2488 SilcSocketConnection sock = remote_client->connection;
2489 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2490 silc_server_close_connection(server, sock);
2492 /* Remove remote client */
2493 if (!silc_idlist_del_client(server->global_list, remote_client))
2494 silc_idlist_del_client(server->local_list, remote_client);
2498 silc_server_command_free(cmd);
2501 /* Server side of command INFO. This sends information about us to
2502 the client. If client requested specific server we will send the
2503 command to that server. */
2505 SILC_SERVER_CMD_FUNC(info)
2507 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2508 SilcServer server = cmd->server;
2509 SilcBuffer packet, idp;
2512 char *dest_server, *server_info = NULL, *server_name;
2513 uint16 ident = silc_command_get_ident(cmd->payload);
2514 SilcServerEntry entry = NULL;
2515 SilcServerID *server_id = NULL;
2517 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 0, 2);
2519 /* Get server name */
2520 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2523 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2525 server_id = silc_id_payload_parse_id(tmp, tmp_len);
2527 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2528 SILC_STATUS_ERR_NO_SERVER_ID);
2534 /* Check whether we have this server cached */
2535 entry = silc_idlist_find_server_by_id(server->local_list,
2538 entry = silc_idlist_find_server_by_id(server->global_list,
2540 if (!entry && server->server_type == SILC_ROUTER) {
2541 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2542 SILC_STATUS_ERR_NO_SUCH_SERVER);
2548 if ((!dest_server && !server_id) ||
2549 (dest_server && !cmd->pending &&
2550 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2551 /* Send our reply */
2552 char info_string[256];
2554 memset(info_string, 0, sizeof(info_string));
2555 snprintf(info_string, sizeof(info_string),
2556 "location: %s server: %s admin: %s <%s>",
2557 server->config->admin_info->location,
2558 server->config->admin_info->server_type,
2559 server->config->admin_info->admin_name,
2560 server->config->admin_info->admin_email);
2562 server_info = info_string;
2563 entry = server->id_entry;
2565 /* Check whether we have this server cached */
2566 if (!entry && dest_server) {
2567 entry = silc_idlist_find_server_by_name(server->global_list,
2570 entry = silc_idlist_find_server_by_name(server->local_list,
2575 if (!cmd->pending &&
2576 server->server_type == SILC_ROUTER && entry && !entry->server_info) {
2577 /* Send to the server */
2581 old_ident = silc_command_get_ident(cmd->payload);
2582 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2583 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2585 silc_server_packet_send(server, entry->connection,
2586 SILC_PACKET_COMMAND, cmd->packet->flags,
2587 tmpbuf->data, tmpbuf->len, TRUE);
2589 /* Reprocess this packet after received reply from router */
2590 silc_server_command_pending(server, SILC_COMMAND_INFO,
2591 silc_command_get_ident(cmd->payload),
2592 silc_server_command_destructor,
2593 silc_server_command_info,
2594 silc_server_command_dup(cmd));
2595 cmd->pending = TRUE;
2596 silc_command_set_ident(cmd->payload, old_ident);
2597 silc_buffer_free(tmpbuf);
2601 if (!entry && !cmd->pending && !server->standalone) {
2602 /* Send to the primary router */
2606 old_ident = silc_command_get_ident(cmd->payload);
2607 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2608 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2610 silc_server_packet_send(server, server->router->connection,
2611 SILC_PACKET_COMMAND, cmd->packet->flags,
2612 tmpbuf->data, tmpbuf->len, TRUE);
2614 /* Reprocess this packet after received reply from router */
2615 silc_server_command_pending(server, SILC_COMMAND_INFO,
2616 silc_command_get_ident(cmd->payload),
2617 silc_server_command_destructor,
2618 silc_server_command_info,
2619 silc_server_command_dup(cmd));
2620 cmd->pending = TRUE;
2621 silc_command_set_ident(cmd->payload, old_ident);
2622 silc_buffer_free(tmpbuf);
2628 silc_free(server_id);
2631 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2632 SILC_STATUS_ERR_NO_SUCH_SERVER);
2636 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2638 server_info = entry->server_info;
2639 server_name = entry->server_name;
2641 /* Send the reply */
2642 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2643 SILC_STATUS_OK, ident, 3,
2644 2, idp->data, idp->len,
2646 strlen(server_name),
2648 strlen(server_info));
2649 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2650 packet->data, packet->len, FALSE);
2652 silc_buffer_free(packet);
2653 silc_buffer_free(idp);
2656 silc_server_command_free(cmd);
2659 /* Server side of command PING. This just replies to the ping. */
2661 SILC_SERVER_CMD_FUNC(ping)
2663 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2664 SilcServer server = cmd->server;
2669 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
2672 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2674 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2675 SILC_STATUS_ERR_NO_SERVER_ID);
2678 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2682 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2683 /* Send our reply */
2684 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2687 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2688 SILC_STATUS_ERR_NO_SUCH_SERVER);
2695 silc_server_command_free(cmd);
2698 /* Internal routine to join channel. The channel sent to this function
2699 has been either created or resolved from ID lists. This joins the sent
2700 client to the channel. */
2702 static void silc_server_command_join_channel(SilcServer server,
2703 SilcServerCommandContext cmd,
2704 SilcChannelEntry channel,
2705 SilcClientID *client_id,
2709 SilcSocketConnection sock = cmd->sock;
2711 uint32 tmp_len, user_count;
2712 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
2713 SilcClientEntry client;
2714 SilcChannelClientEntry chl;
2715 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
2716 uint16 ident = silc_command_get_ident(cmd->payload);
2719 SILC_LOG_DEBUG(("Start"));
2724 /* Get the client entry */
2725 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2726 client = (SilcClientEntry)sock->user_data;
2728 client = silc_idlist_find_client_by_id(server->local_list, client_id,
2735 * Check channel modes
2738 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2739 strncat(check, client->nickname, strlen(client->nickname));
2740 if (!strchr(client->nickname, '@')) {
2741 strncat(check, "@", 1);
2742 strncat(check, server->server_name, strlen(server->server_name));
2744 strncat(check, "!", 1);
2745 strncat(check, client->username, strlen(client->username));
2746 if (!strchr(client->username, '@')) {
2747 strncat(check, "@", 1);
2748 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
2752 /* Check invite list if channel is invite-only channel */
2753 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
2754 channel->mode & SILC_CHANNEL_MODE_INVITE) {
2755 if (!channel->invite_list) {
2756 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2757 SILC_STATUS_ERR_NOT_INVITED);
2761 if (!silc_string_match(channel->invite_list, check)) {
2762 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2763 SILC_STATUS_ERR_NOT_INVITED);
2768 /* Check ban list if it exists. If the client's nickname, server,
2769 username and/or hostname is in the ban list the access to the
2770 channel is denied. */
2771 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && channel->ban_list) {
2772 if (silc_string_match(channel->ban_list, check)) {
2773 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2774 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
2779 /* Get passphrase */
2780 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2782 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
2783 memcpy(passphrase, tmp, tmp_len);
2786 /* Check the channel passphrase if set. */
2787 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2788 if (!passphrase || memcmp(channel->passphrase, passphrase,
2789 strlen(channel->passphrase))) {
2790 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2791 SILC_STATUS_ERR_BAD_PASSWORD);
2796 /* Check user count limit if set. */
2797 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
2798 if (silc_list_count(channel->user_list) + 1 >
2799 channel->user_limit) {
2800 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2801 SILC_STATUS_ERR_CHANNEL_IS_FULL);
2807 * Client is allowed to join to the channel. Make it happen.
2810 /* Check whether the client already is on the channel */
2811 if (silc_server_client_on_channel(client, channel)) {
2812 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2813 SILC_STATUS_ERR_USER_ON_CHANNEL);
2817 /* Generate new channel key as protocol dictates */
2818 if ((!created && silc_list_count(channel->user_list) > 0) ||
2819 !channel->channel_key)
2820 silc_server_create_channel_key(server, channel, 0);
2822 /* Send the channel key. This is broadcasted to the channel but is not
2823 sent to the client who is joining to the channel. */
2824 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
2825 silc_server_send_channel_key(server, NULL, channel,
2826 server->server_type == SILC_ROUTER ?
2827 FALSE : !server->standalone);
2829 /* Join the client to the channel by adding it to channel's user list.
2830 Add also the channel to client entry's channels list for fast cross-
2832 chl = silc_calloc(1, sizeof(*chl));
2834 chl->client = client;
2835 chl->channel = channel;
2836 silc_list_add(channel->user_list, chl);
2837 silc_list_add(client->channels, chl);
2839 /* Get users on the channel */
2840 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
2843 /* Encode Client ID Payload of the original client who wants to join */
2844 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2846 /* Encode command reply packet */
2847 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2848 SILC_PUT32_MSB(channel->mode, mode);
2849 SILC_PUT32_MSB(created, tmp2);
2850 SILC_PUT32_MSB(user_count, tmp3);
2852 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
2853 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
2854 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
2855 strlen(channel->channel_key->
2857 channel->channel_key->cipher->name,
2858 channel->key_len / 8, channel->key);
2863 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2864 SILC_STATUS_OK, ident, 13,
2865 2, channel->channel_name,
2866 strlen(channel->channel_name),
2867 3, chidp->data, chidp->len,
2868 4, clidp->data, clidp->len,
2871 7, keyp ? keyp->data : NULL,
2872 keyp ? keyp->len : 0,
2873 8, channel->ban_list,
2875 strlen(channel->ban_list) : 0,
2876 9, channel->invite_list,
2877 channel->invite_list ?
2878 strlen(channel->invite_list) : 0,
2881 strlen(channel->topic) : 0,
2882 11, channel->hmac->hmac->name,
2883 strlen(channel->hmac->hmac->name),
2885 13, user_list->data, user_list->len,
2886 14, mode_list->data,
2889 /* Send command reply */
2890 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
2891 reply->data, reply->len, FALSE);
2893 if (!cmd->pending) {
2894 /* Send JOIN notify to locally connected clients on the channel */
2895 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2896 SILC_NOTIFY_TYPE_JOIN, 2,
2897 clidp->data, clidp->len,
2898 chidp->data, chidp->len);
2900 /* Send JOIN notify packet to our primary router */
2901 if (!server->standalone)
2902 silc_server_send_notify_join(server, server->router->connection,
2903 server->server_type == SILC_ROUTER ?
2904 TRUE : FALSE, channel, client->id);
2907 silc_buffer_free(reply);
2908 silc_buffer_free(clidp);
2909 silc_buffer_free(chidp);
2910 silc_buffer_free(keyp);
2911 silc_buffer_free(user_list);
2912 silc_buffer_free(mode_list);
2916 silc_free(passphrase);
2919 /* Server side of command JOIN. Joins client into requested channel. If
2920 the channel does not exist it will be created. */
2922 SILC_SERVER_CMD_FUNC(join)
2924 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2925 SilcServer server = cmd->server;
2927 char *tmp, *channel_name = NULL, *cipher, *hmac;
2928 SilcChannelEntry channel;
2930 int created = FALSE;
2931 SilcClientID *client_id;
2933 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
2935 /* Get channel name */
2936 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2938 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2939 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2944 if (strlen(channel_name) > 256)
2945 channel_name[255] = '\0';
2947 if (silc_server_command_bad_chars(channel_name) == TRUE) {
2948 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2949 SILC_STATUS_ERR_BAD_CHANNEL);
2950 silc_free(channel_name);
2954 /* Get Client ID of the client who is joining to the channel */
2955 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2957 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2958 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2961 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2963 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2964 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2968 /* Get cipher and hmac name */
2969 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2970 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2972 /* See if the channel exists */
2973 channel = silc_idlist_find_channel_by_name(server->local_list,
2974 channel_name, NULL);
2976 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2977 /* If this is coming from client the Client ID in the command packet must
2978 be same as the client's ID. */
2979 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2980 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2981 if (!SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
2982 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2983 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2988 if (!channel || !channel->id) {
2989 /* Channel not found */
2991 /* If we are standalone server we don't have a router, we just create
2992 the channel by ourselves. */
2993 if (server->standalone) {
2994 channel = silc_server_create_new_channel(server, server->id, cipher,
2995 hmac, channel_name, TRUE);
2997 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2998 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3002 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3007 /* The channel does not exist on our server. If we are normal server
3008 we will send JOIN command to our router which will handle the
3009 joining procedure (either creates the channel if it doesn't exist
3010 or joins the client to it). */
3011 if (server->server_type == SILC_SERVER) {
3015 old_ident = silc_command_get_ident(cmd->payload);
3016 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3017 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3019 /* Send JOIN command to our router */
3020 silc_server_packet_send(server, (SilcSocketConnection)
3021 server->router->connection,
3022 SILC_PACKET_COMMAND, cmd->packet->flags,
3023 tmpbuf->data, tmpbuf->len, TRUE);
3025 /* Reprocess this packet after received reply from router */
3026 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3027 silc_command_get_ident(cmd->payload),
3028 silc_server_command_destructor,
3029 silc_server_command_join,
3030 silc_server_command_dup(cmd));
3031 cmd->pending = TRUE;
3035 /* We are router and the channel does not seem exist so we will check
3036 our global list as well for the channel. */
3037 channel = silc_idlist_find_channel_by_name(server->global_list,
3038 channel_name, NULL);
3040 /* Channel really does not exist, create it */
3041 channel = silc_server_create_new_channel(server, server->id, cipher,
3042 hmac, channel_name, TRUE);
3044 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3045 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3049 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3056 /* Channel not found */
3058 /* If the command came from router and/or we are normal server then
3059 something went wrong with the joining as the channel was not found.
3060 We can't do anything else but ignore this. */
3061 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3062 server->server_type == SILC_SERVER)
3065 /* We are router and the channel does not seem exist so we will check
3066 our global list as well for the channel. */
3067 channel = silc_idlist_find_channel_by_name(server->global_list,
3068 channel_name, NULL);
3070 /* Channel really does not exist, create it */
3071 channel = silc_server_create_new_channel(server, server->id, cipher,
3072 hmac, channel_name, TRUE);
3074 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3075 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3079 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3085 /* If the channel does not have global users and is also empty it means the
3086 channel was created globally (by our router) and the client will be the
3087 channel founder and operator. */
3088 if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
3089 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3090 created = TRUE; /* Created globally by our router */
3093 /* Join to the channel */
3094 silc_server_command_join_channel(server, cmd, channel, client_id,
3097 silc_free(client_id);
3100 silc_server_command_free(cmd);
3103 /* Server side of command MOTD. Sends server's current "message of the
3104 day" to the client. */
3106 SILC_SERVER_CMD_FUNC(motd)
3108 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3109 SilcServer server = cmd->server;
3110 SilcBuffer packet, idp;
3111 char *motd, *dest_server;
3113 uint16 ident = silc_command_get_ident(cmd->payload);
3115 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 1);
3117 /* Get server name */
3118 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3120 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3121 SILC_STATUS_ERR_NO_SUCH_SERVER);
3125 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3128 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3130 if (server->config && server->config->motd &&
3131 server->config->motd->motd_file) {
3133 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
3138 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3139 SILC_STATUS_OK, ident, 2,
3145 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3146 SILC_STATUS_OK, ident, 1,
3150 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3151 packet->data, packet->len, FALSE);
3152 silc_buffer_free(packet);
3153 silc_buffer_free(idp);
3155 SilcServerEntry entry;
3157 /* Check whether we have this server cached */
3158 entry = silc_idlist_find_server_by_name(server->global_list,
3161 entry = silc_idlist_find_server_by_name(server->local_list,
3165 if (server->server_type == SILC_ROUTER && !cmd->pending &&
3166 entry && !entry->motd) {
3167 /* Send to the server */
3171 old_ident = silc_command_get_ident(cmd->payload);
3172 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3173 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3175 silc_server_packet_send(server, entry->connection,
3176 SILC_PACKET_COMMAND, cmd->packet->flags,
3177 tmpbuf->data, tmpbuf->len, TRUE);
3179 /* Reprocess this packet after received reply from router */
3180 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3181 silc_command_get_ident(cmd->payload),
3182 silc_server_command_destructor,
3183 silc_server_command_motd,
3184 silc_server_command_dup(cmd));
3185 cmd->pending = TRUE;
3186 silc_command_set_ident(cmd->payload, old_ident);
3187 silc_buffer_free(tmpbuf);
3191 if (!entry && !cmd->pending && !server->standalone) {
3192 /* Send to the primary router */
3196 old_ident = silc_command_get_ident(cmd->payload);
3197 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3198 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3200 silc_server_packet_send(server, server->router->connection,
3201 SILC_PACKET_COMMAND, cmd->packet->flags,
3202 tmpbuf->data, tmpbuf->len, TRUE);
3204 /* Reprocess this packet after received reply from router */
3205 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3206 silc_command_get_ident(cmd->payload),
3207 silc_server_command_destructor,
3208 silc_server_command_motd,
3209 silc_server_command_dup(cmd));
3210 cmd->pending = TRUE;
3211 silc_command_set_ident(cmd->payload, old_ident);
3212 silc_buffer_free(tmpbuf);
3217 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3218 SILC_STATUS_ERR_NO_SUCH_SERVER);
3222 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3225 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3226 SILC_STATUS_OK, ident, 2,
3229 strlen(entry->motd));
3231 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3232 SILC_STATUS_OK, ident, 1,
3235 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3236 packet->data, packet->len, FALSE);
3237 silc_buffer_free(packet);
3238 silc_buffer_free(idp);
3242 silc_server_command_free(cmd);
3245 /* Server side of command UMODE. Client can use this command to set/unset
3246 user mode. Client actually cannot set itself to be as server/router
3247 operator so this can be used only to unset the modes. */
3249 SILC_SERVER_CMD_FUNC(umode)
3251 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3252 SilcServer server = cmd->server;
3253 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3255 unsigned char *tmp_mask;
3257 uint16 ident = silc_command_get_ident(cmd->payload);
3259 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3262 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_UMODE, cmd, 2, 2);
3264 /* Get the client's mode mask */
3265 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3267 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3268 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3271 SILC_GET32_MSB(mask, tmp_mask);
3277 if (mask & SILC_UMODE_SERVER_OPERATOR) {
3278 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR)) {
3279 /* Cannot operator mode */
3280 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3281 SILC_STATUS_ERR_PERM_DENIED);
3285 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
3286 /* Remove the server operator rights */
3287 client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3290 if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3291 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
3292 /* Cannot operator mode */
3293 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3294 SILC_STATUS_ERR_PERM_DENIED);
3298 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
3299 /* Remove the router operator rights */
3300 client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3303 if (mask & SILC_UMODE_GONE) {
3304 client->mode |= SILC_UMODE_GONE;
3306 if (client->mode & SILC_UMODE_GONE)
3307 /* Remove the gone status */
3308 client->mode &= ~SILC_UMODE_GONE;
3311 /* Send UMODE change to primary router */
3312 if (!server->standalone)
3313 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3314 client->id, client->mode);
3316 /* Send command reply to sender */
3317 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3318 SILC_STATUS_OK, ident, 1,
3320 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3321 packet->data, packet->len, FALSE);
3322 silc_buffer_free(packet);
3325 silc_server_command_free(cmd);
3328 /* Checks that client has rights to add or remove channel modes. If any
3329 of the checks fails FALSE is returned. */
3331 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3332 SilcChannelClientEntry client,
3335 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3336 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3338 /* Check whether has rights to change anything */
3339 if (!is_op && !is_fo)
3342 /* Check whether has rights to change everything */
3346 /* We know that client is channel operator, check that they are not
3347 changing anything that requires channel founder rights. Rest of the
3348 modes are available automatically for channel operator. */
3350 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3351 if (is_op && !is_fo)
3354 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3355 if (is_op && !is_fo)
3360 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3361 if (is_op && !is_fo)
3364 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3365 if (is_op && !is_fo)
3370 if (mode & SILC_CHANNEL_MODE_CIPHER) {
3371 if (is_op && !is_fo)
3374 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3375 if (is_op && !is_fo)
3380 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3381 if (is_op && !is_fo)
3384 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3385 if (is_op && !is_fo)
3393 /* Server side command of CMODE. Changes channel mode */
3395 SILC_SERVER_CMD_FUNC(cmode)
3397 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3398 SilcServer server = cmd->server;
3399 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3400 SilcIDListData idata = (SilcIDListData)client;
3401 SilcChannelID *channel_id;
3402 SilcChannelEntry channel;
3403 SilcChannelClientEntry chl;
3404 SilcBuffer packet, cidp;
3405 unsigned char *tmp, *tmp_id, *tmp_mask;
3406 char *cipher = NULL, *hmac = NULL;
3407 uint32 mode_mask, tmp_len, tmp_len2;
3408 uint16 ident = silc_command_get_ident(cmd->payload);
3410 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CMODE, cmd, 2, 7);
3412 /* Get Channel ID */
3413 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3415 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3416 SILC_STATUS_ERR_NO_CHANNEL_ID);
3419 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3421 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3422 SILC_STATUS_ERR_NO_CHANNEL_ID);
3426 /* Get the channel mode mask */
3427 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3429 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3430 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3433 SILC_GET32_MSB(mode_mask, tmp_mask);
3435 /* Get channel entry */
3436 channel = silc_idlist_find_channel_by_id(server->local_list,
3439 channel = silc_idlist_find_channel_by_id(server->global_list,
3442 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3443 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3448 /* Check whether this client is on the channel */
3449 if (!silc_server_client_on_channel(client, channel)) {
3450 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3451 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3455 /* Get entry to the channel user list */
3456 silc_list_start(channel->user_list);
3457 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
3458 if (chl->client == client)
3461 /* Check that client has rights to change any requested channel modes */
3462 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3463 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3464 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3469 * Check the modes. Modes that requires nothing special operation are
3473 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3474 /* Channel uses private keys to protect traffic. Client(s) has set the
3475 key locally they want to use, server does not know that key. */
3476 /* Nothing interesting to do here */
3478 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3479 /* The mode is removed and we need to generate and distribute
3480 new channel key. Clients are not using private channel keys
3481 anymore after this. */
3483 /* Re-generate channel key */
3484 silc_server_create_channel_key(server, channel, 0);
3486 /* Send the channel key. This sends it to our local clients and if
3487 we are normal server to our router as well. */
3488 silc_server_send_channel_key(server, NULL, channel,
3489 server->server_type == SILC_ROUTER ?
3490 FALSE : !server->standalone);
3492 cipher = channel->channel_key->cipher->name;
3493 hmac = channel->hmac->hmac->name;
3497 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3498 /* User limit is set on channel */
3501 /* Get user limit */
3502 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3504 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3505 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3506 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3510 SILC_GET32_MSB(user_limit, tmp);
3511 channel->user_limit = user_limit;
3514 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3515 /* User limit mode is unset. Remove user limit */
3516 channel->user_limit = 0;
3519 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3520 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3521 /* Passphrase has been set to channel */
3523 /* Get the passphrase */
3524 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3526 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3527 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3531 /* Save the passphrase */
3532 channel->passphrase = strdup(tmp);
3535 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3536 /* Passphrase mode is unset. remove the passphrase */
3537 if (channel->passphrase) {
3538 silc_free(channel->passphrase);
3539 channel->passphrase = NULL;
3544 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3545 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3546 /* Cipher to use protect the traffic */
3549 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3551 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3552 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3556 /* Delete old cipher and allocate the new one */
3557 silc_cipher_free(channel->channel_key);
3558 if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
3559 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3560 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3564 /* Re-generate channel key */
3565 silc_server_create_channel_key(server, channel, 0);
3567 /* Send the channel key. This sends it to our local clients and if
3568 we are normal server to our router as well. */
3569 silc_server_send_channel_key(server, NULL, channel,
3570 server->server_type == SILC_ROUTER ?
3571 FALSE : !server->standalone);
3574 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3575 /* Cipher mode is unset. Remove the cipher and revert back to
3577 cipher = channel->cipher;
3579 /* Delete old cipher and allocate default one */
3580 silc_cipher_free(channel->channel_key);
3581 if (!silc_cipher_alloc(cipher ? cipher : "aes-256-cbc",
3582 &channel->channel_key)) {
3583 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3584 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3588 /* Re-generate channel key */
3589 silc_server_create_channel_key(server, channel, 0);
3591 /* Send the channel key. This sends it to our local clients and if
3592 we are normal server to our router as well. */
3593 silc_server_send_channel_key(server, NULL, channel,
3594 server->server_type == SILC_ROUTER ?
3595 FALSE : !server->standalone);
3599 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3600 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3601 /* HMAC to use protect the traffic */
3602 unsigned char hash[32];
3605 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3607 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3608 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3612 /* Delete old hmac and allocate the new one */
3613 silc_hmac_free(channel->hmac);
3614 if (!silc_hmac_alloc(hmac, NULL, &channel->hmac)) {
3615 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3616 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3620 /* Set the HMAC key out of current channel key. The client must do
3622 silc_hash_make(channel->hmac->hash, channel->key, channel->key_len / 8,
3624 silc_hmac_set_key(channel->hmac, hash,
3625 silc_hash_len(channel->hmac->hash));
3626 memset(hash, 0, sizeof(hash));
3629 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
3630 /* Hmac mode is unset. Remove the hmac and revert back to
3632 unsigned char hash[32];
3633 hmac = channel->hmac_name;
3635 /* Delete old hmac and allocate default one */
3636 silc_hmac_free(channel->hmac);
3637 if (!silc_hmac_alloc(hmac ? hmac : "hmac-sha1-96", NULL,
3639 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3640 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3644 /* Set the HMAC key out of current channel key. The client must do
3646 silc_hash_make(channel->hmac->hash, channel->key, channel->key_len / 8,
3648 silc_hmac_set_key(channel->hmac, hash,
3649 silc_hash_len(channel->hmac->hash));
3650 memset(hash, 0, sizeof(hash));
3654 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3655 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3656 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
3657 /* Set the founder authentication */
3658 SilcAuthPayload auth;
3660 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
3662 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3663 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3667 auth = silc_auth_payload_parse(tmp, tmp_len);
3669 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3670 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3674 /* Save the public key */
3675 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
3676 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
3679 channel->founder_method = silc_auth_get_method(auth);
3681 if (channel->founder_method == SILC_AUTH_PASSWORD) {
3682 tmp = silc_auth_get_data(auth, &tmp_len);
3683 channel->founder_passwd =
3684 silc_calloc(tmp_len + 1, sizeof(*channel->founder_passwd));
3685 memcpy(channel->founder_passwd, tmp, tmp_len);
3686 channel->founder_passwd_len = tmp_len;
3689 silc_auth_payload_free(auth);
3693 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3694 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3695 if (channel->founder_key)
3696 silc_pkcs_public_key_free(channel->founder_key);
3697 if (channel->founder_passwd) {
3698 silc_free(channel->founder_passwd);
3699 channel->founder_passwd = NULL;
3705 /* Finally, set the mode */
3706 channel->mode = mode_mask;
3708 /* Send CMODE_CHANGE notify */
3709 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3710 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3711 SILC_NOTIFY_TYPE_CMODE_CHANGE, 4,
3712 cidp->data, cidp->len,
3714 cipher, cipher ? strlen(cipher) : 0,
3715 hmac, hmac ? strlen(hmac) : 0);
3717 /* Set CMODE notify type to network */
3718 if (!server->standalone)
3719 silc_server_send_notify_cmode(server, server->router->connection,
3720 server->server_type == SILC_ROUTER ?
3721 TRUE : FALSE, channel,
3722 mode_mask, client->id, SILC_ID_CLIENT,
3725 /* Send command reply to sender */
3726 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3727 SILC_STATUS_OK, ident, 1,
3729 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3730 packet->data, packet->len, FALSE);
3732 silc_buffer_free(packet);
3733 silc_free(channel_id);
3737 silc_server_command_free(cmd);
3740 /* Server side of CUMODE command. Changes client's mode on a channel. */
3742 SILC_SERVER_CMD_FUNC(cumode)
3744 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3745 SilcServer server = cmd->server;
3746 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3747 SilcIDListData idata = (SilcIDListData)client;
3748 SilcChannelID *channel_id;
3749 SilcClientID *client_id;
3750 SilcChannelEntry channel;
3751 SilcClientEntry target_client;
3752 SilcChannelClientEntry chl;
3753 SilcBuffer packet, idp;
3754 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
3755 uint32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
3757 uint16 ident = silc_command_get_ident(cmd->payload);
3759 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 4);
3761 /* Get Channel ID */
3762 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3764 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3765 SILC_STATUS_ERR_NO_CHANNEL_ID);
3768 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
3770 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3771 SILC_STATUS_ERR_NO_CHANNEL_ID);
3775 /* Get channel entry */
3776 channel = silc_idlist_find_channel_by_id(server->local_list,
3779 channel = silc_idlist_find_channel_by_id(server->global_list,
3782 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3783 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3788 /* Check whether sender is on the channel */
3789 if (!silc_server_client_on_channel(client, channel)) {
3790 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3791 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3795 /* Check that client has rights to change other's rights */
3796 silc_list_start(channel->user_list);
3797 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3798 if (chl->client == client) {
3799 sender_mask = chl->mode;
3804 /* Get the target client's channel mode mask */
3805 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3807 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3808 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3811 SILC_GET32_MSB(target_mask, tmp_mask);
3813 /* Get target Client ID */
3814 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3816 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3817 SILC_STATUS_ERR_NO_CLIENT_ID);
3820 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
3822 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3823 SILC_STATUS_ERR_NO_CLIENT_ID);
3827 /* Get target client's entry */
3828 target_client = silc_idlist_find_client_by_id(server->local_list,
3830 if (!target_client) {
3831 target_client = silc_idlist_find_client_by_id(server->global_list,
3835 if (target_client != client &&
3836 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
3837 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
3838 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3839 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3843 /* Check whether target client is on the channel */
3844 if (target_client != client) {
3845 if (!silc_server_client_on_channel(target_client, channel)) {
3846 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3847 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
3851 /* Get entry to the channel user list */
3852 silc_list_start(channel->user_list);
3853 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
3854 if (chl->client == target_client)
3862 /* If the target client is founder, no one else can change their mode
3864 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
3865 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3866 SILC_STATUS_ERR_NOT_YOU);
3870 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
3871 /* The client tries to claim the founder rights. */
3872 unsigned char *tmp_auth;
3873 uint32 tmp_auth_len, auth_len;
3876 if (target_client != client) {
3877 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3878 SILC_STATUS_ERR_NOT_YOU);
3882 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
3883 !channel->founder_key) {
3884 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3885 SILC_STATUS_ERR_NOT_YOU);
3889 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
3891 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3892 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3896 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
3897 (void *)channel->founder_passwd : (void *)channel->founder_key);
3898 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
3899 channel->founder_passwd_len : 0);
3901 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
3902 channel->founder_method, auth, auth_len,
3903 idata->hash, client->id, SILC_ID_CLIENT)) {
3904 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3905 SILC_STATUS_ERR_AUTH_FAILED);
3909 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
3912 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3913 if (target_client == client) {
3914 /* Remove channel founder rights from itself */
3915 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3918 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3919 SILC_STATUS_ERR_NOT_YOU);
3925 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
3926 /* Promote to operator */
3927 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3928 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3929 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3930 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3931 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3935 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
3939 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
3940 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3941 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3942 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3943 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3947 /* Demote to normal user */
3948 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
3953 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3954 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3956 /* Send notify to channel, notify only if mode was actually changed. */
3958 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3959 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3960 idp->data, idp->len,
3964 /* Set CUMODE notify type to network */
3965 if (!server->standalone)
3966 silc_server_send_notify_cumode(server, server->router->connection,
3967 server->server_type == SILC_ROUTER ?
3968 TRUE : FALSE, channel,
3969 target_mask, client->id,
3974 /* Send command reply to sender */
3975 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
3976 SILC_STATUS_OK, ident, 2,
3978 3, tmp_id, tmp_len);
3979 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3980 packet->data, packet->len, FALSE);
3982 silc_buffer_free(packet);
3983 silc_free(channel_id);
3984 silc_free(client_id);
3985 silc_buffer_free(idp);
3988 silc_server_command_free(cmd);
3991 /* Server side of KICK command. Kicks client out of channel. */
3993 SILC_SERVER_CMD_FUNC(kick)
3995 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3996 SilcServer server = cmd->server;
3997 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3998 SilcClientEntry target_client;
3999 SilcChannelID *channel_id;
4000 SilcClientID *client_id;
4001 SilcChannelEntry channel;
4002 SilcChannelClientEntry chl;
4005 unsigned char *tmp, *comment;
4007 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 3);
4009 /* Get Channel ID */
4010 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4012 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4013 SILC_STATUS_ERR_NO_CHANNEL_ID);
4016 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
4018 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4019 SILC_STATUS_ERR_NO_CHANNEL_ID);
4023 /* Get channel entry */
4024 channel = silc_idlist_find_channel_by_id(server->local_list,
4027 channel = silc_idlist_find_channel_by_id(server->local_list,
4030 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4031 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4036 /* Check whether sender is on the channel */
4037 if (!silc_server_client_on_channel(client, channel)) {
4038 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4039 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4043 /* Check that the kicker is channel operator or channel founder */
4044 silc_list_start(channel->user_list);
4045 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
4046 if (chl->client == client) {
4047 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4048 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4049 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4056 /* Get target Client ID */
4057 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4059 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4060 SILC_STATUS_ERR_NO_CLIENT_ID);
4063 client_id = silc_id_payload_parse_id(tmp, tmp_len);
4065 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4066 SILC_STATUS_ERR_NO_CLIENT_ID);
4070 /* Get target client's entry */
4071 target_client = silc_idlist_find_client_by_id(server->local_list,
4073 if (!target_client) {
4074 target_client = silc_idlist_find_client_by_id(server->global_list,
4078 /* Check that the target client is not channel founder. Channel founder
4079 cannot be kicked from the channel. */
4080 silc_list_start(channel->user_list);
4081 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
4082 if (chl->client == target_client) {
4083 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4084 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4085 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4092 /* Check whether target client is on the channel */
4093 if (!silc_server_client_on_channel(target_client, channel)) {
4094 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4095 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4101 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4105 /* Send command reply to sender */
4106 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4109 /* Send KICKED notify to local clients on the channel */
4110 idp = silc_id_payload_encode(target_client->id, SILC_ID_CLIENT);
4111 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4112 SILC_NOTIFY_TYPE_KICKED,
4114 idp->data, idp->len,
4115 comment, comment ? strlen(comment) : 0);
4116 silc_buffer_free(idp);
4118 /* Remove the client from the channel. If the channel does not exist
4119 after removing the client then the client kicked itself off the channel
4120 and we don't have to send anything after that. */
4121 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4122 target_client, FALSE))
4125 /* Send KICKED notify to primary route */
4126 if (!server->standalone)
4127 silc_server_send_notify_kicked(server, server->router->connection,
4128 server->server_type == SILC_ROUTER ?
4129 TRUE : FALSE, channel,
4130 target_client->id, comment);
4132 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4133 /* Re-generate channel key */
4134 silc_server_create_channel_key(server, channel, 0);
4136 /* Send the channel key to the channel. The key of course is not sent
4137 to the client who was kicked off the channel. */
4138 silc_server_send_channel_key(server, target_client->connection, channel,
4139 server->server_type == SILC_ROUTER ?
4140 FALSE : !server->standalone);
4144 silc_server_command_free(cmd);
4147 /* Server side of OPER command. Client uses this comand to obtain server
4148 operator privileges to this server/router. */
4150 SILC_SERVER_CMD_FUNC(oper)
4152 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4153 SilcServer server = cmd->server;
4154 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4155 unsigned char *username, *auth;
4157 SilcServerConfigSectionAdminConnection *admin;
4158 SilcIDListData idata = (SilcIDListData)client;
4160 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_OPER, cmd, 1, 2);
4162 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4165 /* Get the username */
4166 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4168 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4169 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4173 /* Get the admin configuration */
4174 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4175 username, client->nickname);
4177 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4178 username, client->nickname);
4180 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4181 SILC_STATUS_ERR_AUTH_FAILED);
4186 /* Get the authentication payload */
4187 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4189 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4190 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4194 /* Verify the authentication data */
4195 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4196 admin->auth_data, admin->auth_data_len,
4197 idata->hash, client->id, SILC_ID_CLIENT)) {
4198 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4199 SILC_STATUS_ERR_AUTH_FAILED);
4203 /* Client is now server operator */
4204 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4206 /* Send UMODE change to primary router */
4207 if (!server->standalone)
4208 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4209 client->id, client->mode);
4211 /* Send reply to the sender */
4212 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4216 silc_server_command_free(cmd);
4219 /* Server side of SILCOPER command. Client uses this comand to obtain router
4220 operator privileges to this router. */
4222 SILC_SERVER_CMD_FUNC(silcoper)
4224 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4225 SilcServer server = cmd->server;
4226 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4227 unsigned char *username, *auth;
4229 SilcServerConfigSectionAdminConnection *admin;
4230 SilcIDListData idata = (SilcIDListData)client;
4232 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4234 if (server->server_type == SILC_SERVER)
4237 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4240 /* Get the username */
4241 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4243 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4244 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4248 /* Get the admin configuration */
4249 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4250 username, client->nickname);
4252 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4253 username, client->nickname);
4255 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4256 SILC_STATUS_ERR_AUTH_FAILED);
4261 /* Get the authentication payload */
4262 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4264 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4265 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4269 /* Verify the authentication data */
4270 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4271 admin->auth_data, admin->auth_data_len,
4272 idata->hash, client->id, SILC_ID_CLIENT)) {
4273 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4274 SILC_STATUS_ERR_AUTH_FAILED);
4278 /* Client is now router operator */
4279 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4281 /* Send UMODE change to primary router */
4282 if (!server->standalone)
4283 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4284 client->id, client->mode);
4286 /* Send reply to the sender */
4287 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4291 silc_server_command_free(cmd);
4294 /* Server side command of CONNECT. Connects us to the specified remote
4295 server or router. */
4297 SILC_SERVER_CMD_FUNC(connect)
4299 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4300 SilcServer server = cmd->server;
4301 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4302 unsigned char *tmp, *host;
4304 uint32 port = SILC_PORT;
4306 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CONNECT, cmd, 1, 2);
4308 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4311 /* Check whether client has the permissions. */
4312 if (client->mode == SILC_UMODE_NONE) {
4313 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4314 SILC_STATUS_ERR_NO_SERVER_PRIV);
4318 if (server->server_type == SILC_ROUTER &&
4319 client->mode & SILC_UMODE_SERVER_OPERATOR) {
4320 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4321 SILC_STATUS_ERR_NO_ROUTER_PRIV);
4325 /* Get the remote server */
4326 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4328 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4329 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4334 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4336 SILC_GET32_MSB(port, tmp);
4338 /* Create the connection. It is done with timeout and is async. */
4339 silc_server_create_connection(server, host, port);
4341 /* Send reply to the sender */
4342 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4346 silc_server_command_free(cmd);
4349 /* Server side of command BAN. This is used to manage the ban list of the
4350 channel. To add clients and remove clients from the ban list. */
4352 SILC_SERVER_CMD_FUNC(ban)
4354 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4355 SilcServer server = cmd->server;
4356 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4358 SilcChannelEntry channel;
4359 SilcChannelClientEntry chl;
4360 SilcChannelID *channel_id = NULL;
4361 unsigned char *id, *add, *del;
4362 uint32 id_len, tmp_len;
4363 uint16 ident = silc_command_get_ident(cmd->payload);
4365 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4368 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_BAN, cmd, 0, 3);
4370 /* Get Channel ID */
4371 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4373 channel_id = silc_id_payload_parse_id(id, id_len);
4375 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4376 SILC_STATUS_ERR_NO_CHANNEL_ID);
4381 /* Get channel entry. The server must know about the channel since the
4382 client is expected to be on the channel. */
4383 channel = silc_idlist_find_channel_by_id(server->local_list,
4386 channel = silc_idlist_find_channel_by_id(server->global_list,
4389 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4390 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4395 /* Check whether this client is on the channel */
4396 if (!silc_server_client_on_channel(client, channel)) {
4397 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4398 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4402 /* Get entry to the channel user list */
4403 silc_list_start(channel->user_list);
4404 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
4405 if (chl->client == client)
4408 /* The client must be at least channel operator. */
4409 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4410 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4411 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4415 /* Get the new ban and add it to the ban list */
4416 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4418 if (!channel->ban_list)
4419 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4421 channel->ban_list = silc_realloc(channel->ban_list,
4422 sizeof(*channel->ban_list) *
4424 strlen(channel->ban_list) + 2));
4425 if (add[tmp_len - 1] == ',')
4426 add[tmp_len - 1] = '\0';
4428 strncat(channel->ban_list, add, tmp_len);
4429 strncat(channel->ban_list, ",", 1);
4432 /* Get the ban to be removed and remove it from the list */
4433 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4434 if (del && channel->ban_list) {
4435 char *start, *end, *n;
4437 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4438 silc_free(channel->ban_list);
4439 channel->ban_list = NULL;
4441 start = strstr(channel->ban_list, del);
4442 if (start && strlen(start) >= tmp_len) {
4443 end = start + tmp_len;
4444 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4445 strncat(n, channel->ban_list, start - channel->ban_list);
4446 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4448 silc_free(channel->ban_list);
4449 channel->ban_list = n;
4454 /* Send the BAN notify type to our primary router. */
4455 if (!server->standalone && (add || del))
4456 silc_server_send_notify_ban(server, server->router->connection,
4457 server->server_type == SILC_ROUTER ?
4458 TRUE : FALSE, channel, add, del);
4460 /* Send the reply back to the client */
4461 if (channel->ban_list)
4463 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4464 SILC_STATUS_OK, ident, 2,
4466 3, channel->ban_list,
4467 strlen(channel->ban_list) - 1);
4470 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4471 SILC_STATUS_OK, ident, 1,
4474 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4475 packet->data, packet->len, FALSE);
4477 silc_buffer_free(packet);
4481 silc_free(channel_id);
4482 silc_server_command_free(cmd);
4485 /* Server side command of CLOSE. Closes connection to a specified server. */
4487 SILC_SERVER_CMD_FUNC(close)
4489 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4490 SilcServer server = cmd->server;
4491 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4492 SilcServerEntry server_entry;
4493 SilcSocketConnection sock;
4496 unsigned char *name;
4497 uint32 port = SILC_PORT;
4499 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CLOSE, cmd, 1, 2);
4501 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4504 /* Check whether client has the permissions. */
4505 if (client->mode == SILC_UMODE_NONE) {
4506 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4507 SILC_STATUS_ERR_NO_SERVER_PRIV);
4511 /* Get the remote server */
4512 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4514 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4515 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4520 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4522 SILC_GET32_MSB(port, tmp);
4524 server_entry = silc_idlist_find_server_by_conn(server->local_list,
4526 if (!server_entry) {
4527 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4528 SILC_STATUS_ERR_NO_SERVER_ID);
4532 /* Send reply to the sender */
4533 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4536 /* Close the connection to the server */
4537 sock = (SilcSocketConnection)server_entry->connection;
4538 silc_server_free_sock_user_data(server, sock);
4539 silc_server_close_connection(server, sock);
4542 silc_server_command_free(cmd);
4545 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4546 active connections. */
4548 SILC_SERVER_CMD_FUNC(shutdown)
4550 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4551 SilcServer server = cmd->server;
4552 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4554 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4556 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4559 /* Check whether client has the permission. */
4560 if (client->mode == SILC_UMODE_NONE) {
4561 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4562 SILC_STATUS_ERR_NO_SERVER_PRIV);
4566 /* Send reply to the sender */
4567 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4570 /* Then, gracefully, or not, bring the server down. */
4571 silc_server_stop(server);
4575 silc_server_command_free(cmd);
4578 /* Server side command of LEAVE. Removes client from a channel. */
4580 SILC_SERVER_CMD_FUNC(leave)
4582 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4583 SilcServer server = cmd->server;
4584 SilcSocketConnection sock = cmd->sock;
4585 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4586 SilcChannelID *id = NULL;
4587 SilcChannelEntry channel;
4591 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
4593 /* Get Channel ID */
4594 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4596 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4597 SILC_STATUS_ERR_NO_CHANNEL_ID);
4600 id = silc_id_payload_parse_id(tmp, len);
4602 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4603 SILC_STATUS_ERR_NO_CHANNEL_ID);
4607 /* Get channel entry */
4608 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4610 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4612 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4613 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4618 /* Check whether this client is on the channel */
4619 if (!silc_server_client_on_channel(id_entry, channel)) {
4620 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4621 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4625 /* Notify routers that they should remove this client from their list
4626 of clients on the channel. Send LEAVE notify type. */
4627 if (!server->standalone)
4628 silc_server_send_notify_leave(server, server->router->connection,
4629 server->server_type == SILC_ROUTER ?
4630 TRUE : FALSE, channel, id_entry->id);
4632 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4635 /* Remove client from channel */
4636 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4638 /* If the channel does not exist anymore we won't send anything */
4641 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4642 /* Re-generate channel key */
4643 silc_server_create_channel_key(server, channel, 0);
4645 /* Send the channel key */
4646 silc_server_send_channel_key(server, NULL, channel,
4647 server->server_type == SILC_ROUTER ?
4648 FALSE : !server->standalone);
4654 silc_server_command_free(cmd);
4657 /* Server side of command USERS. Resolves clients and their USERS currently
4658 joined on the requested channel. The list of Client ID's and their modes
4659 on the channel is sent back. */
4661 SILC_SERVER_CMD_FUNC(users)
4663 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4664 SilcServer server = cmd->server;
4665 SilcChannelEntry channel;
4668 unsigned char *channel_id;
4669 uint32 channel_id_len;
4670 SilcBuffer client_id_list;
4671 SilcBuffer client_mode_list;
4672 unsigned char lc[4];
4673 uint32 list_count = 0;
4674 uint16 ident = silc_command_get_ident(cmd->payload);
4676 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
4678 /* Get Channel ID */
4679 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4681 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4682 SILC_STATUS_ERR_NO_CHANNEL_ID);
4685 id = silc_id_payload_parse_id(channel_id, channel_id_len);
4687 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4688 SILC_STATUS_ERR_NO_CHANNEL_ID);
4692 /* If we are server and we don't know about this channel we will send
4693 the command to our router. If we know about the channel then we also
4694 have the list of users already. */
4695 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4697 if (server->server_type == SILC_SERVER && !server->standalone &&
4701 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
4702 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4704 /* Send USERS command */
4705 silc_server_packet_send(server, server->router->connection,
4706 SILC_PACKET_COMMAND, cmd->packet->flags,
4707 tmpbuf->data, tmpbuf->len, TRUE);
4709 /* Reprocess this packet after received reply */
4710 silc_server_command_pending(server, SILC_COMMAND_USERS,
4711 silc_command_get_ident(cmd->payload),
4712 silc_server_command_destructor,
4713 silc_server_command_users,
4714 silc_server_command_dup(cmd));
4715 cmd->pending = TRUE;
4716 silc_command_set_ident(cmd->payload, ident);
4718 silc_buffer_free(tmpbuf);
4723 /* We are router and we will check the global list as well. */
4724 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4726 /* Channel really does not exist */
4727 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4728 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4733 /* Get the users list */
4734 silc_server_get_users_on_channel(server, channel, &client_id_list,
4735 &client_mode_list, &list_count);
4738 SILC_PUT32_MSB(list_count, lc);
4741 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
4742 SILC_STATUS_OK, ident, 4,
4743 2, channel_id, channel_id_len,
4745 4, client_id_list->data,
4746 client_id_list->len,
4747 5, client_mode_list->data,
4748 client_mode_list->len);
4749 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4750 packet->data, packet->len, FALSE);
4752 silc_buffer_free(packet);
4753 silc_buffer_free(client_id_list);
4754 silc_buffer_free(client_mode_list);
4758 silc_server_command_free(cmd);
4761 /* Server side of command GETKEY. This fetches the client's public key
4762 from the server where to the client is connected. */
4764 SILC_SERVER_CMD_FUNC(getkey)
4766 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4767 SilcServer server = cmd->server;
4769 SilcClientEntry client;
4770 SilcServerEntry server_entry;
4771 SilcClientID *client_id = NULL;
4772 SilcServerID *server_id = NULL;
4773 SilcIDPayload idp = NULL;
4774 uint16 ident = silc_command_get_ident(cmd->payload);
4780 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4782 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4783 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4786 idp = silc_id_payload_parse_data(tmp, tmp_len);
4788 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4789 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4793 id_type = silc_id_payload_get_type(idp);
4794 if (id_type == SILC_ID_CLIENT) {
4795 client_id = silc_id_payload_get_id(idp);
4797 /* If the client is not found from local list there is no chance it
4798 would be locally connected client so send the command further. */
4799 client = silc_idlist_find_client_by_id(server->local_list,
4802 if ((!client && !cmd->pending && !server->standalone) ||
4803 (client && !client->connection)) {
4806 SilcSocketConnection dest_sock;
4808 dest_sock = silc_server_get_client_route(server, NULL, 0,
4813 old_ident = silc_command_get_ident(cmd->payload);
4814 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
4815 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4817 silc_server_packet_send(server, dest_sock,
4818 SILC_PACKET_COMMAND, cmd->packet->flags,
4819 tmpbuf->data, tmpbuf->len, TRUE);
4821 /* Reprocess this packet after received reply from router */
4822 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
4823 silc_command_get_ident(cmd->payload),
4824 silc_server_command_destructor,
4825 silc_server_command_getkey,
4826 silc_server_command_dup(cmd));
4827 cmd->pending = TRUE;
4829 silc_command_set_ident(cmd->payload, old_ident);
4830 silc_buffer_free(tmpbuf);
4834 if (!client && cmd->pending) {
4835 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4836 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
4840 /* The client is locally connected, just get the public key and
4842 tmp = silc_pkcs_public_key_encode(client->data.public_key, &tmp_len);
4843 pk = silc_buffer_alloc(4 + tmp_len);
4844 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
4845 silc_buffer_format(pk,
4846 SILC_STR_UI_SHORT(tmp_len),
4847 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
4848 SILC_STR_UI_XNSTRING(tmp, tmp_len),
4852 } else if (id_type == SILC_ID_SERVER) {
4853 server_id = silc_id_payload_get_id(idp);
4855 /* If the server is not found from local list there is no chance it
4856 would be locally connected server so send the command further. */
4857 server_entry = silc_idlist_find_server_by_id(server->local_list,
4860 if ((!server_entry && !cmd->pending && !server->standalone) ||
4861 (server_entry && !server_entry->connection)) {
4865 old_ident = silc_command_get_ident(cmd->payload);
4866 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
4867 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4869 silc_server_packet_send(server, server->router->connection,
4870 SILC_PACKET_COMMAND, cmd->packet->flags,
4871 tmpbuf->data, tmpbuf->len, TRUE);
4873 /* Reprocess this packet after received reply from router */
4874 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
4875 silc_command_get_ident(cmd->payload),
4876 silc_server_command_destructor,
4877 silc_server_command_getkey,
4878 silc_server_command_dup(cmd));
4879 cmd->pending = TRUE;
4881 silc_command_set_ident(cmd->payload, old_ident);
4882 silc_buffer_free(tmpbuf);
4886 if (!server_entry && cmd->pending) {
4887 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4888 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
4892 /* The client is locally connected, just get the public key and
4894 tmp = silc_pkcs_public_key_encode(server_entry->data.public_key, &tmp_len);
4895 pk = silc_buffer_alloc(4 + tmp_len);
4896 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
4897 silc_buffer_format(pk,
4898 SILC_STR_UI_SHORT(tmp_len),
4899 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
4900 SILC_STR_UI_XNSTRING(tmp, tmp_len),
4907 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4908 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
4909 SILC_STATUS_OK, ident, 2,
4911 3, pk->data, pk->len);
4912 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4913 packet->data, packet->len, FALSE);
4914 silc_buffer_free(packet);
4915 silc_buffer_free(pk);
4919 silc_id_payload_free(idp);
4920 silc_free(client_id);
4921 silc_free(server_id);
4922 silc_server_command_free(cmd);