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, client->id);
1769 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1773 silc_free(client->id);
1775 /* Save the nickname as this client is our local client */
1776 if (client->nickname)
1777 silc_free(client->nickname);
1779 client->nickname = strdup(nick);
1780 client->id = new_id;
1782 /* Update client cache */
1783 silc_idcache_add(server->local_list->clients, client->nickname,
1784 strlen(client->nickname), client->id,
1785 (void *)client, FALSE);
1787 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1789 /* Send NICK_CHANGE notify to the client's channels */
1790 silc_server_send_notify_on_channels(server, NULL, client,
1791 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1792 oidp->data, oidp->len,
1793 nidp->data, nidp->len);
1795 /* Send the new Client ID as reply command back to client */
1796 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
1797 SILC_STATUS_OK, ident, 1,
1798 2, nidp->data, nidp->len);
1799 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1800 0, packet->data, packet->len, FALSE);
1802 silc_buffer_free(packet);
1803 silc_buffer_free(nidp);
1804 silc_buffer_free(oidp);
1807 silc_server_command_free(cmd);
1810 /* Sends the LIST command reply */
1813 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
1814 SilcChannelEntry *lch,
1816 SilcChannelEntry *gch,
1820 SilcBuffer packet, idp;
1821 SilcChannelEntry entry;
1822 SilcCommandStatus status;
1823 uint16 ident = silc_command_get_ident(cmd->payload);
1825 unsigned char usercount[4];
1828 for (i = 0; i < lch_count; i++)
1829 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
1831 for (i = 0; i < gch_count; i++)
1832 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
1835 status = SILC_STATUS_OK;
1836 if ((lch_count + gch_count) > 1)
1837 status = SILC_STATUS_LIST_START;
1840 for (i = 0; i < lch_count; i++) {
1847 status = SILC_STATUS_LIST_ITEM;
1849 if (i == lch_count - 1 && gch_count)
1851 if (lch_count > 1 && i == lch_count - 1)
1852 status = SILC_STATUS_LIST_END;
1854 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1856 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
1857 topic = "*private*";
1858 memset(usercount, 0, sizeof(usercount));
1860 topic = entry->topic;
1861 users = silc_list_count(entry->user_list);
1862 SILC_PUT32_MSB(users, usercount);
1865 /* Send the reply */
1868 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1870 2, idp->data, idp->len,
1871 3, entry->channel_name,
1872 strlen(entry->channel_name),
1873 4, topic, strlen(topic),
1877 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1879 2, idp->data, idp->len,
1880 3, entry->channel_name,
1881 strlen(entry->channel_name),
1883 silc_server_packet_send(cmd->server, cmd->sock,
1884 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
1885 packet->len, FALSE);
1886 silc_buffer_free(packet);
1887 silc_buffer_free(idp);
1890 status = i ? SILC_STATUS_LIST_ITEM : SILC_STATUS_OK;
1893 for (i = 0; i < gch_count; i++) {
1900 status = SILC_STATUS_LIST_ITEM;
1902 if (gch_count > 1 && i == lch_count - 1)
1903 status = SILC_STATUS_LIST_END;
1905 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1907 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
1908 topic = "*private*";
1909 memset(usercount, 0, sizeof(usercount));
1911 topic = entry->topic;
1912 users = silc_list_count(entry->user_list);
1913 SILC_PUT32_MSB(users, usercount);
1916 /* Send the reply */
1919 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1921 2, idp->data, idp->len,
1922 3, entry->channel_name,
1923 strlen(entry->channel_name),
1924 4, topic, strlen(topic),
1928 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1930 2, idp->data, idp->len,
1931 3, entry->channel_name,
1932 strlen(entry->channel_name),
1934 silc_server_packet_send(cmd->server, cmd->sock,
1935 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
1936 packet->len, FALSE);
1937 silc_buffer_free(packet);
1938 silc_buffer_free(idp);
1942 /* Server side of LIST command. This lists the channel of the requested
1943 server. Secret channels are not listed. */
1945 SILC_SERVER_CMD_FUNC(list)
1947 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1948 SilcServer server = cmd->server;
1949 SilcChannelID *channel_id = NULL;
1952 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
1953 uint32 lch_count = 0, gch_count = 0;
1955 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LIST, cmd, 0, 2);
1957 /* Get Channel ID */
1958 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1960 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1962 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
1963 SILC_STATUS_ERR_NO_CHANNEL_ID);
1968 /* Get the channels from local list */
1969 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
1972 /* Get the channels from global list if we are router */
1973 if (server->server_type == SILC_ROUTER)
1974 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
1977 /* Send the reply */
1978 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
1979 gchannels, gch_count);
1982 silc_server_command_free(cmd);
1985 /* Server side of TOPIC command. Sets topic for channel and/or returns
1986 current topic to client. */
1988 SILC_SERVER_CMD_FUNC(topic)
1990 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1991 SilcServer server = cmd->server;
1992 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1993 SilcChannelID *channel_id;
1994 SilcChannelEntry channel;
1995 SilcChannelClientEntry chl;
1996 SilcBuffer packet, idp;
1998 uint32 argc, tmp_len;
1999 uint16 ident = silc_command_get_ident(cmd->payload);
2001 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
2003 argc = silc_argument_get_arg_num(cmd->args);
2005 /* Get Channel ID */
2006 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2008 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2009 SILC_STATUS_ERR_NO_CHANNEL_ID);
2012 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2014 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2015 SILC_STATUS_ERR_NO_CHANNEL_ID);
2019 /* Check whether the channel exists */
2020 channel = silc_idlist_find_channel_by_id(server->local_list,
2023 channel = silc_idlist_find_channel_by_id(server->global_list,
2026 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2027 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2034 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2036 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2037 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2041 if (strlen(tmp) > 256) {
2042 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2043 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2047 /* See whether has rights to change topic */
2048 silc_list_start(channel->user_list);
2049 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2050 if (chl->client == client)
2053 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2054 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2055 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2056 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2061 /* Set the topic for channel */
2063 silc_free(channel->topic);
2064 channel->topic = strdup(tmp);
2066 /* Send TOPIC_SET notify type to the network */
2067 if (!server->standalone)
2068 silc_server_send_notify_topic_set(server, server->router->connection,
2069 server->server_type == SILC_ROUTER ?
2070 TRUE : FALSE, channel, client->id,
2073 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2075 /* Send notify about topic change to all clients on the channel */
2076 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2077 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2078 idp->data, idp->len,
2079 channel->topic, strlen(channel->topic));
2080 silc_buffer_free(idp);
2083 /* Send the topic to client as reply packet */
2084 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2086 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2087 SILC_STATUS_OK, ident, 2,
2088 2, idp->data, idp->len,
2090 strlen(channel->topic));
2092 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2093 SILC_STATUS_OK, ident, 1,
2094 2, idp->data, idp->len);
2095 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2096 0, packet->data, packet->len, FALSE);
2098 silc_buffer_free(packet);
2099 silc_buffer_free(idp);
2100 silc_free(channel_id);
2103 silc_server_command_free(cmd);
2106 /* Server side of INVITE command. Invites some client to join some channel.
2107 This command is also used to manage the invite list of the channel. */
2109 SILC_SERVER_CMD_FUNC(invite)
2111 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2112 SilcServer server = cmd->server;
2113 SilcSocketConnection sock = cmd->sock, dest_sock;
2114 SilcChannelClientEntry chl;
2115 SilcClientEntry sender, dest;
2116 SilcClientID *dest_id = NULL;
2117 SilcChannelEntry channel;
2118 SilcChannelID *channel_id = NULL;
2119 SilcIDListData idata;
2120 SilcBuffer idp, idp2, packet;
2121 unsigned char *tmp, *add, *del;
2123 uint16 ident = silc_command_get_ident(cmd->payload);
2125 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 4);
2127 /* Get Channel ID */
2128 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2130 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2131 SILC_STATUS_ERR_NO_CHANNEL_ID);
2134 channel_id = silc_id_payload_parse_id(tmp, len);
2136 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2137 SILC_STATUS_ERR_NO_CHANNEL_ID);
2141 /* Get the channel entry */
2142 channel = silc_idlist_find_channel_by_id(server->local_list,
2145 channel = silc_idlist_find_channel_by_id(server->global_list,
2148 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2149 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2154 /* Check whether the sender of this command is on the channel. */
2155 sender = (SilcClientEntry)sock->user_data;
2156 if (!silc_server_client_on_channel(sender, channel)) {
2157 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2158 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2162 /* Check whether the channel is invite-only channel. If yes then the
2163 sender of this command must be at least channel operator. */
2164 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2165 silc_list_start(channel->user_list);
2166 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2167 if (chl->client == sender) {
2168 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2169 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2170 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2177 /* Get destination client ID */
2178 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2182 dest_id = silc_id_payload_parse_id(tmp, len);
2184 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2185 SILC_STATUS_ERR_NO_CLIENT_ID);
2189 /* Get the client entry */
2190 dest = silc_server_get_client_resolve(server, dest_id);
2192 if (server->server_type == SILC_ROUTER) {
2193 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2194 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2198 /* The client info is being resolved. Reprocess this packet after
2199 receiving the reply to the query. */
2200 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2202 silc_server_command_destructor,
2203 silc_server_command_invite,
2204 silc_server_command_dup(cmd));
2205 cmd->pending = TRUE;
2206 silc_free(channel_id);
2211 /* Check whether the requested client is already on the channel. */
2212 if (silc_server_client_on_channel(dest, channel)) {
2213 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2214 SILC_STATUS_ERR_USER_ON_CHANNEL);
2218 /* Get route to the client */
2219 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2221 memset(invite, 0, sizeof(invite));
2222 strncat(invite, dest->nickname, strlen(dest->nickname));
2223 strncat(invite, "!", 1);
2224 strncat(invite, dest->username, strlen(dest->username));
2225 if (!strchr(dest->username, '@')) {
2226 strncat(invite, "@", 1);
2227 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2230 len = strlen(invite);
2231 if (!channel->invite_list)
2232 channel->invite_list = silc_calloc(len + 2,
2233 sizeof(*channel->invite_list));
2235 channel->invite_list = silc_realloc(channel->invite_list,
2236 sizeof(*channel->invite_list) *
2238 strlen(channel->invite_list) + 2));
2239 strncat(channel->invite_list, invite, len);
2240 strncat(channel->invite_list, ",", 1);
2242 /* Send notify to the client that is invited to the channel */
2243 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2244 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2245 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2247 SILC_NOTIFY_TYPE_INVITE, 3,
2248 idp->data, idp->len,
2249 channel->channel_name,
2250 strlen(channel->channel_name),
2251 idp2->data, idp2->len);
2252 silc_buffer_free(idp);
2253 silc_buffer_free(idp2);
2256 /* Add the client to the invite list of the channel */
2257 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2259 if (!channel->invite_list)
2260 channel->invite_list = silc_calloc(len + 2,
2261 sizeof(*channel->invite_list));
2263 channel->invite_list = silc_realloc(channel->invite_list,
2264 sizeof(*channel->invite_list) *
2266 strlen(channel->invite_list) + 2));
2267 if (add[len - 1] == ',')
2268 add[len - 1] = '\0';
2270 strncat(channel->invite_list, add, len);
2271 strncat(channel->invite_list, ",", 1);
2274 /* Get the invite to be removed and remove it from the list */
2275 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2276 if (del && channel->invite_list) {
2277 char *start, *end, *n;
2279 if (!strncmp(channel->invite_list, del,
2280 strlen(channel->invite_list) - 1)) {
2281 silc_free(channel->invite_list);
2282 channel->invite_list = NULL;
2284 start = strstr(channel->invite_list, del);
2285 if (start && strlen(start) >= len) {
2287 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2288 strncat(n, channel->invite_list, start - channel->invite_list);
2289 strncat(n, end + 1, ((channel->invite_list +
2290 strlen(channel->invite_list)) - end) - 1);
2291 silc_free(channel->invite_list);
2292 channel->invite_list = n;
2297 /* Send notify to the primary router */
2298 if (!server->standalone)
2299 silc_server_send_notify_invite(server, server->router->connection,
2300 server->server_type == SILC_ROUTER ?
2301 TRUE : FALSE, channel,
2302 sender->id, add, del);
2304 /* Send command reply */
2305 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2306 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2307 SILC_STATUS_OK, ident, 2,
2309 3, channel->invite_list,
2310 channel->invite_list ?
2311 strlen(channel->invite_list) :
2313 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2314 packet->data, packet->len, FALSE);
2315 silc_buffer_free(packet);
2321 silc_free(channel_id);
2322 silc_server_command_free(cmd);
2327 SilcSocketConnection sock;
2331 /* Quits connection to client. This gets called if client won't
2332 close the connection even when it has issued QUIT command. */
2334 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2336 QuitInternal q = (QuitInternal)context;
2338 /* Free all client specific data, such as client entry and entires
2339 on channels this client may be on. */
2340 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2342 q->sock->user_data = NULL;
2344 /* Close the connection on our side */
2345 silc_server_close_connection(q->server, q->sock);
2347 silc_free(q->signoff);
2351 /* Quits SILC session. This is the normal way to disconnect client. */
2353 SILC_SERVER_CMD_FUNC(quit)
2355 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2356 SilcServer server = cmd->server;
2357 SilcSocketConnection sock = cmd->sock;
2359 unsigned char *tmp = NULL;
2362 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_QUIT, cmd, 0, 1);
2364 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2367 /* Get destination ID */
2368 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2372 q = silc_calloc(1, sizeof(*q));
2375 q->signoff = tmp ? strdup(tmp) : NULL;
2377 /* We quit the connection with little timeout */
2378 silc_task_register(server->timeout_queue, sock->sock,
2379 silc_server_command_quit_cb, (void *)q,
2380 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2383 silc_server_command_free(cmd);
2386 /* Server side of command KILL. This command is used by router operator
2387 to remove an client from the SILC Network temporarily. */
2389 SILC_SERVER_CMD_FUNC(kill)
2391 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2392 SilcServer server = cmd->server;
2393 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2394 SilcClientEntry remote_client;
2395 SilcClientID *client_id;
2396 unsigned char *tmp, *comment;
2397 uint32 tmp_len, tmp_len2;
2399 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_KILL, cmd, 1, 2);
2401 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2404 /* KILL command works only on router */
2405 if (server->server_type != SILC_ROUTER) {
2406 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2407 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2411 /* Check whether client has the permissions. */
2412 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2413 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2414 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2418 /* Get the client ID */
2419 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2421 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2422 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2425 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2427 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2428 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2432 /* Get the client entry */
2433 remote_client = silc_idlist_find_client_by_id(server->local_list,
2435 if (!remote_client) {
2436 remote_client = silc_idlist_find_client_by_id(server->global_list,
2438 if (!remote_client) {
2439 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2440 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2446 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2450 /* Send reply to the sender */
2451 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2454 /* Send the KILL notify packets. First send it to the channel, then
2455 to our primary router and then directly to the client who is being
2456 killed right now. */
2458 /* Send KILLED notify to the channels. It is not sent to the client
2459 as it will be sent differently destined directly to the client and not
2461 silc_server_send_notify_on_channels(server, remote_client,
2462 remote_client, SILC_NOTIFY_TYPE_KILLED,
2465 comment, comment ? tmp_len2 : 0);
2467 /* Send KILLED notify to primary route */
2468 if (!server->standalone)
2469 silc_server_send_notify_killed(server, server->router->connection, TRUE,
2470 remote_client->id, comment);
2472 /* Send KILLED notify to the client directly */
2473 silc_server_send_notify_killed(server, remote_client->connection ?
2474 remote_client->connection :
2475 remote_client->router->connection, FALSE,
2476 remote_client->id, comment);
2478 /* Remove the client from all channels. This generates new keys to the
2479 channels as well. */
2480 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2483 /* Remove the client entry, If it is locally connected then we will also
2484 disconnect the client here */
2485 if (remote_client->data.registered && remote_client->connection) {
2486 /* Remove locally conneted client */
2487 SilcSocketConnection sock = remote_client->connection;
2488 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2489 silc_server_close_connection(server, sock);
2491 /* Remove remote client */
2492 if (!silc_idlist_del_client(server->global_list, remote_client))
2493 silc_idlist_del_client(server->local_list, remote_client);
2497 silc_server_command_free(cmd);
2500 /* Server side of command INFO. This sends information about us to
2501 the client. If client requested specific server we will send the
2502 command to that server. */
2504 SILC_SERVER_CMD_FUNC(info)
2506 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2507 SilcServer server = cmd->server;
2508 SilcBuffer packet, idp;
2511 char *dest_server, *server_info = NULL, *server_name;
2512 uint16 ident = silc_command_get_ident(cmd->payload);
2513 SilcServerEntry entry = NULL;
2514 SilcServerID *server_id = NULL;
2516 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 0, 2);
2518 /* Get server name */
2519 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2522 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2524 server_id = silc_id_payload_parse_id(tmp, tmp_len);
2526 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2527 SILC_STATUS_ERR_NO_SERVER_ID);
2533 /* Check whether we have this server cached */
2534 entry = silc_idlist_find_server_by_id(server->local_list,
2537 entry = silc_idlist_find_server_by_id(server->global_list,
2539 if (!entry && server->server_type == SILC_ROUTER) {
2540 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2541 SILC_STATUS_ERR_NO_SUCH_SERVER);
2547 if ((!dest_server && !server_id) ||
2548 (dest_server && !cmd->pending &&
2549 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2550 /* Send our reply */
2551 char info_string[256];
2553 memset(info_string, 0, sizeof(info_string));
2554 snprintf(info_string, sizeof(info_string),
2555 "location: %s server: %s admin: %s <%s>",
2556 server->config->admin_info->location,
2557 server->config->admin_info->server_type,
2558 server->config->admin_info->admin_name,
2559 server->config->admin_info->admin_email);
2561 server_info = info_string;
2562 entry = server->id_entry;
2564 /* Check whether we have this server cached */
2565 if (!entry && dest_server) {
2566 entry = silc_idlist_find_server_by_name(server->global_list,
2569 entry = silc_idlist_find_server_by_name(server->local_list,
2574 if (!cmd->pending &&
2575 server->server_type == SILC_ROUTER && entry && !entry->server_info) {
2576 /* Send to the server */
2580 old_ident = silc_command_get_ident(cmd->payload);
2581 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2582 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2584 silc_server_packet_send(server, entry->connection,
2585 SILC_PACKET_COMMAND, cmd->packet->flags,
2586 tmpbuf->data, tmpbuf->len, TRUE);
2588 /* Reprocess this packet after received reply from router */
2589 silc_server_command_pending(server, SILC_COMMAND_INFO,
2590 silc_command_get_ident(cmd->payload),
2591 silc_server_command_destructor,
2592 silc_server_command_info,
2593 silc_server_command_dup(cmd));
2594 cmd->pending = TRUE;
2595 silc_command_set_ident(cmd->payload, old_ident);
2596 silc_buffer_free(tmpbuf);
2600 if (!entry && !cmd->pending && !server->standalone) {
2601 /* Send to the primary router */
2605 old_ident = silc_command_get_ident(cmd->payload);
2606 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2607 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2609 silc_server_packet_send(server, server->router->connection,
2610 SILC_PACKET_COMMAND, cmd->packet->flags,
2611 tmpbuf->data, tmpbuf->len, TRUE);
2613 /* Reprocess this packet after received reply from router */
2614 silc_server_command_pending(server, SILC_COMMAND_INFO,
2615 silc_command_get_ident(cmd->payload),
2616 silc_server_command_destructor,
2617 silc_server_command_info,
2618 silc_server_command_dup(cmd));
2619 cmd->pending = TRUE;
2620 silc_command_set_ident(cmd->payload, old_ident);
2621 silc_buffer_free(tmpbuf);
2627 silc_free(server_id);
2630 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2631 SILC_STATUS_ERR_NO_SUCH_SERVER);
2635 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2637 server_info = entry->server_info;
2638 server_name = entry->server_name;
2640 /* Send the reply */
2641 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2642 SILC_STATUS_OK, ident, 3,
2643 2, idp->data, idp->len,
2645 strlen(server_name),
2647 strlen(server_info));
2648 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2649 packet->data, packet->len, FALSE);
2651 silc_buffer_free(packet);
2652 silc_buffer_free(idp);
2655 silc_server_command_free(cmd);
2658 /* Server side of command PING. This just replies to the ping. */
2660 SILC_SERVER_CMD_FUNC(ping)
2662 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2663 SilcServer server = cmd->server;
2668 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
2671 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2673 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2674 SILC_STATUS_ERR_NO_SERVER_ID);
2677 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2681 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2682 /* Send our reply */
2683 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2686 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2687 SILC_STATUS_ERR_NO_SUCH_SERVER);
2694 silc_server_command_free(cmd);
2697 /* Internal routine to join channel. The channel sent to this function
2698 has been either created or resolved from ID lists. This joins the sent
2699 client to the channel. */
2701 static void silc_server_command_join_channel(SilcServer server,
2702 SilcServerCommandContext cmd,
2703 SilcChannelEntry channel,
2704 SilcClientID *client_id,
2708 SilcSocketConnection sock = cmd->sock;
2710 uint32 tmp_len, user_count;
2711 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
2712 SilcClientEntry client;
2713 SilcChannelClientEntry chl;
2714 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
2715 uint16 ident = silc_command_get_ident(cmd->payload);
2718 SILC_LOG_DEBUG(("Start"));
2723 /* Get the client entry */
2724 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2725 client = (SilcClientEntry)sock->user_data;
2727 client = silc_idlist_find_client_by_id(server->local_list, client_id,
2734 * Check channel modes
2737 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2738 strncat(check, client->nickname, strlen(client->nickname));
2739 if (!strchr(client->nickname, '@')) {
2740 strncat(check, "@", 1);
2741 strncat(check, server->server_name, strlen(server->server_name));
2743 strncat(check, "!", 1);
2744 strncat(check, client->username, strlen(client->username));
2745 if (!strchr(client->username, '@')) {
2746 strncat(check, "@", 1);
2747 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
2751 /* Check invite list if channel is invite-only channel */
2752 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
2753 channel->mode & SILC_CHANNEL_MODE_INVITE) {
2754 if (!channel->invite_list) {
2755 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2756 SILC_STATUS_ERR_NOT_INVITED);
2760 if (!silc_string_match(channel->invite_list, check)) {
2761 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2762 SILC_STATUS_ERR_NOT_INVITED);
2767 /* Check ban list if it exists. If the client's nickname, server,
2768 username and/or hostname is in the ban list the access to the
2769 channel is denied. */
2770 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && channel->ban_list) {
2771 if (silc_string_match(channel->ban_list, check)) {
2772 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2773 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
2778 /* Get passphrase */
2779 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2781 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
2782 memcpy(passphrase, tmp, tmp_len);
2785 /* Check the channel passphrase if set. */
2786 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2787 if (!passphrase || memcmp(channel->passphrase, passphrase,
2788 strlen(channel->passphrase))) {
2789 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2790 SILC_STATUS_ERR_BAD_PASSWORD);
2795 /* Check user count limit if set. */
2796 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
2797 if (silc_list_count(channel->user_list) + 1 >
2798 channel->user_limit) {
2799 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2800 SILC_STATUS_ERR_CHANNEL_IS_FULL);
2806 * Client is allowed to join to the channel. Make it happen.
2809 /* Check whether the client already is on the channel */
2810 if (silc_server_client_on_channel(client, channel)) {
2811 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2812 SILC_STATUS_ERR_USER_ON_CHANNEL);
2816 /* Generate new channel key as protocol dictates */
2817 if ((!created && silc_list_count(channel->user_list) > 0) ||
2818 !channel->channel_key)
2819 silc_server_create_channel_key(server, channel, 0);
2821 /* Send the channel key. This is broadcasted to the channel but is not
2822 sent to the client who is joining to the channel. */
2823 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
2824 silc_server_send_channel_key(server, NULL, channel,
2825 server->server_type == SILC_ROUTER ?
2826 FALSE : !server->standalone);
2828 /* Join the client to the channel by adding it to channel's user list.
2829 Add also the channel to client entry's channels list for fast cross-
2831 chl = silc_calloc(1, sizeof(*chl));
2833 chl->client = client;
2834 chl->channel = channel;
2835 silc_list_add(channel->user_list, chl);
2836 silc_list_add(client->channels, chl);
2838 /* Get users on the channel */
2839 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
2842 /* Encode Client ID Payload of the original client who wants to join */
2843 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2845 /* Encode command reply packet */
2846 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2847 SILC_PUT32_MSB(channel->mode, mode);
2848 SILC_PUT32_MSB(created, tmp2);
2849 SILC_PUT32_MSB(user_count, tmp3);
2851 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
2852 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
2853 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
2854 strlen(channel->channel_key->
2856 channel->channel_key->cipher->name,
2857 channel->key_len / 8, channel->key);
2862 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2863 SILC_STATUS_OK, ident, 13,
2864 2, channel->channel_name,
2865 strlen(channel->channel_name),
2866 3, chidp->data, chidp->len,
2867 4, clidp->data, clidp->len,
2870 7, keyp ? keyp->data : NULL,
2871 keyp ? keyp->len : 0,
2872 8, channel->ban_list,
2874 strlen(channel->ban_list) : 0,
2875 9, channel->invite_list,
2876 channel->invite_list ?
2877 strlen(channel->invite_list) : 0,
2880 strlen(channel->topic) : 0,
2881 11, channel->hmac->hmac->name,
2882 strlen(channel->hmac->hmac->name),
2884 13, user_list->data, user_list->len,
2885 14, mode_list->data,
2888 /* Send command reply */
2889 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
2890 reply->data, reply->len, FALSE);
2892 if (!cmd->pending) {
2893 /* Send JOIN notify to locally connected clients on the channel */
2894 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2895 SILC_NOTIFY_TYPE_JOIN, 2,
2896 clidp->data, clidp->len,
2897 chidp->data, chidp->len);
2899 /* Send JOIN notify packet to our primary router */
2900 if (!server->standalone)
2901 silc_server_send_notify_join(server, server->router->connection,
2902 server->server_type == SILC_ROUTER ?
2903 TRUE : FALSE, channel, client->id);
2906 silc_buffer_free(reply);
2907 silc_buffer_free(clidp);
2908 silc_buffer_free(chidp);
2909 silc_buffer_free(keyp);
2910 silc_buffer_free(user_list);
2911 silc_buffer_free(mode_list);
2915 silc_free(passphrase);
2918 /* Server side of command JOIN. Joins client into requested channel. If
2919 the channel does not exist it will be created. */
2921 SILC_SERVER_CMD_FUNC(join)
2923 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2924 SilcServer server = cmd->server;
2926 char *tmp, *channel_name = NULL, *cipher, *hmac;
2927 SilcChannelEntry channel;
2929 int created = FALSE;
2930 SilcClientID *client_id;
2932 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
2934 /* Get channel name */
2935 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2937 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2938 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2943 if (strlen(channel_name) > 256)
2944 channel_name[255] = '\0';
2946 if (silc_server_command_bad_chars(channel_name) == TRUE) {
2947 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2948 SILC_STATUS_ERR_BAD_CHANNEL);
2949 silc_free(channel_name);
2953 /* Get Client ID of the client who is joining to the channel */
2954 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2956 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2957 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2960 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2962 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2963 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2967 /* Get cipher and hmac name */
2968 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2969 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2971 /* See if the channel exists */
2972 channel = silc_idlist_find_channel_by_name(server->local_list,
2973 channel_name, NULL);
2975 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2976 /* If this is coming from client the Client ID in the command packet must
2977 be same as the client's ID. */
2978 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2979 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2980 if (!SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
2981 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2982 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2987 if (!channel || !channel->id) {
2988 /* Channel not found */
2990 /* If we are standalone server we don't have a router, we just create
2991 the channel by ourselves. */
2992 if (server->standalone) {
2993 channel = silc_server_create_new_channel(server, server->id, cipher,
2994 hmac, channel_name, TRUE);
2996 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2997 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3001 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3006 /* The channel does not exist on our server. If we are normal server
3007 we will send JOIN command to our router which will handle the
3008 joining procedure (either creates the channel if it doesn't exist
3009 or joins the client to it). */
3010 if (server->server_type == SILC_SERVER) {
3014 old_ident = silc_command_get_ident(cmd->payload);
3015 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3016 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3018 /* Send JOIN command to our router */
3019 silc_server_packet_send(server, (SilcSocketConnection)
3020 server->router->connection,
3021 SILC_PACKET_COMMAND, cmd->packet->flags,
3022 tmpbuf->data, tmpbuf->len, TRUE);
3024 /* Reprocess this packet after received reply from router */
3025 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3026 silc_command_get_ident(cmd->payload),
3027 silc_server_command_destructor,
3028 silc_server_command_join,
3029 silc_server_command_dup(cmd));
3030 cmd->pending = TRUE;
3034 /* We are router and the channel does not seem exist so we will check
3035 our global list as well for the channel. */
3036 channel = silc_idlist_find_channel_by_name(server->global_list,
3037 channel_name, NULL);
3039 /* Channel really does not exist, create it */
3040 channel = silc_server_create_new_channel(server, server->id, cipher,
3041 hmac, channel_name, TRUE);
3043 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3044 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3048 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3055 /* Channel not found */
3057 /* If the command came from router and/or we are normal server then
3058 something went wrong with the joining as the channel was not found.
3059 We can't do anything else but ignore this. */
3060 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3061 server->server_type == SILC_SERVER)
3064 /* We are router and the channel does not seem exist so we will check
3065 our global list as well for the channel. */
3066 channel = silc_idlist_find_channel_by_name(server->global_list,
3067 channel_name, NULL);
3069 /* Channel really does not exist, create it */
3070 channel = silc_server_create_new_channel(server, server->id, cipher,
3071 hmac, channel_name, TRUE);
3073 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3074 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3078 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3084 /* If the channel does not have global users and is also empty it means the
3085 channel was created globally (by our router) and the client will be the
3086 channel founder and operator. */
3087 if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
3088 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3089 created = TRUE; /* Created globally by our router */
3092 /* Join to the channel */
3093 silc_server_command_join_channel(server, cmd, channel, client_id,
3096 silc_free(client_id);
3099 silc_server_command_free(cmd);
3102 /* Server side of command MOTD. Sends server's current "message of the
3103 day" to the client. */
3105 SILC_SERVER_CMD_FUNC(motd)
3107 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3108 SilcServer server = cmd->server;
3109 SilcBuffer packet, idp;
3110 char *motd, *dest_server;
3112 uint16 ident = silc_command_get_ident(cmd->payload);
3114 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 1);
3116 /* Get server name */
3117 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3119 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3120 SILC_STATUS_ERR_NO_SUCH_SERVER);
3124 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3127 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3129 if (server->config && server->config->motd &&
3130 server->config->motd->motd_file) {
3132 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
3137 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3138 SILC_STATUS_OK, ident, 2,
3144 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3145 SILC_STATUS_OK, ident, 1,
3149 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3150 packet->data, packet->len, FALSE);
3151 silc_buffer_free(packet);
3152 silc_buffer_free(idp);
3154 SilcServerEntry entry;
3156 /* Check whether we have this server cached */
3157 entry = silc_idlist_find_server_by_name(server->global_list,
3160 entry = silc_idlist_find_server_by_name(server->local_list,
3164 if (server->server_type == SILC_ROUTER && !cmd->pending &&
3165 entry && !entry->motd) {
3166 /* Send to the server */
3170 old_ident = silc_command_get_ident(cmd->payload);
3171 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3172 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3174 silc_server_packet_send(server, entry->connection,
3175 SILC_PACKET_COMMAND, cmd->packet->flags,
3176 tmpbuf->data, tmpbuf->len, TRUE);
3178 /* Reprocess this packet after received reply from router */
3179 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3180 silc_command_get_ident(cmd->payload),
3181 silc_server_command_destructor,
3182 silc_server_command_motd,
3183 silc_server_command_dup(cmd));
3184 cmd->pending = TRUE;
3185 silc_command_set_ident(cmd->payload, old_ident);
3186 silc_buffer_free(tmpbuf);
3190 if (!entry && !cmd->pending && !server->standalone) {
3191 /* Send to the primary router */
3195 old_ident = silc_command_get_ident(cmd->payload);
3196 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3197 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3199 silc_server_packet_send(server, server->router->connection,
3200 SILC_PACKET_COMMAND, cmd->packet->flags,
3201 tmpbuf->data, tmpbuf->len, TRUE);
3203 /* Reprocess this packet after received reply from router */
3204 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3205 silc_command_get_ident(cmd->payload),
3206 silc_server_command_destructor,
3207 silc_server_command_motd,
3208 silc_server_command_dup(cmd));
3209 cmd->pending = TRUE;
3210 silc_command_set_ident(cmd->payload, old_ident);
3211 silc_buffer_free(tmpbuf);
3216 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3217 SILC_STATUS_ERR_NO_SUCH_SERVER);
3221 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3224 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3225 SILC_STATUS_OK, ident, 2,
3228 strlen(entry->motd));
3230 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3231 SILC_STATUS_OK, ident, 1,
3234 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3235 packet->data, packet->len, FALSE);
3236 silc_buffer_free(packet);
3237 silc_buffer_free(idp);
3241 silc_server_command_free(cmd);
3244 /* Server side of command UMODE. Client can use this command to set/unset
3245 user mode. Client actually cannot set itself to be as server/router
3246 operator so this can be used only to unset the modes. */
3248 SILC_SERVER_CMD_FUNC(umode)
3250 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3251 SilcServer server = cmd->server;
3252 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3254 unsigned char *tmp_mask;
3256 uint16 ident = silc_command_get_ident(cmd->payload);
3258 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3261 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_UMODE, cmd, 2, 2);
3263 /* Get the client's mode mask */
3264 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3266 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3267 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3270 SILC_GET32_MSB(mask, tmp_mask);
3276 if (mask & SILC_UMODE_SERVER_OPERATOR) {
3277 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR)) {
3278 /* Cannot operator mode */
3279 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3280 SILC_STATUS_ERR_PERM_DENIED);
3284 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
3285 /* Remove the server operator rights */
3286 client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3289 if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3290 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
3291 /* Cannot operator mode */
3292 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3293 SILC_STATUS_ERR_PERM_DENIED);
3297 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
3298 /* Remove the router operator rights */
3299 client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3302 if (mask & SILC_UMODE_GONE) {
3303 client->mode |= SILC_UMODE_GONE;
3305 if (client->mode & SILC_UMODE_GONE)
3306 /* Remove the gone status */
3307 client->mode &= ~SILC_UMODE_GONE;
3310 /* Send UMODE change to primary router */
3311 if (!server->standalone)
3312 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3313 client->id, client->mode);
3315 /* Send command reply to sender */
3316 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3317 SILC_STATUS_OK, ident, 1,
3319 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3320 packet->data, packet->len, FALSE);
3321 silc_buffer_free(packet);
3324 silc_server_command_free(cmd);
3327 /* Checks that client has rights to add or remove channel modes. If any
3328 of the checks fails FALSE is returned. */
3330 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3331 SilcChannelClientEntry client,
3334 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3335 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3337 /* Check whether has rights to change anything */
3338 if (!is_op && !is_fo)
3341 /* Check whether has rights to change everything */
3345 /* We know that client is channel operator, check that they are not
3346 changing anything that requires channel founder rights. Rest of the
3347 modes are available automatically for channel operator. */
3349 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3350 if (is_op && !is_fo)
3353 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3354 if (is_op && !is_fo)
3359 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3360 if (is_op && !is_fo)
3363 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3364 if (is_op && !is_fo)
3369 if (mode & SILC_CHANNEL_MODE_CIPHER) {
3370 if (is_op && !is_fo)
3373 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3374 if (is_op && !is_fo)
3379 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3380 if (is_op && !is_fo)
3383 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3384 if (is_op && !is_fo)
3392 /* Server side command of CMODE. Changes channel mode */
3394 SILC_SERVER_CMD_FUNC(cmode)
3396 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3397 SilcServer server = cmd->server;
3398 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3399 SilcIDListData idata = (SilcIDListData)client;
3400 SilcChannelID *channel_id;
3401 SilcChannelEntry channel;
3402 SilcChannelClientEntry chl;
3403 SilcBuffer packet, cidp;
3404 unsigned char *tmp, *tmp_id, *tmp_mask;
3405 char *cipher = NULL, *hmac = NULL;
3406 uint32 mode_mask, tmp_len, tmp_len2;
3407 uint16 ident = silc_command_get_ident(cmd->payload);
3409 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CMODE, cmd, 2, 7);
3411 /* Get Channel ID */
3412 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3414 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3415 SILC_STATUS_ERR_NO_CHANNEL_ID);
3418 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3420 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3421 SILC_STATUS_ERR_NO_CHANNEL_ID);
3425 /* Get the channel mode mask */
3426 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3428 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3429 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3432 SILC_GET32_MSB(mode_mask, tmp_mask);
3434 /* Get channel entry */
3435 channel = silc_idlist_find_channel_by_id(server->local_list,
3438 channel = silc_idlist_find_channel_by_id(server->global_list,
3441 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3442 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3447 /* Check whether this client is on the channel */
3448 if (!silc_server_client_on_channel(client, channel)) {
3449 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3450 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3454 /* Get entry to the channel user list */
3455 silc_list_start(channel->user_list);
3456 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
3457 if (chl->client == client)
3460 /* Check that client has rights to change any requested channel modes */
3461 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3462 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3463 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3468 * Check the modes. Modes that requires nothing special operation are
3472 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3473 /* Channel uses private keys to protect traffic. Client(s) has set the
3474 key locally they want to use, server does not know that key. */
3475 /* Nothing interesting to do here */
3477 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3478 /* The mode is removed and we need to generate and distribute
3479 new channel key. Clients are not using private channel keys
3480 anymore after this. */
3482 /* Re-generate channel key */
3483 silc_server_create_channel_key(server, channel, 0);
3485 /* Send the channel key. This sends it to our local clients and if
3486 we are normal server to our router as well. */
3487 silc_server_send_channel_key(server, NULL, channel,
3488 server->server_type == SILC_ROUTER ?
3489 FALSE : !server->standalone);
3491 cipher = channel->channel_key->cipher->name;
3492 hmac = channel->hmac->hmac->name;
3496 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3497 /* User limit is set on channel */
3500 /* Get user limit */
3501 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3503 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3504 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3505 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3509 SILC_GET32_MSB(user_limit, tmp);
3510 channel->user_limit = user_limit;
3513 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3514 /* User limit mode is unset. Remove user limit */
3515 channel->user_limit = 0;
3518 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3519 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3520 /* Passphrase has been set to channel */
3522 /* Get the passphrase */
3523 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3525 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3526 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3530 /* Save the passphrase */
3531 channel->passphrase = strdup(tmp);
3534 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3535 /* Passphrase mode is unset. remove the passphrase */
3536 if (channel->passphrase) {
3537 silc_free(channel->passphrase);
3538 channel->passphrase = NULL;
3543 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3544 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3545 /* Cipher to use protect the traffic */
3548 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3550 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3551 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3555 /* Delete old cipher and allocate the new one */
3556 silc_cipher_free(channel->channel_key);
3557 if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
3558 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3559 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3563 /* Re-generate channel key */
3564 silc_server_create_channel_key(server, channel, 0);
3566 /* Send the channel key. This sends it to our local clients and if
3567 we are normal server to our router as well. */
3568 silc_server_send_channel_key(server, NULL, channel,
3569 server->server_type == SILC_ROUTER ?
3570 FALSE : !server->standalone);
3573 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3574 /* Cipher mode is unset. Remove the cipher and revert back to
3576 cipher = channel->cipher;
3578 /* Delete old cipher and allocate default one */
3579 silc_cipher_free(channel->channel_key);
3580 if (!silc_cipher_alloc(cipher ? cipher : "aes-256-cbc",
3581 &channel->channel_key)) {
3582 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3583 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3587 /* Re-generate channel key */
3588 silc_server_create_channel_key(server, channel, 0);
3590 /* Send the channel key. This sends it to our local clients and if
3591 we are normal server to our router as well. */
3592 silc_server_send_channel_key(server, NULL, channel,
3593 server->server_type == SILC_ROUTER ?
3594 FALSE : !server->standalone);
3598 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3599 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3600 /* HMAC to use protect the traffic */
3601 unsigned char hash[32];
3604 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3606 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3607 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3611 /* Delete old hmac and allocate the new one */
3612 silc_hmac_free(channel->hmac);
3613 if (!silc_hmac_alloc(hmac, NULL, &channel->hmac)) {
3614 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3615 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3619 /* Set the HMAC key out of current channel key. The client must do
3621 silc_hash_make(channel->hmac->hash, channel->key, channel->key_len / 8,
3623 silc_hmac_set_key(channel->hmac, hash,
3624 silc_hash_len(channel->hmac->hash));
3625 memset(hash, 0, sizeof(hash));
3628 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
3629 /* Hmac mode is unset. Remove the hmac and revert back to
3631 unsigned char hash[32];
3632 hmac = channel->hmac_name;
3634 /* Delete old hmac and allocate default one */
3635 silc_hmac_free(channel->hmac);
3636 if (!silc_hmac_alloc(hmac ? hmac : "hmac-sha1-96", NULL,
3638 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3639 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3643 /* Set the HMAC key out of current channel key. The client must do
3645 silc_hash_make(channel->hmac->hash, channel->key, channel->key_len / 8,
3647 silc_hmac_set_key(channel->hmac, hash,
3648 silc_hash_len(channel->hmac->hash));
3649 memset(hash, 0, sizeof(hash));
3653 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3654 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3655 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
3656 /* Set the founder authentication */
3657 SilcAuthPayload auth;
3659 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
3661 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3662 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3666 auth = silc_auth_payload_parse(tmp, tmp_len);
3668 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3669 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3673 /* Save the public key */
3674 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
3675 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
3678 channel->founder_method = silc_auth_get_method(auth);
3680 if (channel->founder_method == SILC_AUTH_PASSWORD) {
3681 tmp = silc_auth_get_data(auth, &tmp_len);
3682 channel->founder_passwd =
3683 silc_calloc(tmp_len + 1, sizeof(*channel->founder_passwd));
3684 memcpy(channel->founder_passwd, tmp, tmp_len);
3685 channel->founder_passwd_len = tmp_len;
3688 silc_auth_payload_free(auth);
3692 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3693 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3694 if (channel->founder_key)
3695 silc_pkcs_public_key_free(channel->founder_key);
3696 if (channel->founder_passwd) {
3697 silc_free(channel->founder_passwd);
3698 channel->founder_passwd = NULL;
3704 /* Finally, set the mode */
3705 channel->mode = mode_mask;
3707 /* Send CMODE_CHANGE notify */
3708 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3709 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3710 SILC_NOTIFY_TYPE_CMODE_CHANGE, 4,
3711 cidp->data, cidp->len,
3713 cipher, cipher ? strlen(cipher) : 0,
3714 hmac, hmac ? strlen(hmac) : 0);
3716 /* Set CMODE notify type to network */
3717 if (!server->standalone)
3718 silc_server_send_notify_cmode(server, server->router->connection,
3719 server->server_type == SILC_ROUTER ?
3720 TRUE : FALSE, channel,
3721 mode_mask, client->id, SILC_ID_CLIENT,
3724 /* Send command reply to sender */
3725 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3726 SILC_STATUS_OK, ident, 1,
3728 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3729 packet->data, packet->len, FALSE);
3731 silc_buffer_free(packet);
3732 silc_free(channel_id);
3736 silc_server_command_free(cmd);
3739 /* Server side of CUMODE command. Changes client's mode on a channel. */
3741 SILC_SERVER_CMD_FUNC(cumode)
3743 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3744 SilcServer server = cmd->server;
3745 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3746 SilcIDListData idata = (SilcIDListData)client;
3747 SilcChannelID *channel_id;
3748 SilcClientID *client_id;
3749 SilcChannelEntry channel;
3750 SilcClientEntry target_client;
3751 SilcChannelClientEntry chl;
3752 SilcBuffer packet, idp;
3753 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
3754 uint32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
3756 uint16 ident = silc_command_get_ident(cmd->payload);
3758 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 4);
3760 /* Get Channel ID */
3761 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3763 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3764 SILC_STATUS_ERR_NO_CHANNEL_ID);
3767 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
3769 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3770 SILC_STATUS_ERR_NO_CHANNEL_ID);
3774 /* Get channel entry */
3775 channel = silc_idlist_find_channel_by_id(server->local_list,
3778 channel = silc_idlist_find_channel_by_id(server->global_list,
3781 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3782 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3787 /* Check whether sender is on the channel */
3788 if (!silc_server_client_on_channel(client, channel)) {
3789 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3790 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3794 /* Check that client has rights to change other's rights */
3795 silc_list_start(channel->user_list);
3796 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3797 if (chl->client == client) {
3798 sender_mask = chl->mode;
3803 /* Get the target client's channel mode mask */
3804 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3806 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3807 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3810 SILC_GET32_MSB(target_mask, tmp_mask);
3812 /* Get target Client ID */
3813 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3815 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3816 SILC_STATUS_ERR_NO_CLIENT_ID);
3819 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
3821 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3822 SILC_STATUS_ERR_NO_CLIENT_ID);
3826 /* Get target client's entry */
3827 target_client = silc_idlist_find_client_by_id(server->local_list,
3829 if (!target_client) {
3830 target_client = silc_idlist_find_client_by_id(server->global_list,
3834 if (target_client != client &&
3835 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
3836 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
3837 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3838 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3842 /* Check whether target client is on the channel */
3843 if (target_client != client) {
3844 if (!silc_server_client_on_channel(target_client, channel)) {
3845 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3846 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
3850 /* Get entry to the channel user list */
3851 silc_list_start(channel->user_list);
3852 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
3853 if (chl->client == target_client)
3861 /* If the target client is founder, no one else can change their mode
3863 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
3864 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3865 SILC_STATUS_ERR_NOT_YOU);
3869 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
3870 /* The client tries to claim the founder rights. */
3871 unsigned char *tmp_auth;
3872 uint32 tmp_auth_len, auth_len;
3875 if (target_client != client) {
3876 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3877 SILC_STATUS_ERR_NOT_YOU);
3881 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
3882 !channel->founder_key) {
3883 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3884 SILC_STATUS_ERR_NOT_YOU);
3888 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
3890 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3891 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3895 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
3896 (void *)channel->founder_passwd : (void *)channel->founder_key);
3897 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
3898 channel->founder_passwd_len : 0);
3900 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
3901 channel->founder_method, auth, auth_len,
3902 idata->hash, client->id, SILC_ID_CLIENT)) {
3903 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3904 SILC_STATUS_ERR_AUTH_FAILED);
3908 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
3911 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3912 if (target_client == client) {
3913 /* Remove channel founder rights from itself */
3914 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3917 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3918 SILC_STATUS_ERR_NOT_YOU);
3924 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
3925 /* Promote to operator */
3926 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3927 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3928 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3929 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3930 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3934 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
3938 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
3939 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3940 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3941 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3942 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3946 /* Demote to normal user */
3947 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
3952 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3953 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3955 /* Send notify to channel, notify only if mode was actually changed. */
3957 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3958 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3959 idp->data, idp->len,
3963 /* Set CUMODE notify type to network */
3964 if (!server->standalone)
3965 silc_server_send_notify_cumode(server, server->router->connection,
3966 server->server_type == SILC_ROUTER ?
3967 TRUE : FALSE, channel,
3968 target_mask, client->id,
3973 /* Send command reply to sender */
3974 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
3975 SILC_STATUS_OK, ident, 2,
3977 3, tmp_id, tmp_len);
3978 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3979 packet->data, packet->len, FALSE);
3981 silc_buffer_free(packet);
3982 silc_free(channel_id);
3983 silc_free(client_id);
3984 silc_buffer_free(idp);
3987 silc_server_command_free(cmd);
3990 /* Server side of KICK command. Kicks client out of channel. */
3992 SILC_SERVER_CMD_FUNC(kick)
3994 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3995 SilcServer server = cmd->server;
3996 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3997 SilcClientEntry target_client;
3998 SilcChannelID *channel_id;
3999 SilcClientID *client_id;
4000 SilcChannelEntry channel;
4001 SilcChannelClientEntry chl;
4004 unsigned char *tmp, *comment;
4006 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 3);
4008 /* Get Channel ID */
4009 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4011 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4012 SILC_STATUS_ERR_NO_CHANNEL_ID);
4015 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
4017 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4018 SILC_STATUS_ERR_NO_CHANNEL_ID);
4022 /* Get channel entry */
4023 channel = silc_idlist_find_channel_by_id(server->local_list,
4026 channel = silc_idlist_find_channel_by_id(server->local_list,
4029 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4030 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4035 /* Check whether sender is on the channel */
4036 if (!silc_server_client_on_channel(client, channel)) {
4037 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4038 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4042 /* Check that the kicker is channel operator or channel founder */
4043 silc_list_start(channel->user_list);
4044 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
4045 if (chl->client == client) {
4046 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4047 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4048 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4055 /* Get target Client ID */
4056 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4058 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4059 SILC_STATUS_ERR_NO_CLIENT_ID);
4062 client_id = silc_id_payload_parse_id(tmp, tmp_len);
4064 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4065 SILC_STATUS_ERR_NO_CLIENT_ID);
4069 /* Get target client's entry */
4070 target_client = silc_idlist_find_client_by_id(server->local_list,
4072 if (!target_client) {
4073 target_client = silc_idlist_find_client_by_id(server->global_list,
4077 /* Check that the target client is not channel founder. Channel founder
4078 cannot be kicked from the channel. */
4079 silc_list_start(channel->user_list);
4080 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
4081 if (chl->client == target_client) {
4082 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4083 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4084 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4091 /* Check whether target client is on the channel */
4092 if (!silc_server_client_on_channel(target_client, channel)) {
4093 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4094 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4100 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4104 /* Send command reply to sender */
4105 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4108 /* Send KICKED notify to local clients on the channel */
4109 idp = silc_id_payload_encode(target_client->id, SILC_ID_CLIENT);
4110 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4111 SILC_NOTIFY_TYPE_KICKED,
4113 idp->data, idp->len,
4114 comment, comment ? strlen(comment) : 0);
4115 silc_buffer_free(idp);
4117 /* Remove the client from the channel. If the channel does not exist
4118 after removing the client then the client kicked itself off the channel
4119 and we don't have to send anything after that. */
4120 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4121 target_client, FALSE))
4124 /* Send KICKED notify to primary route */
4125 if (!server->standalone)
4126 silc_server_send_notify_kicked(server, server->router->connection,
4127 server->server_type == SILC_ROUTER ?
4128 TRUE : FALSE, channel,
4129 target_client->id, comment);
4131 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4132 /* Re-generate channel key */
4133 silc_server_create_channel_key(server, channel, 0);
4135 /* Send the channel key to the channel. The key of course is not sent
4136 to the client who was kicked off the channel. */
4137 silc_server_send_channel_key(server, target_client->connection, channel,
4138 server->server_type == SILC_ROUTER ?
4139 FALSE : !server->standalone);
4143 silc_server_command_free(cmd);
4146 /* Server side of OPER command. Client uses this comand to obtain server
4147 operator privileges to this server/router. */
4149 SILC_SERVER_CMD_FUNC(oper)
4151 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4152 SilcServer server = cmd->server;
4153 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4154 unsigned char *username, *auth;
4156 SilcServerConfigSectionAdminConnection *admin;
4157 SilcIDListData idata = (SilcIDListData)client;
4159 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_OPER, cmd, 1, 2);
4161 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4164 /* Get the username */
4165 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4167 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4168 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4172 /* Get the admin configuration */
4173 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4174 username, client->nickname);
4176 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4177 username, client->nickname);
4179 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4180 SILC_STATUS_ERR_AUTH_FAILED);
4185 /* Get the authentication payload */
4186 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4188 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4189 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4193 /* Verify the authentication data */
4194 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4195 admin->auth_data, admin->auth_data_len,
4196 idata->hash, client->id, SILC_ID_CLIENT)) {
4197 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4198 SILC_STATUS_ERR_AUTH_FAILED);
4202 /* Client is now server operator */
4203 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4205 /* Send UMODE change to primary router */
4206 if (!server->standalone)
4207 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4208 client->id, client->mode);
4210 /* Send reply to the sender */
4211 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4215 silc_server_command_free(cmd);
4218 /* Server side of SILCOPER command. Client uses this comand to obtain router
4219 operator privileges to this router. */
4221 SILC_SERVER_CMD_FUNC(silcoper)
4223 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4224 SilcServer server = cmd->server;
4225 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4226 unsigned char *username, *auth;
4228 SilcServerConfigSectionAdminConnection *admin;
4229 SilcIDListData idata = (SilcIDListData)client;
4231 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4233 if (server->server_type == SILC_SERVER)
4236 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4239 /* Get the username */
4240 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4242 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4243 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4247 /* Get the admin configuration */
4248 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4249 username, client->nickname);
4251 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4252 username, client->nickname);
4254 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4255 SILC_STATUS_ERR_AUTH_FAILED);
4260 /* Get the authentication payload */
4261 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4263 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4264 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4268 /* Verify the authentication data */
4269 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4270 admin->auth_data, admin->auth_data_len,
4271 idata->hash, client->id, SILC_ID_CLIENT)) {
4272 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4273 SILC_STATUS_ERR_AUTH_FAILED);
4277 /* Client is now router operator */
4278 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4280 /* Send UMODE change to primary router */
4281 if (!server->standalone)
4282 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4283 client->id, client->mode);
4285 /* Send reply to the sender */
4286 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4290 silc_server_command_free(cmd);
4293 /* Server side command of CONNECT. Connects us to the specified remote
4294 server or router. */
4296 SILC_SERVER_CMD_FUNC(connect)
4298 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4299 SilcServer server = cmd->server;
4300 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4301 unsigned char *tmp, *host;
4303 uint32 port = SILC_PORT;
4305 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CONNECT, cmd, 1, 2);
4307 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4310 /* Check whether client has the permissions. */
4311 if (client->mode == SILC_UMODE_NONE) {
4312 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4313 SILC_STATUS_ERR_NO_SERVER_PRIV);
4317 if (server->server_type == SILC_ROUTER &&
4318 client->mode & SILC_UMODE_SERVER_OPERATOR) {
4319 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4320 SILC_STATUS_ERR_NO_ROUTER_PRIV);
4324 /* Get the remote server */
4325 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4327 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4328 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4333 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4335 SILC_GET32_MSB(port, tmp);
4337 /* Create the connection. It is done with timeout and is async. */
4338 silc_server_create_connection(server, host, port);
4340 /* Send reply to the sender */
4341 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4345 silc_server_command_free(cmd);
4348 /* Server side of command BAN. This is used to manage the ban list of the
4349 channel. To add clients and remove clients from the ban list. */
4351 SILC_SERVER_CMD_FUNC(ban)
4353 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4354 SilcServer server = cmd->server;
4355 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4357 SilcChannelEntry channel;
4358 SilcChannelClientEntry chl;
4359 SilcChannelID *channel_id = NULL;
4360 unsigned char *id, *add, *del;
4361 uint32 id_len, tmp_len;
4362 uint16 ident = silc_command_get_ident(cmd->payload);
4364 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4367 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_BAN, cmd, 0, 3);
4369 /* Get Channel ID */
4370 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4372 channel_id = silc_id_payload_parse_id(id, id_len);
4374 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4375 SILC_STATUS_ERR_NO_CHANNEL_ID);
4380 /* Get channel entry. The server must know about the channel since the
4381 client is expected to be on the channel. */
4382 channel = silc_idlist_find_channel_by_id(server->local_list,
4385 channel = silc_idlist_find_channel_by_id(server->global_list,
4388 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4389 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4394 /* Check whether this client is on the channel */
4395 if (!silc_server_client_on_channel(client, channel)) {
4396 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4397 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4401 /* Get entry to the channel user list */
4402 silc_list_start(channel->user_list);
4403 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
4404 if (chl->client == client)
4407 /* The client must be at least channel operator. */
4408 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4409 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4410 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4414 /* Get the new ban and add it to the ban list */
4415 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4417 if (!channel->ban_list)
4418 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4420 channel->ban_list = silc_realloc(channel->ban_list,
4421 sizeof(*channel->ban_list) *
4423 strlen(channel->ban_list) + 2));
4424 if (add[tmp_len - 1] == ',')
4425 add[tmp_len - 1] = '\0';
4427 strncat(channel->ban_list, add, tmp_len);
4428 strncat(channel->ban_list, ",", 1);
4431 /* Get the ban to be removed and remove it from the list */
4432 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4433 if (del && channel->ban_list) {
4434 char *start, *end, *n;
4436 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4437 silc_free(channel->ban_list);
4438 channel->ban_list = NULL;
4440 start = strstr(channel->ban_list, del);
4441 if (start && strlen(start) >= tmp_len) {
4442 end = start + tmp_len;
4443 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4444 strncat(n, channel->ban_list, start - channel->ban_list);
4445 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4447 silc_free(channel->ban_list);
4448 channel->ban_list = n;
4453 /* Send the BAN notify type to our primary router. */
4454 if (!server->standalone && (add || del))
4455 silc_server_send_notify_ban(server, server->router->connection,
4456 server->server_type == SILC_ROUTER ?
4457 TRUE : FALSE, channel, add, del);
4459 /* Send the reply back to the client */
4460 if (channel->ban_list)
4462 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4463 SILC_STATUS_OK, ident, 2,
4465 3, channel->ban_list,
4466 strlen(channel->ban_list) - 1);
4469 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4470 SILC_STATUS_OK, ident, 1,
4473 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4474 packet->data, packet->len, FALSE);
4476 silc_buffer_free(packet);
4480 silc_free(channel_id);
4481 silc_server_command_free(cmd);
4484 /* Server side command of CLOSE. Closes connection to a specified server. */
4486 SILC_SERVER_CMD_FUNC(close)
4488 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4489 SilcServer server = cmd->server;
4490 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4491 SilcServerEntry server_entry;
4492 SilcSocketConnection sock;
4495 unsigned char *name;
4496 uint32 port = SILC_PORT;
4498 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CLOSE, cmd, 1, 2);
4500 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4503 /* Check whether client has the permissions. */
4504 if (client->mode == SILC_UMODE_NONE) {
4505 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4506 SILC_STATUS_ERR_NO_SERVER_PRIV);
4510 /* Get the remote server */
4511 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4513 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4514 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4519 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4521 SILC_GET32_MSB(port, tmp);
4523 server_entry = silc_idlist_find_server_by_conn(server->local_list,
4525 if (!server_entry) {
4526 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4527 SILC_STATUS_ERR_NO_SERVER_ID);
4531 /* Send reply to the sender */
4532 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4535 /* Close the connection to the server */
4536 sock = (SilcSocketConnection)server_entry->connection;
4537 silc_server_free_sock_user_data(server, sock);
4538 silc_server_close_connection(server, sock);
4541 silc_server_command_free(cmd);
4544 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4545 active connections. */
4547 SILC_SERVER_CMD_FUNC(shutdown)
4549 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4550 SilcServer server = cmd->server;
4551 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4553 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4555 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4558 /* Check whether client has the permission. */
4559 if (client->mode == SILC_UMODE_NONE) {
4560 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4561 SILC_STATUS_ERR_NO_SERVER_PRIV);
4565 /* Send reply to the sender */
4566 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4569 /* Then, gracefully, or not, bring the server down. */
4570 silc_server_stop(server);
4574 silc_server_command_free(cmd);
4577 /* Server side command of LEAVE. Removes client from a channel. */
4579 SILC_SERVER_CMD_FUNC(leave)
4581 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4582 SilcServer server = cmd->server;
4583 SilcSocketConnection sock = cmd->sock;
4584 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4585 SilcChannelID *id = NULL;
4586 SilcChannelEntry channel;
4590 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
4592 /* Get Channel ID */
4593 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4595 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4596 SILC_STATUS_ERR_NO_CHANNEL_ID);
4599 id = silc_id_payload_parse_id(tmp, len);
4601 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4602 SILC_STATUS_ERR_NO_CHANNEL_ID);
4606 /* Get channel entry */
4607 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4609 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4611 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4612 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4617 /* Check whether this client is on the channel */
4618 if (!silc_server_client_on_channel(id_entry, channel)) {
4619 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4620 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4624 /* Notify routers that they should remove this client from their list
4625 of clients on the channel. Send LEAVE notify type. */
4626 if (!server->standalone)
4627 silc_server_send_notify_leave(server, server->router->connection,
4628 server->server_type == SILC_ROUTER ?
4629 TRUE : FALSE, channel, id_entry->id);
4631 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4634 /* Remove client from channel */
4635 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4637 /* If the channel does not exist anymore we won't send anything */
4640 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4641 /* Re-generate channel key */
4642 silc_server_create_channel_key(server, channel, 0);
4644 /* Send the channel key */
4645 silc_server_send_channel_key(server, NULL, channel,
4646 server->server_type == SILC_ROUTER ?
4647 FALSE : !server->standalone);
4653 silc_server_command_free(cmd);
4656 /* Server side of command USERS. Resolves clients and their USERS currently
4657 joined on the requested channel. The list of Client ID's and their modes
4658 on the channel is sent back. */
4660 SILC_SERVER_CMD_FUNC(users)
4662 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4663 SilcServer server = cmd->server;
4664 SilcChannelEntry channel;
4667 unsigned char *channel_id;
4668 uint32 channel_id_len;
4669 SilcBuffer client_id_list;
4670 SilcBuffer client_mode_list;
4671 unsigned char lc[4];
4672 uint32 list_count = 0;
4673 uint16 ident = silc_command_get_ident(cmd->payload);
4675 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
4677 /* Get Channel ID */
4678 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4680 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4681 SILC_STATUS_ERR_NO_CHANNEL_ID);
4684 id = silc_id_payload_parse_id(channel_id, channel_id_len);
4686 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4687 SILC_STATUS_ERR_NO_CHANNEL_ID);
4691 /* If we are server and we don't know about this channel we will send
4692 the command to our router. If we know about the channel then we also
4693 have the list of users already. */
4694 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4696 if (server->server_type == SILC_SERVER && !server->standalone &&
4700 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
4701 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4703 /* Send USERS command */
4704 silc_server_packet_send(server, server->router->connection,
4705 SILC_PACKET_COMMAND, cmd->packet->flags,
4706 tmpbuf->data, tmpbuf->len, TRUE);
4708 /* Reprocess this packet after received reply */
4709 silc_server_command_pending(server, SILC_COMMAND_USERS,
4710 silc_command_get_ident(cmd->payload),
4711 silc_server_command_destructor,
4712 silc_server_command_users,
4713 silc_server_command_dup(cmd));
4714 cmd->pending = TRUE;
4715 silc_command_set_ident(cmd->payload, ident);
4717 silc_buffer_free(tmpbuf);
4722 /* We are router and we will check the global list as well. */
4723 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4725 /* Channel really does not exist */
4726 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4727 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4732 /* Get the users list */
4733 silc_server_get_users_on_channel(server, channel, &client_id_list,
4734 &client_mode_list, &list_count);
4737 SILC_PUT32_MSB(list_count, lc);
4740 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
4741 SILC_STATUS_OK, ident, 4,
4742 2, channel_id, channel_id_len,
4744 4, client_id_list->data,
4745 client_id_list->len,
4746 5, client_mode_list->data,
4747 client_mode_list->len);
4748 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4749 packet->data, packet->len, FALSE);
4751 silc_buffer_free(packet);
4752 silc_buffer_free(client_id_list);
4753 silc_buffer_free(client_mode_list);
4757 silc_server_command_free(cmd);
4760 /* Server side of command GETKEY. This fetches the client's public key
4761 from the server where to the client is connected. */
4763 SILC_SERVER_CMD_FUNC(getkey)
4765 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4766 SilcServer server = cmd->server;
4768 SilcClientEntry client;
4769 SilcServerEntry server_entry;
4770 SilcClientID *client_id = NULL;
4771 SilcServerID *server_id = NULL;
4772 SilcIDPayload idp = NULL;
4773 uint16 ident = silc_command_get_ident(cmd->payload);
4779 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4781 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4782 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4785 idp = silc_id_payload_parse_data(tmp, tmp_len);
4787 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4788 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4792 id_type = silc_id_payload_get_type(idp);
4793 if (id_type == SILC_ID_CLIENT) {
4794 client_id = silc_id_payload_get_id(idp);
4796 /* If the client is not found from local list there is no chance it
4797 would be locally connected client so send the command further. */
4798 client = silc_idlist_find_client_by_id(server->local_list,
4801 if ((!client && !cmd->pending && !server->standalone) ||
4802 (client && !client->connection)) {
4805 SilcSocketConnection dest_sock;
4807 dest_sock = silc_server_get_client_route(server, NULL, 0,
4812 old_ident = silc_command_get_ident(cmd->payload);
4813 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
4814 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4816 silc_server_packet_send(server, dest_sock,
4817 SILC_PACKET_COMMAND, cmd->packet->flags,
4818 tmpbuf->data, tmpbuf->len, TRUE);
4820 /* Reprocess this packet after received reply from router */
4821 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
4822 silc_command_get_ident(cmd->payload),
4823 silc_server_command_destructor,
4824 silc_server_command_getkey,
4825 silc_server_command_dup(cmd));
4826 cmd->pending = TRUE;
4828 silc_command_set_ident(cmd->payload, old_ident);
4829 silc_buffer_free(tmpbuf);
4833 if (!client && cmd->pending) {
4834 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4835 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
4839 /* The client is locally connected, just get the public key and
4841 tmp = silc_pkcs_public_key_encode(client->data.public_key, &tmp_len);
4842 pk = silc_buffer_alloc(4 + tmp_len);
4843 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
4844 silc_buffer_format(pk,
4845 SILC_STR_UI_SHORT(tmp_len),
4846 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
4847 SILC_STR_UI_XNSTRING(tmp, tmp_len),
4851 } else if (id_type == SILC_ID_SERVER) {
4852 server_id = silc_id_payload_get_id(idp);
4854 /* If the server is not found from local list there is no chance it
4855 would be locally connected server so send the command further. */
4856 server_entry = silc_idlist_find_server_by_id(server->local_list,
4859 if ((!server_entry && !cmd->pending && !server->standalone) ||
4860 (server_entry && !server_entry->connection)) {
4864 old_ident = silc_command_get_ident(cmd->payload);
4865 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
4866 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4868 silc_server_packet_send(server, server->router->connection,
4869 SILC_PACKET_COMMAND, cmd->packet->flags,
4870 tmpbuf->data, tmpbuf->len, TRUE);
4872 /* Reprocess this packet after received reply from router */
4873 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
4874 silc_command_get_ident(cmd->payload),
4875 silc_server_command_destructor,
4876 silc_server_command_getkey,
4877 silc_server_command_dup(cmd));
4878 cmd->pending = TRUE;
4880 silc_command_set_ident(cmd->payload, old_ident);
4881 silc_buffer_free(tmpbuf);
4885 if (!server_entry && cmd->pending) {
4886 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4887 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
4891 /* The client is locally connected, just get the public key and
4893 tmp = silc_pkcs_public_key_encode(server_entry->data.public_key, &tmp_len);
4894 pk = silc_buffer_alloc(4 + tmp_len);
4895 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
4896 silc_buffer_format(pk,
4897 SILC_STR_UI_SHORT(tmp_len),
4898 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
4899 SILC_STR_UI_XNSTRING(tmp, tmp_len),
4906 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4907 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
4908 SILC_STATUS_OK, ident, 2,
4910 3, pk->data, pk->len);
4911 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4912 packet->data, packet->len, FALSE);
4913 silc_buffer_free(packet);
4914 silc_buffer_free(pk);
4918 silc_id_payload_free(idp);
4919 silc_free(client_id);
4920 silc_free(server_id);
4921 silc_server_command_free(cmd);