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 if (entry->nickname) {
559 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
560 SILC_STATUS_ERR_NO_SUCH_NICK,
562 strlen(entry->nickname));
564 SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
565 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
566 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
567 2, idp->data, idp->len);
568 silc_buffer_free(idp);
575 status = SILC_STATUS_LIST_ITEM;
577 if (clients_count > 1 && k == clients_count - 1)
578 status = SILC_STATUS_LIST_END;
580 if (count && k - 1 == count)
581 status = SILC_STATUS_LIST_END;
583 if (count && k - 1 > count)
586 /* Sanity check, however these should never fail. However, as
587 this sanity check has been added here they have failed. */
588 if (!entry->nickname || !entry->username || !entry->userinfo)
591 /* Send WHOIS reply */
592 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
593 tmp = silc_argument_get_first_arg(cmd->args, NULL);
595 memset(uh, 0, sizeof(uh));
596 memset(nh, 0, sizeof(nh));
597 memset(idle, 0, sizeof(idle));
599 strncat(nh, entry->nickname, strlen(entry->nickname));
600 if (!strchr(entry->nickname, '@')) {
602 if (entry->servername) {
603 strncat(nh, entry->servername, strlen(entry->servername));
605 len = entry->router ? strlen(entry->router->server_name) :
606 strlen(server->server_name);
607 strncat(nh, entry->router ? entry->router->server_name :
608 server->server_name, len);
612 strncat(uh, entry->username, strlen(entry->username));
613 if (!strchr(entry->username, '@')) {
615 hsock = (SilcSocketConnection)entry->connection;
616 len = strlen(hsock->hostname);
617 strncat(uh, hsock->hostname, len);
620 channels = silc_server_get_client_channel_list(server, entry);
622 SILC_PUT32_MSB(entry->mode, mode);
624 if (entry->connection) {
625 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
629 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
631 2, idp->data, idp->len,
635 strlen(entry->userinfo),
641 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
643 2, idp->data, idp->len,
647 strlen(entry->userinfo),
651 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
652 0, packet->data, packet->len, FALSE);
654 silc_buffer_free(packet);
655 silc_buffer_free(idp);
657 silc_buffer_free(channels);
664 silc_server_command_whois_from_client(SilcServerCommandContext cmd)
666 SilcServer server = cmd->server;
667 char *nick = NULL, *server_name = NULL;
669 SilcClientEntry *clients = NULL, entry;
670 SilcClientID **client_id = NULL;
671 uint32 client_id_count = 0, clients_count = 0;
674 /* Protocol dictates that we must always send the received WHOIS request
675 to our router if we are normal server, so let's do it now unless we
676 are standalone. We will not send any replies to the client until we
677 have received reply from the router. */
678 if (server->server_type == SILC_SERVER && !cmd->pending &&
679 !server->standalone) {
683 old_ident = silc_command_get_ident(cmd->payload);
684 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
685 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
687 /* Send WHOIS command to our router */
688 silc_server_packet_send(server, (SilcSocketConnection)
689 server->router->connection,
690 SILC_PACKET_COMMAND, cmd->packet->flags,
691 tmpbuf->data, tmpbuf->len, TRUE);
693 /* Reprocess this packet after received reply from router */
694 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
695 silc_command_get_ident(cmd->payload),
696 silc_server_command_destructor,
697 silc_server_command_whois,
698 silc_server_command_dup(cmd));
701 silc_command_set_ident(cmd->payload, old_ident);
703 silc_buffer_free(tmpbuf);
708 /* We are ready to process the command request. Let's search for the
709 requested client and send reply to the requesting client. */
711 /* Parse the whois request */
712 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
713 &nick, &server_name, &count,
717 /* Get all clients matching that ID or nickname from local list */
718 if (client_id_count) {
719 /* Check all Client ID's received in the command packet */
720 for (i = 0; i < client_id_count; i++) {
721 entry = silc_idlist_find_client_by_id(server->local_list,
724 clients = silc_realloc(clients, sizeof(*clients) *
725 (clients_count + 1));
726 clients[clients_count++] = entry;
730 if (!silc_idlist_get_clients_by_hash(server->local_list,
731 nick, server->md5hash,
732 &clients, &clients_count))
733 silc_idlist_get_clients_by_nickname(server->local_list,
735 &clients, &clients_count);
738 /* Check global list as well */
739 if (client_id_count) {
740 /* Check all Client ID's received in the command packet */
741 for (i = 0; i < client_id_count; i++) {
742 entry = silc_idlist_find_client_by_id(server->global_list,
745 clients = silc_realloc(clients, sizeof(*clients) *
746 (clients_count + 1));
747 clients[clients_count++] = entry;
751 if (!silc_idlist_get_clients_by_hash(server->global_list,
752 nick, server->md5hash,
753 &clients, &clients_count))
754 silc_idlist_get_clients_by_nickname(server->global_list,
756 &clients, &clients_count);
760 /* Such client(s) really does not exist in the SILC network. */
761 if (!client_id_count) {
762 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
763 SILC_STATUS_ERR_NO_SUCH_NICK,
764 3, nick, strlen(nick));
766 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
767 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
768 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
769 2, idp->data, idp->len);
770 silc_buffer_free(idp);
775 /* Router always finds the client entry if it exists in the SILC network.
776 However, it might be incomplete entry and does not include all the
777 mandatory fields that WHOIS command reply requires. Check for these and
778 make query from the server who owns the client if some fields are
780 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
785 /* Send the command reply to the client */
786 silc_server_command_whois_send_reply(cmd, clients, clients_count,
790 if (client_id_count) {
791 for (i = 0; i < client_id_count; i++)
792 silc_free(client_id[i]);
793 silc_free(client_id);
800 silc_free(server_name);
806 silc_server_command_whois_from_server(SilcServerCommandContext cmd)
808 SilcServer server = cmd->server;
809 char *nick = NULL, *server_name = NULL;
811 SilcClientEntry *clients = NULL, entry;
812 SilcClientID **client_id = NULL;
813 uint32 client_id_count = 0, clients_count = 0;
816 /* Parse the whois request */
817 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
818 &nick, &server_name, &count,
822 /* Process the command request. Let's search for the requested client and
823 send reply to the requesting server. */
825 if (client_id_count) {
826 /* Check all Client ID's received in the command packet */
827 for (i = 0; i < client_id_count; i++) {
828 entry = silc_idlist_find_client_by_id(server->local_list,
831 clients = silc_realloc(clients, sizeof(*clients) *
832 (clients_count + 1));
833 clients[clients_count++] = entry;
837 if (!silc_idlist_get_clients_by_hash(server->local_list,
838 nick, server->md5hash,
839 &clients, &clients_count))
840 silc_idlist_get_clients_by_nickname(server->local_list,
842 &clients, &clients_count);
845 /* If we are router we will check our global list as well. */
846 if (server->server_type == SILC_ROUTER) {
847 if (client_id_count) {
848 /* Check all Client ID's received in the command packet */
849 for (i = 0; i < client_id_count; i++) {
850 entry = silc_idlist_find_client_by_id(server->global_list,
853 clients = silc_realloc(clients, sizeof(*clients) *
854 (clients_count + 1));
855 clients[clients_count++] = entry;
859 if (!silc_idlist_get_clients_by_hash(server->global_list,
860 nick, server->md5hash,
861 &clients, &clients_count))
862 silc_idlist_get_clients_by_nickname(server->global_list,
864 &clients, &clients_count);
869 /* Such a client really does not exist in the SILC network. */
870 if (!client_id_count) {
871 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
872 SILC_STATUS_ERR_NO_SUCH_NICK,
873 3, nick, strlen(nick));
875 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
876 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
877 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
878 2, idp->data, idp->len);
879 silc_buffer_free(idp);
884 /* Router always finds the client entry if it exists in the SILC network.
885 However, it might be incomplete entry and does not include all the
886 mandatory fields that WHOIS command reply requires. Check for these and
887 make query from the server who owns the client if some fields are
889 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
894 /* Send the command reply to the client */
895 silc_server_command_whois_send_reply(cmd, clients, clients_count,
899 if (client_id_count) {
900 for (i = 0; i < client_id_count; i++)
901 silc_free(client_id[i]);
902 silc_free(client_id);
909 silc_free(server_name);
914 /* Server side of command WHOIS. Processes user's query and sends found
915 results as command replies back to the client. */
917 SILC_SERVER_CMD_FUNC(whois)
919 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
922 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOIS, cmd, 1, 3328);
924 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
925 ret = silc_server_command_whois_from_client(cmd);
926 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
927 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
928 ret = silc_server_command_whois_from_server(cmd);
931 silc_server_command_free(cmd);
934 /******************************************************************************
938 ******************************************************************************/
941 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
949 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
951 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
952 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
956 /* Get the nickname@server string and parse it. */
957 if (strchr(tmp, '@')) {
958 len = strcspn(tmp, "@");
959 *nickname = silc_calloc(len + 1, sizeof(char));
960 memcpy(*nickname, tmp, len);
961 *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
962 memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
964 *nickname = strdup(tmp);
966 /* Get the max count of reply messages allowed */
967 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
977 silc_server_command_whowas_check(SilcServerCommandContext cmd,
978 SilcClientEntry *clients,
979 uint32 clients_count)
981 SilcServer server = cmd->server;
983 SilcClientEntry entry;
985 for (i = 0; i < clients_count; i++) {
988 if (!entry->nickname || !entry->username) {
995 old_ident = silc_command_get_ident(cmd->payload);
996 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
997 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
999 /* Send WHOWAS command */
1000 silc_server_packet_send(server, entry->router->connection,
1001 SILC_PACKET_COMMAND, cmd->packet->flags,
1002 tmpbuf->data, tmpbuf->len, TRUE);
1004 /* Reprocess this packet after received reply */
1005 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1006 silc_command_get_ident(cmd->payload),
1007 silc_server_command_destructor,
1008 silc_server_command_whowas,
1009 silc_server_command_dup(cmd));
1010 cmd->pending = TRUE;
1012 silc_command_set_ident(cmd->payload, old_ident);
1014 silc_buffer_free(tmpbuf);
1023 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1024 SilcClientEntry *clients,
1025 uint32 clients_count)
1027 SilcServer server = cmd->server;
1029 int i, count = 0, len;
1030 SilcBuffer packet, idp;
1031 SilcClientEntry entry = NULL;
1032 SilcCommandStatus status;
1033 uint16 ident = silc_command_get_ident(cmd->payload);
1035 char nh[256], uh[256];
1037 status = SILC_STATUS_OK;
1038 if (clients_count > 1)
1039 status = SILC_STATUS_LIST_START;
1041 for (i = 0; i < clients_count; i++) {
1044 /* We will take only clients that are not valid anymore. They are the
1045 ones that are not registered anymore but still have a ID. They
1046 have disconnected us, and thus valid for WHOWAS. */
1047 if (entry->data.registered == TRUE)
1049 if (entry->id == NULL)
1052 if (count && i - 1 == count)
1057 if (clients_count > 2)
1058 status = SILC_STATUS_LIST_ITEM;
1060 if (clients_count > 1 && i == clients_count - 1)
1061 status = SILC_STATUS_LIST_END;
1063 /* Sanity check, however these should never fail. However, as
1064 this sanity check has been added here they have failed. */
1065 if (!entry->nickname || !entry->username)
1068 /* Send WHOWAS reply */
1069 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1070 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1072 memset(uh, 0, sizeof(uh));
1073 memset(nh, 0, sizeof(nh));
1075 strncat(nh, entry->nickname, strlen(entry->nickname));
1076 if (!strchr(entry->nickname, '@')) {
1077 strncat(nh, "@", 1);
1078 if (entry->servername) {
1079 strncat(nh, entry->servername, strlen(entry->servername));
1081 len = entry->router ? strlen(entry->router->server_name) :
1082 strlen(server->server_name);
1083 strncat(nh, entry->router ? entry->router->server_name :
1084 server->server_name, len);
1088 strncat(uh, entry->username, strlen(entry->username));
1089 if (!strchr(entry->username, '@')) {
1090 strncat(uh, "@", 1);
1091 strcat(uh, "*private*");
1094 if (entry->userinfo)
1096 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1098 2, idp->data, idp->len,
1102 strlen(entry->userinfo));
1105 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1107 2, idp->data, idp->len,
1111 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1112 0, packet->data, packet->len, FALSE);
1114 silc_buffer_free(packet);
1115 silc_buffer_free(idp);
1118 if (found == FALSE && entry)
1119 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1120 SILC_STATUS_ERR_NO_SUCH_NICK,
1122 strlen(entry->nickname));
1126 silc_server_command_whowas_from_client(SilcServerCommandContext cmd)
1128 SilcServer server = cmd->server;
1129 char *nick = NULL, *server_name = NULL;
1131 SilcClientEntry *clients = NULL;
1132 uint32 clients_count = 0;
1135 /* Protocol dictates that we must always send the received WHOWAS request
1136 to our router if we are normal server, so let's do it now unless we
1137 are standalone. We will not send any replies to the client until we
1138 have received reply from the router. */
1139 if (server->server_type == SILC_SERVER &&
1140 !cmd->pending && !server->standalone) {
1144 old_ident = silc_command_get_ident(cmd->payload);
1145 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1146 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1148 /* Send WHOWAS command to our router */
1149 silc_server_packet_send(server, (SilcSocketConnection)
1150 server->router->connection,
1151 SILC_PACKET_COMMAND, cmd->packet->flags,
1152 tmpbuf->data, tmpbuf->len, TRUE);
1154 /* Reprocess this packet after received reply from router */
1155 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1156 silc_command_get_ident(cmd->payload),
1157 silc_server_command_destructor,
1158 silc_server_command_whowas,
1159 silc_server_command_dup(cmd));
1160 cmd->pending = TRUE;
1162 silc_command_set_ident(cmd->payload, old_ident);
1164 silc_buffer_free(tmpbuf);
1169 /* We are ready to process the command request. Let's search for the
1170 requested client and send reply to the requesting client. */
1172 /* Parse the whowas request */
1173 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1176 /* Get all clients matching that nickname from local list */
1177 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1179 &clients, &clients_count))
1180 silc_idlist_get_clients_by_hash(server->local_list,
1181 nick, server->md5hash,
1182 &clients, &clients_count);
1184 /* Check global list as well */
1185 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1187 &clients, &clients_count))
1188 silc_idlist_get_clients_by_hash(server->global_list,
1189 nick, server->md5hash,
1190 &clients, &clients_count);
1192 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1197 /* Send the command reply to the client */
1198 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1206 silc_free(server_name);
1212 silc_server_command_whowas_from_server(SilcServerCommandContext cmd)
1214 SilcServer server = cmd->server;
1215 char *nick = NULL, *server_name = NULL;
1217 SilcClientEntry *clients = NULL;
1218 uint32 clients_count = 0;
1221 /* Parse the whowas request */
1222 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1225 /* Process the command request. Let's search for the requested client and
1226 send reply to the requesting server. */
1228 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1230 &clients, &clients_count))
1231 silc_idlist_get_clients_by_hash(server->local_list,
1232 nick, server->md5hash,
1233 &clients, &clients_count);
1235 /* If we are router we will check our global list as well. */
1236 if (server->server_type == SILC_ROUTER) {
1237 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1239 &clients, &clients_count))
1240 silc_idlist_get_clients_by_hash(server->global_list,
1241 nick, server->md5hash,
1242 &clients, &clients_count);
1246 /* Such a client really does not exist in the SILC network. */
1247 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1248 SILC_STATUS_ERR_NO_SUCH_NICK,
1249 3, nick, strlen(nick));
1253 /* Send the command reply to the client */
1254 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1262 silc_free(server_name);
1267 /* Server side of command WHOWAS. */
1269 SILC_SERVER_CMD_FUNC(whowas)
1271 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1274 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1276 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1277 ret = silc_server_command_whowas_from_client(cmd);
1278 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
1279 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1280 ret = silc_server_command_whowas_from_server(cmd);
1283 silc_server_command_free(cmd);
1286 /******************************************************************************
1290 ******************************************************************************/
1292 /* Checks that all mandatory fields are present. If not then send WHOIS
1293 request to the server who owns the client. We use WHOIS because we want
1294 to get as much information as possible at once. */
1297 silc_server_command_identify_check(SilcServerCommandContext cmd,
1298 SilcClientEntry *clients,
1299 uint32 clients_count)
1301 SilcServer server = cmd->server;
1303 SilcClientEntry entry;
1305 for (i = 0; i < clients_count; i++) {
1308 if (!entry || entry->data.registered == FALSE)
1311 if (!entry->nickname) {
1318 old_ident = silc_command_get_ident(cmd->payload);
1319 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1320 silc_command_set_command(cmd->payload, SILC_COMMAND_WHOIS);
1321 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1323 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1324 now anyway so make it a good one. */
1325 silc_server_packet_send(server, entry->router->connection,
1326 SILC_PACKET_COMMAND, cmd->packet->flags,
1327 tmpbuf->data, tmpbuf->len, TRUE);
1329 /* Reprocess this packet after received reply */
1330 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1331 silc_command_get_ident(cmd->payload),
1332 silc_server_command_destructor,
1333 silc_server_command_identify,
1334 silc_server_command_dup(cmd));
1336 cmd->pending = TRUE;
1338 /* Put old data back to the Command Payload we just changed */
1339 silc_command_set_ident(cmd->payload, old_ident);
1340 silc_command_set_command(cmd->payload, SILC_COMMAND_IDENTIFY);
1342 silc_buffer_free(tmpbuf);
1351 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1352 SilcClientEntry *clients,
1353 uint32 clients_count,
1356 SilcServer server = cmd->server;
1359 SilcBuffer packet, idp;
1360 SilcClientEntry entry;
1361 SilcCommandStatus status;
1362 uint16 ident = silc_command_get_ident(cmd->payload);
1363 char nh[256], uh[256];
1364 SilcSocketConnection hsock;
1367 for (i = 0; i < clients_count; i++)
1368 if (clients[i]->data.registered)
1371 status = SILC_STATUS_OK;
1373 status = SILC_STATUS_LIST_START;
1375 for (i = 0, k = 0; i < clients_count; i++) {
1378 if (entry->data.registered == FALSE) {
1379 if (clients_count == 1) {
1380 SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1381 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1382 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1383 2, idp->data, idp->len);
1384 silc_buffer_free(idp);
1390 status = SILC_STATUS_LIST_ITEM;
1392 if (clients_count > 1 && k == clients_count - 1)
1393 status = SILC_STATUS_LIST_END;
1395 if (count && k - 1 == count)
1396 status = SILC_STATUS_LIST_END;
1398 if (count && k - 1 > count)
1401 /* Send IDENTIFY reply */
1402 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1403 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1405 memset(uh, 0, sizeof(uh));
1406 memset(nh, 0, sizeof(nh));
1408 strncat(nh, entry->nickname, strlen(entry->nickname));
1409 if (!strchr(entry->nickname, '@')) {
1410 strncat(nh, "@", 1);
1411 if (entry->servername) {
1412 strncat(nh, entry->servername, strlen(entry->servername));
1414 len = entry->router ? strlen(entry->router->server_name) :
1415 strlen(server->server_name);
1416 strncat(nh, entry->router ? entry->router->server_name :
1417 server->server_name, len);
1421 if (!entry->username) {
1422 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1424 2, idp->data, idp->len,
1427 strncat(uh, entry->username, strlen(entry->username));
1428 if (!strchr(entry->username, '@')) {
1429 strncat(uh, "@", 1);
1430 hsock = (SilcSocketConnection)entry->connection;
1431 len = strlen(hsock->hostname);
1432 strncat(uh, hsock->hostname, len);
1435 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1437 2, idp->data, idp->len,
1442 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1443 0, packet->data, packet->len, FALSE);
1445 silc_buffer_free(packet);
1446 silc_buffer_free(idp);
1453 silc_server_command_identify_from_client(SilcServerCommandContext cmd)
1455 SilcServer server = cmd->server;
1456 char *nick = NULL, *server_name = NULL;
1458 SilcClientEntry *clients = NULL, entry;
1459 SilcClientID **client_id = NULL;
1460 uint32 client_id_count = 0, clients_count = 0;
1463 /* Protocol dictates that we must always send the received IDENTIFY request
1464 to our router if we are normal server, so let's do it now unless we
1465 are standalone. We will not send any replies to the client until we
1466 have received reply from the router. */
1467 if (server->server_type == SILC_SERVER &&
1468 !cmd->pending && !server->standalone) {
1472 old_ident = silc_command_get_ident(cmd->payload);
1473 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1474 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1476 /* Send IDENTIFY command to our router */
1477 silc_server_packet_send(server, (SilcSocketConnection)
1478 server->router->connection,
1479 SILC_PACKET_COMMAND, cmd->packet->flags,
1480 tmpbuf->data, tmpbuf->len, TRUE);
1482 /* Reprocess this packet after received reply from router */
1483 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1484 silc_command_get_ident(cmd->payload),
1485 silc_server_command_destructor,
1486 silc_server_command_identify,
1487 silc_server_command_dup(cmd));
1488 cmd->pending = TRUE;
1490 silc_command_set_ident(cmd->payload, old_ident);
1492 silc_buffer_free(tmpbuf);
1497 /* We are ready to process the command request. Let's search for the
1498 requested client and send reply to the requesting client. */
1500 /* Parse the IDENTIFY request */
1501 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1502 &nick, &server_name, &count,
1503 SILC_COMMAND_IDENTIFY))
1506 /* Get all clients matching that ID or nickname from local list */
1507 if (client_id_count) {
1508 /* Check all Client ID's received in the command packet */
1509 for (i = 0; i < client_id_count; i++) {
1510 entry = silc_idlist_find_client_by_id(server->local_list,
1511 client_id[i], NULL);
1513 clients = silc_realloc(clients, sizeof(*clients) *
1514 (clients_count + 1));
1515 clients[clients_count++] = entry;
1519 if (!silc_idlist_get_clients_by_hash(server->local_list,
1520 nick, server->md5hash,
1521 &clients, &clients_count))
1522 silc_idlist_get_clients_by_nickname(server->local_list,
1524 &clients, &clients_count);
1527 /* Check global list as well */
1528 if (client_id_count) {
1529 /* Check all Client ID's received in the command packet */
1530 for (i = 0; i < client_id_count; i++) {
1531 entry = silc_idlist_find_client_by_id(server->global_list,
1532 client_id[i], NULL);
1534 clients = silc_realloc(clients, sizeof(*clients) *
1535 (clients_count + 1));
1536 clients[clients_count++] = entry;
1540 if (!silc_idlist_get_clients_by_hash(server->global_list,
1541 nick, server->md5hash,
1542 &clients, &clients_count))
1543 silc_idlist_get_clients_by_nickname(server->global_list,
1545 &clients, &clients_count);
1549 /* Such a client really does not exist in the SILC network. */
1550 if (!client_id_count) {
1551 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1552 SILC_STATUS_ERR_NO_SUCH_NICK,
1553 3, nick, strlen(nick));
1555 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1556 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1557 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1558 2, idp->data, idp->len);
1559 silc_buffer_free(idp);
1564 /* Check that all mandatory fields are present and request those data
1565 from the server who owns the client if necessary. */
1566 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1571 /* Send the command reply to the client */
1572 silc_server_command_identify_send_reply(cmd, clients, clients_count,
1576 if (client_id_count) {
1577 for (i = 0; i < client_id_count; i++)
1578 silc_free(client_id[i]);
1579 silc_free(client_id);
1586 silc_free(server_name);
1592 silc_server_command_identify_from_server(SilcServerCommandContext cmd)
1594 SilcServer server = cmd->server;
1595 char *nick = NULL, *server_name = NULL;
1597 SilcClientEntry *clients = NULL, entry;
1598 SilcClientID **client_id = NULL;
1599 uint32 client_id_count = 0, clients_count = 0;
1602 /* Parse the IDENTIFY request */
1603 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1604 &nick, &server_name, &count,
1605 SILC_COMMAND_IDENTIFY))
1608 /* Process the command request. Let's search for the requested client and
1609 send reply to the requesting server. */
1611 if (client_id_count) {
1612 /* Check all Client ID's received in the command packet */
1613 for (i = 0; i < client_id_count; i++) {
1614 entry = silc_idlist_find_client_by_id(server->local_list,
1615 client_id[i], NULL);
1617 clients = silc_realloc(clients, sizeof(*clients) *
1618 (clients_count + 1));
1619 clients[clients_count++] = entry;
1623 if (!silc_idlist_get_clients_by_hash(server->local_list,
1624 nick, server->md5hash,
1625 &clients, &clients_count))
1626 silc_idlist_get_clients_by_nickname(server->local_list,
1628 &clients, &clients_count);
1631 /* If we are router we will check our global list as well. */
1632 if (server->server_type == SILC_ROUTER) {
1633 if (client_id_count) {
1634 /* Check all Client ID's received in the command packet */
1635 for (i = 0; i < client_id_count; i++) {
1636 entry = silc_idlist_find_client_by_id(server->global_list,
1637 client_id[i], NULL);
1639 clients = silc_realloc(clients, sizeof(*clients) *
1640 (clients_count + 1));
1641 clients[clients_count++] = entry;
1645 if (!silc_idlist_get_clients_by_hash(server->global_list,
1646 nick, server->md5hash,
1647 &clients, &clients_count))
1648 silc_idlist_get_clients_by_nickname(server->global_list,
1650 &clients, &clients_count);
1655 /* Such a client really does not exist in the SILC network. */
1656 if (!client_id_count) {
1657 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1658 SILC_STATUS_ERR_NO_SUCH_NICK,
1659 3, nick, strlen(nick));
1661 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1662 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1663 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1664 2, idp->data, idp->len);
1665 silc_buffer_free(idp);
1670 /* Check that all mandatory fields are present and request those data
1671 from the server who owns the client if necessary. */
1672 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1677 /* Send the command reply */
1678 silc_server_command_identify_send_reply(cmd, clients, clients_count, count);
1681 if (client_id_count) {
1682 for (i = 0; i < client_id_count; i++)
1683 silc_free(client_id[i]);
1684 silc_free(client_id);
1691 silc_free(server_name);
1696 SILC_SERVER_CMD_FUNC(identify)
1698 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1701 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1703 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1704 ret = silc_server_command_identify_from_client(cmd);
1705 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) |
1706 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1707 ret = silc_server_command_identify_from_server(cmd);
1710 silc_server_command_free(cmd);
1713 /* Checks string for bad characters and returns TRUE if they are found. */
1715 static int silc_server_command_bad_chars(char *nick)
1717 if (strchr(nick, '\\')) return TRUE;
1718 if (strchr(nick, '\"')) return TRUE;
1719 if (strchr(nick, '´')) return TRUE;
1720 if (strchr(nick, '`')) return TRUE;
1721 if (strchr(nick, '\'')) return TRUE;
1722 if (strchr(nick, '*')) return TRUE;
1723 if (strchr(nick, '/')) return TRUE;
1724 if (strchr(nick, '@')) return TRUE;
1729 /* Server side of command NICK. Sets nickname for user. Setting
1730 nickname causes generation of a new client ID for the client. The
1731 new client ID is sent to the client after changing the nickname. */
1733 SILC_SERVER_CMD_FUNC(nick)
1735 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1736 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1737 SilcServer server = cmd->server;
1738 SilcBuffer packet, nidp, oidp;
1739 SilcClientID *new_id;
1741 uint16 ident = silc_command_get_ident(cmd->payload);
1743 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1746 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NICK, cmd, 1, 1);
1748 /* Check nickname */
1749 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1750 if (silc_server_command_bad_chars(nick) == TRUE) {
1751 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1752 SILC_STATUS_ERR_BAD_NICKNAME);
1756 if (strlen(nick) > 128)
1759 /* Create new Client ID */
1760 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
1761 cmd->server->md5hash, nick,
1764 /* Send notify about nickname change to our router. We send the new
1765 ID and ask to replace it with the old one. If we are router the
1766 packet is broadcasted. Send NICK_CHANGE notify. */
1767 if (!server->standalone)
1768 silc_server_send_notify_nick_change(server, server->router->connection,
1769 server->server_type == SILC_SERVER ?
1770 FALSE : TRUE, client->id,
1773 /* Remove old cache entry */
1774 silc_idcache_del_by_context(server->local_list->clients, client);
1776 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1780 silc_free(client->id);
1782 /* Save the nickname as this client is our local client */
1783 if (client->nickname)
1784 silc_free(client->nickname);
1786 client->nickname = strdup(nick);
1787 client->id = new_id;
1789 /* Update client cache */
1790 silc_idcache_add(server->local_list->clients, client->nickname,
1791 client->id, (void *)client, FALSE);
1793 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1795 /* Send NICK_CHANGE notify to the client's channels */
1796 silc_server_send_notify_on_channels(server, NULL, client,
1797 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1798 oidp->data, oidp->len,
1799 nidp->data, nidp->len);
1801 /* Send the new Client ID as reply command back to client */
1802 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
1803 SILC_STATUS_OK, ident, 1,
1804 2, nidp->data, nidp->len);
1805 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1806 0, packet->data, packet->len, FALSE);
1808 silc_buffer_free(packet);
1809 silc_buffer_free(nidp);
1810 silc_buffer_free(oidp);
1813 silc_server_command_free(cmd);
1816 /* Sends the LIST command reply */
1819 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
1820 SilcChannelEntry *lch,
1822 SilcChannelEntry *gch,
1826 SilcBuffer packet, idp;
1827 SilcChannelEntry entry;
1828 SilcCommandStatus status;
1829 uint16 ident = silc_command_get_ident(cmd->payload);
1831 unsigned char usercount[4];
1834 for (i = 0; i < lch_count; i++)
1835 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
1837 for (i = 0; i < gch_count; i++)
1838 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
1841 status = SILC_STATUS_OK;
1842 if ((lch_count + gch_count) > 1)
1843 status = SILC_STATUS_LIST_START;
1846 for (i = 0; i < lch_count; i++) {
1853 status = SILC_STATUS_LIST_ITEM;
1855 if (i == lch_count - 1 && gch_count)
1857 if (lch_count > 1 && i == lch_count - 1)
1858 status = SILC_STATUS_LIST_END;
1860 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1862 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
1863 topic = "*private*";
1864 memset(usercount, 0, sizeof(usercount));
1866 topic = entry->topic;
1867 users = silc_list_count(entry->user_list);
1868 SILC_PUT32_MSB(users, usercount);
1871 /* Send the reply */
1874 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1876 2, idp->data, idp->len,
1877 3, entry->channel_name,
1878 strlen(entry->channel_name),
1879 4, topic, strlen(topic),
1883 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1885 2, idp->data, idp->len,
1886 3, entry->channel_name,
1887 strlen(entry->channel_name),
1889 silc_server_packet_send(cmd->server, cmd->sock,
1890 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
1891 packet->len, FALSE);
1892 silc_buffer_free(packet);
1893 silc_buffer_free(idp);
1896 status = i ? SILC_STATUS_LIST_ITEM : SILC_STATUS_OK;
1899 for (i = 0; i < gch_count; i++) {
1906 status = SILC_STATUS_LIST_ITEM;
1908 if (gch_count > 1 && i == lch_count - 1)
1909 status = SILC_STATUS_LIST_END;
1911 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1913 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
1914 topic = "*private*";
1915 memset(usercount, 0, sizeof(usercount));
1917 topic = entry->topic;
1918 users = silc_list_count(entry->user_list);
1919 SILC_PUT32_MSB(users, usercount);
1922 /* Send the reply */
1925 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1927 2, idp->data, idp->len,
1928 3, entry->channel_name,
1929 strlen(entry->channel_name),
1930 4, topic, strlen(topic),
1934 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1936 2, idp->data, idp->len,
1937 3, entry->channel_name,
1938 strlen(entry->channel_name),
1940 silc_server_packet_send(cmd->server, cmd->sock,
1941 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
1942 packet->len, FALSE);
1943 silc_buffer_free(packet);
1944 silc_buffer_free(idp);
1948 /* Server side of LIST command. This lists the channel of the requested
1949 server. Secret channels are not listed. */
1951 SILC_SERVER_CMD_FUNC(list)
1953 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1954 SilcServer server = cmd->server;
1955 SilcChannelID *channel_id = NULL;
1958 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
1959 uint32 lch_count = 0, gch_count = 0;
1961 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LIST, cmd, 0, 2);
1963 /* Get Channel ID */
1964 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1966 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1968 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
1969 SILC_STATUS_ERR_NO_CHANNEL_ID);
1974 /* Get the channels from local list */
1975 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
1978 /* Get the channels from global list if we are router */
1979 if (server->server_type == SILC_ROUTER)
1980 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
1983 /* Send the reply */
1984 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
1985 gchannels, gch_count);
1988 silc_server_command_free(cmd);
1991 /* Server side of TOPIC command. Sets topic for channel and/or returns
1992 current topic to client. */
1994 SILC_SERVER_CMD_FUNC(topic)
1996 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1997 SilcServer server = cmd->server;
1998 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1999 SilcChannelID *channel_id;
2000 SilcChannelEntry channel;
2001 SilcChannelClientEntry chl;
2002 SilcBuffer packet, idp;
2004 uint32 argc, tmp_len;
2005 uint16 ident = silc_command_get_ident(cmd->payload);
2007 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
2009 argc = silc_argument_get_arg_num(cmd->args);
2011 /* Get Channel ID */
2012 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2014 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2015 SILC_STATUS_ERR_NO_CHANNEL_ID);
2018 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2020 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2021 SILC_STATUS_ERR_NO_CHANNEL_ID);
2025 /* Check whether the channel exists */
2026 channel = silc_idlist_find_channel_by_id(server->local_list,
2029 channel = silc_idlist_find_channel_by_id(server->global_list,
2032 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2033 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2040 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2042 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2043 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2047 if (strlen(tmp) > 256) {
2048 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2049 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2053 /* See whether has rights to change topic */
2054 silc_list_start(channel->user_list);
2055 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2056 if (chl->client == client)
2059 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2060 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2061 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2062 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2067 /* Set the topic for channel */
2069 silc_free(channel->topic);
2070 channel->topic = strdup(tmp);
2072 /* Send TOPIC_SET notify type to the network */
2073 if (!server->standalone)
2074 silc_server_send_notify_topic_set(server, server->router->connection,
2075 server->server_type == SILC_ROUTER ?
2076 TRUE : FALSE, channel, client->id,
2079 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2081 /* Send notify about topic change to all clients on the channel */
2082 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2083 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2084 idp->data, idp->len,
2085 channel->topic, strlen(channel->topic));
2086 silc_buffer_free(idp);
2089 /* Send the topic to client as reply packet */
2090 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2092 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2093 SILC_STATUS_OK, ident, 2,
2094 2, idp->data, idp->len,
2096 strlen(channel->topic));
2098 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2099 SILC_STATUS_OK, ident, 1,
2100 2, idp->data, idp->len);
2101 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2102 0, packet->data, packet->len, FALSE);
2104 silc_buffer_free(packet);
2105 silc_buffer_free(idp);
2106 silc_free(channel_id);
2109 silc_server_command_free(cmd);
2112 /* Server side of INVITE command. Invites some client to join some channel.
2113 This command is also used to manage the invite list of the channel. */
2115 SILC_SERVER_CMD_FUNC(invite)
2117 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2118 SilcServer server = cmd->server;
2119 SilcSocketConnection sock = cmd->sock, dest_sock;
2120 SilcChannelClientEntry chl;
2121 SilcClientEntry sender, dest;
2122 SilcClientID *dest_id = NULL;
2123 SilcChannelEntry channel;
2124 SilcChannelID *channel_id = NULL;
2125 SilcIDListData idata;
2126 SilcBuffer idp, idp2, packet;
2127 unsigned char *tmp, *add, *del;
2129 uint16 ident = silc_command_get_ident(cmd->payload);
2131 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 4);
2133 /* Get Channel ID */
2134 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2136 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2137 SILC_STATUS_ERR_NO_CHANNEL_ID);
2140 channel_id = silc_id_payload_parse_id(tmp, len);
2142 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2143 SILC_STATUS_ERR_NO_CHANNEL_ID);
2147 /* Get the channel entry */
2148 channel = silc_idlist_find_channel_by_id(server->local_list,
2151 channel = silc_idlist_find_channel_by_id(server->global_list,
2154 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2155 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2160 /* Check whether the sender of this command is on the channel. */
2161 sender = (SilcClientEntry)sock->user_data;
2162 if (!silc_server_client_on_channel(sender, channel)) {
2163 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2164 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2168 /* Check whether the channel is invite-only channel. If yes then the
2169 sender of this command must be at least channel operator. */
2170 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2171 silc_list_start(channel->user_list);
2172 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2173 if (chl->client == sender) {
2174 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2175 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2176 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2183 /* Get destination client ID */
2184 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2188 dest_id = silc_id_payload_parse_id(tmp, len);
2190 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2191 SILC_STATUS_ERR_NO_CLIENT_ID);
2195 /* Get the client entry */
2196 dest = silc_server_get_client_resolve(server, dest_id);
2198 if (server->server_type == SILC_ROUTER) {
2199 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2200 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2204 /* The client info is being resolved. Reprocess this packet after
2205 receiving the reply to the query. */
2206 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2208 silc_server_command_destructor,
2209 silc_server_command_invite,
2210 silc_server_command_dup(cmd));
2211 cmd->pending = TRUE;
2212 silc_free(channel_id);
2217 /* Check whether the requested client is already on the channel. */
2218 if (silc_server_client_on_channel(dest, channel)) {
2219 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2220 SILC_STATUS_ERR_USER_ON_CHANNEL);
2224 /* Get route to the client */
2225 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2227 memset(invite, 0, sizeof(invite));
2228 strncat(invite, dest->nickname, strlen(dest->nickname));
2229 strncat(invite, "!", 1);
2230 strncat(invite, dest->username, strlen(dest->username));
2231 if (!strchr(dest->username, '@')) {
2232 strncat(invite, "@", 1);
2233 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2236 len = strlen(invite);
2237 if (!channel->invite_list)
2238 channel->invite_list = silc_calloc(len + 2,
2239 sizeof(*channel->invite_list));
2241 channel->invite_list = silc_realloc(channel->invite_list,
2242 sizeof(*channel->invite_list) *
2244 strlen(channel->invite_list) + 2));
2245 strncat(channel->invite_list, invite, len);
2246 strncat(channel->invite_list, ",", 1);
2248 /* Send notify to the client that is invited to the channel */
2249 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2250 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2251 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2253 SILC_NOTIFY_TYPE_INVITE, 3,
2254 idp->data, idp->len,
2255 channel->channel_name,
2256 strlen(channel->channel_name),
2257 idp2->data, idp2->len);
2258 silc_buffer_free(idp);
2259 silc_buffer_free(idp2);
2262 /* Add the client to the invite list of the channel */
2263 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2265 if (!channel->invite_list)
2266 channel->invite_list = silc_calloc(len + 2,
2267 sizeof(*channel->invite_list));
2269 channel->invite_list = silc_realloc(channel->invite_list,
2270 sizeof(*channel->invite_list) *
2272 strlen(channel->invite_list) + 2));
2273 if (add[len - 1] == ',')
2274 add[len - 1] = '\0';
2276 strncat(channel->invite_list, add, len);
2277 strncat(channel->invite_list, ",", 1);
2280 /* Get the invite to be removed and remove it from the list */
2281 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2282 if (del && channel->invite_list) {
2283 char *start, *end, *n;
2285 if (!strncmp(channel->invite_list, del,
2286 strlen(channel->invite_list) - 1)) {
2287 silc_free(channel->invite_list);
2288 channel->invite_list = NULL;
2290 start = strstr(channel->invite_list, del);
2291 if (start && strlen(start) >= len) {
2293 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2294 strncat(n, channel->invite_list, start - channel->invite_list);
2295 strncat(n, end + 1, ((channel->invite_list +
2296 strlen(channel->invite_list)) - end) - 1);
2297 silc_free(channel->invite_list);
2298 channel->invite_list = n;
2303 /* Send notify to the primary router */
2304 if (!server->standalone)
2305 silc_server_send_notify_invite(server, server->router->connection,
2306 server->server_type == SILC_ROUTER ?
2307 TRUE : FALSE, channel,
2308 sender->id, add, del);
2310 /* Send command reply */
2311 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2312 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2313 SILC_STATUS_OK, ident, 2,
2315 3, channel->invite_list,
2316 channel->invite_list ?
2317 strlen(channel->invite_list) :
2319 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2320 packet->data, packet->len, FALSE);
2321 silc_buffer_free(packet);
2327 silc_free(channel_id);
2328 silc_server_command_free(cmd);
2333 SilcSocketConnection sock;
2337 /* Quits connection to client. This gets called if client won't
2338 close the connection even when it has issued QUIT command. */
2340 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2342 QuitInternal q = (QuitInternal)context;
2344 /* Free all client specific data, such as client entry and entires
2345 on channels this client may be on. */
2346 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2348 q->sock->user_data = NULL;
2350 /* Close the connection on our side */
2351 silc_server_close_connection(q->server, q->sock);
2353 silc_free(q->signoff);
2357 /* Quits SILC session. This is the normal way to disconnect client. */
2359 SILC_SERVER_CMD_FUNC(quit)
2361 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2362 SilcServer server = cmd->server;
2363 SilcSocketConnection sock = cmd->sock;
2365 unsigned char *tmp = NULL;
2368 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_QUIT, cmd, 0, 1);
2370 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2373 /* Get destination ID */
2374 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2378 q = silc_calloc(1, sizeof(*q));
2381 q->signoff = tmp ? strdup(tmp) : NULL;
2383 /* We quit the connection with little timeout */
2384 silc_task_register(server->timeout_queue, sock->sock,
2385 silc_server_command_quit_cb, (void *)q,
2386 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2389 silc_server_command_free(cmd);
2392 /* Server side of command KILL. This command is used by router operator
2393 to remove an client from the SILC Network temporarily. */
2395 SILC_SERVER_CMD_FUNC(kill)
2397 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2398 SilcServer server = cmd->server;
2399 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2400 SilcClientEntry remote_client;
2401 SilcClientID *client_id;
2402 unsigned char *tmp, *comment;
2403 uint32 tmp_len, tmp_len2;
2405 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_KILL, cmd, 1, 2);
2407 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2410 /* KILL command works only on router */
2411 if (server->server_type != SILC_ROUTER) {
2412 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2413 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2417 /* Check whether client has the permissions. */
2418 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2419 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2420 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2424 /* Get the client ID */
2425 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2427 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2428 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2431 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2433 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2434 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2438 /* Get the client entry */
2439 remote_client = silc_idlist_find_client_by_id(server->local_list,
2441 if (!remote_client) {
2442 remote_client = silc_idlist_find_client_by_id(server->global_list,
2444 if (!remote_client) {
2445 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2446 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2452 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2456 /* Send reply to the sender */
2457 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2460 /* Send the KILL notify packets. First send it to the channel, then
2461 to our primary router and then directly to the client who is being
2462 killed right now. */
2464 /* Send KILLED notify to the channels. It is not sent to the client
2465 as it will be sent differently destined directly to the client and not
2467 silc_server_send_notify_on_channels(server, remote_client,
2468 remote_client, SILC_NOTIFY_TYPE_KILLED,
2471 comment, comment ? tmp_len2 : 0);
2473 /* Send KILLED notify to primary route */
2474 if (!server->standalone)
2475 silc_server_send_notify_killed(server, server->router->connection, TRUE,
2476 remote_client->id, comment);
2478 /* Send KILLED notify to the client directly */
2479 silc_server_send_notify_killed(server, remote_client->connection ?
2480 remote_client->connection :
2481 remote_client->router->connection, FALSE,
2482 remote_client->id, comment);
2484 /* Remove the client from all channels. This generates new keys to the
2485 channels as well. */
2486 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2489 /* Remove the client entry, If it is locally connected then we will also
2490 disconnect the client here */
2491 if (remote_client->data.registered && remote_client->connection) {
2492 /* Remove locally conneted client */
2493 SilcSocketConnection sock = remote_client->connection;
2494 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2495 silc_server_close_connection(server, sock);
2497 /* Remove remote client */
2498 if (!silc_idlist_del_client(server->global_list, remote_client))
2499 silc_idlist_del_client(server->local_list, remote_client);
2503 silc_server_command_free(cmd);
2506 /* Server side of command INFO. This sends information about us to
2507 the client. If client requested specific server we will send the
2508 command to that server. */
2510 SILC_SERVER_CMD_FUNC(info)
2512 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2513 SilcServer server = cmd->server;
2514 SilcBuffer packet, idp;
2517 char *dest_server, *server_info = NULL, *server_name;
2518 uint16 ident = silc_command_get_ident(cmd->payload);
2519 SilcServerEntry entry = NULL;
2520 SilcServerID *server_id = NULL;
2522 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 0, 2);
2524 /* Get server name */
2525 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2528 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2530 server_id = silc_id_payload_parse_id(tmp, tmp_len);
2532 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2533 SILC_STATUS_ERR_NO_SERVER_ID);
2539 /* Check whether we have this server cached */
2540 entry = silc_idlist_find_server_by_id(server->local_list,
2543 entry = silc_idlist_find_server_by_id(server->global_list,
2545 if (!entry && server->server_type == SILC_ROUTER) {
2546 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2547 SILC_STATUS_ERR_NO_SUCH_SERVER);
2553 if ((!dest_server && !server_id) ||
2554 (dest_server && !cmd->pending &&
2555 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2556 /* Send our reply */
2557 char info_string[256];
2559 memset(info_string, 0, sizeof(info_string));
2560 snprintf(info_string, sizeof(info_string),
2561 "location: %s server: %s admin: %s <%s>",
2562 server->config->admin_info->location,
2563 server->config->admin_info->server_type,
2564 server->config->admin_info->admin_name,
2565 server->config->admin_info->admin_email);
2567 server_info = info_string;
2568 entry = server->id_entry;
2570 /* Check whether we have this server cached */
2571 if (!entry && dest_server) {
2572 entry = silc_idlist_find_server_by_name(server->global_list,
2575 entry = silc_idlist_find_server_by_name(server->local_list,
2580 if (!cmd->pending &&
2581 server->server_type == SILC_ROUTER && entry && !entry->server_info) {
2582 /* Send to the server */
2586 old_ident = silc_command_get_ident(cmd->payload);
2587 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2588 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2590 silc_server_packet_send(server, entry->connection,
2591 SILC_PACKET_COMMAND, cmd->packet->flags,
2592 tmpbuf->data, tmpbuf->len, TRUE);
2594 /* Reprocess this packet after received reply from router */
2595 silc_server_command_pending(server, SILC_COMMAND_INFO,
2596 silc_command_get_ident(cmd->payload),
2597 silc_server_command_destructor,
2598 silc_server_command_info,
2599 silc_server_command_dup(cmd));
2600 cmd->pending = TRUE;
2601 silc_command_set_ident(cmd->payload, old_ident);
2602 silc_buffer_free(tmpbuf);
2606 if (!entry && !cmd->pending && !server->standalone) {
2607 /* Send to the primary router */
2611 old_ident = silc_command_get_ident(cmd->payload);
2612 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2613 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2615 silc_server_packet_send(server, server->router->connection,
2616 SILC_PACKET_COMMAND, cmd->packet->flags,
2617 tmpbuf->data, tmpbuf->len, TRUE);
2619 /* Reprocess this packet after received reply from router */
2620 silc_server_command_pending(server, SILC_COMMAND_INFO,
2621 silc_command_get_ident(cmd->payload),
2622 silc_server_command_destructor,
2623 silc_server_command_info,
2624 silc_server_command_dup(cmd));
2625 cmd->pending = TRUE;
2626 silc_command_set_ident(cmd->payload, old_ident);
2627 silc_buffer_free(tmpbuf);
2633 silc_free(server_id);
2636 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2637 SILC_STATUS_ERR_NO_SUCH_SERVER);
2641 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2643 server_info = entry->server_info;
2644 server_name = entry->server_name;
2646 /* Send the reply */
2647 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2648 SILC_STATUS_OK, ident, 3,
2649 2, idp->data, idp->len,
2651 strlen(server_name),
2653 strlen(server_info));
2654 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2655 packet->data, packet->len, FALSE);
2657 silc_buffer_free(packet);
2658 silc_buffer_free(idp);
2661 silc_server_command_free(cmd);
2664 /* Server side of command PING. This just replies to the ping. */
2666 SILC_SERVER_CMD_FUNC(ping)
2668 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2669 SilcServer server = cmd->server;
2674 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
2677 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2679 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2680 SILC_STATUS_ERR_NO_SERVER_ID);
2683 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2687 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2688 /* Send our reply */
2689 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2692 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2693 SILC_STATUS_ERR_NO_SUCH_SERVER);
2700 silc_server_command_free(cmd);
2703 /* Internal routine to join channel. The channel sent to this function
2704 has been either created or resolved from ID lists. This joins the sent
2705 client to the channel. */
2707 static void silc_server_command_join_channel(SilcServer server,
2708 SilcServerCommandContext cmd,
2709 SilcChannelEntry channel,
2710 SilcClientID *client_id,
2714 SilcSocketConnection sock = cmd->sock;
2716 uint32 tmp_len, user_count;
2717 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
2718 SilcClientEntry client;
2719 SilcChannelClientEntry chl;
2720 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
2721 uint16 ident = silc_command_get_ident(cmd->payload);
2724 SILC_LOG_DEBUG(("Start"));
2729 /* Get the client entry */
2730 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2731 client = (SilcClientEntry)sock->user_data;
2733 client = silc_idlist_find_client_by_id(server->local_list, client_id,
2740 * Check channel modes
2743 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2744 strncat(check, client->nickname, strlen(client->nickname));
2745 if (!strchr(client->nickname, '@')) {
2746 strncat(check, "@", 1);
2747 strncat(check, server->server_name, strlen(server->server_name));
2749 strncat(check, "!", 1);
2750 strncat(check, client->username, strlen(client->username));
2751 if (!strchr(client->username, '@')) {
2752 strncat(check, "@", 1);
2753 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
2757 /* Check invite list if channel is invite-only channel */
2758 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
2759 channel->mode & SILC_CHANNEL_MODE_INVITE) {
2760 if (!channel->invite_list) {
2761 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2762 SILC_STATUS_ERR_NOT_INVITED);
2766 if (!silc_string_match(channel->invite_list, check)) {
2767 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2768 SILC_STATUS_ERR_NOT_INVITED);
2773 /* Check ban list if it exists. If the client's nickname, server,
2774 username and/or hostname is in the ban list the access to the
2775 channel is denied. */
2776 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && channel->ban_list) {
2777 if (silc_string_match(channel->ban_list, check)) {
2778 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2779 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
2784 /* Get passphrase */
2785 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2787 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
2788 memcpy(passphrase, tmp, tmp_len);
2791 /* Check the channel passphrase if set. */
2792 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2793 if (!passphrase || memcmp(channel->passphrase, passphrase,
2794 strlen(channel->passphrase))) {
2795 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2796 SILC_STATUS_ERR_BAD_PASSWORD);
2801 /* Check user count limit if set. */
2802 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
2803 if (silc_list_count(channel->user_list) + 1 >
2804 channel->user_limit) {
2805 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2806 SILC_STATUS_ERR_CHANNEL_IS_FULL);
2812 * Client is allowed to join to the channel. Make it happen.
2815 /* Check whether the client already is on the channel */
2816 if (silc_server_client_on_channel(client, channel)) {
2817 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2818 SILC_STATUS_ERR_USER_ON_CHANNEL);
2822 /* Generate new channel key as protocol dictates */
2823 if ((!created && silc_list_count(channel->user_list) > 0) ||
2824 !channel->channel_key)
2825 silc_server_create_channel_key(server, channel, 0);
2827 /* Send the channel key. This is broadcasted to the channel but is not
2828 sent to the client who is joining to the channel. */
2829 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
2830 silc_server_send_channel_key(server, NULL, channel,
2831 server->server_type == SILC_ROUTER ?
2832 FALSE : !server->standalone);
2834 /* Join the client to the channel by adding it to channel's user list.
2835 Add also the channel to client entry's channels list for fast cross-
2837 chl = silc_calloc(1, sizeof(*chl));
2839 chl->client = client;
2840 chl->channel = channel;
2841 silc_list_add(channel->user_list, chl);
2842 silc_list_add(client->channels, chl);
2844 /* Get users on the channel */
2845 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
2848 /* Encode Client ID Payload of the original client who wants to join */
2849 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2851 /* Encode command reply packet */
2852 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2853 SILC_PUT32_MSB(channel->mode, mode);
2854 SILC_PUT32_MSB(created, tmp2);
2855 SILC_PUT32_MSB(user_count, tmp3);
2857 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
2858 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
2859 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
2860 strlen(channel->channel_key->
2862 channel->channel_key->cipher->name,
2863 channel->key_len / 8, channel->key);
2868 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2869 SILC_STATUS_OK, ident, 13,
2870 2, channel->channel_name,
2871 strlen(channel->channel_name),
2872 3, chidp->data, chidp->len,
2873 4, clidp->data, clidp->len,
2876 7, keyp ? keyp->data : NULL,
2877 keyp ? keyp->len : 0,
2878 8, channel->ban_list,
2880 strlen(channel->ban_list) : 0,
2881 9, channel->invite_list,
2882 channel->invite_list ?
2883 strlen(channel->invite_list) : 0,
2886 strlen(channel->topic) : 0,
2887 11, channel->hmac->hmac->name,
2888 strlen(channel->hmac->hmac->name),
2890 13, user_list->data, user_list->len,
2891 14, mode_list->data,
2894 /* Send command reply */
2895 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
2896 reply->data, reply->len, FALSE);
2898 if (!cmd->pending) {
2899 /* Send JOIN notify to locally connected clients on the channel */
2900 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2901 SILC_NOTIFY_TYPE_JOIN, 2,
2902 clidp->data, clidp->len,
2903 chidp->data, chidp->len);
2905 /* Send JOIN notify packet to our primary router */
2906 if (!server->standalone)
2907 silc_server_send_notify_join(server, server->router->connection,
2908 server->server_type == SILC_ROUTER ?
2909 TRUE : FALSE, channel, client->id);
2912 silc_buffer_free(reply);
2913 silc_buffer_free(clidp);
2914 silc_buffer_free(chidp);
2915 silc_buffer_free(keyp);
2916 silc_buffer_free(user_list);
2917 silc_buffer_free(mode_list);
2921 silc_free(passphrase);
2924 /* Server side of command JOIN. Joins client into requested channel. If
2925 the channel does not exist it will be created. */
2927 SILC_SERVER_CMD_FUNC(join)
2929 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2930 SilcServer server = cmd->server;
2932 char *tmp, *channel_name = NULL, *cipher, *hmac;
2933 SilcChannelEntry channel;
2935 int created = FALSE;
2936 SilcClientID *client_id;
2938 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
2940 /* Get channel name */
2941 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2943 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2944 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2949 if (strlen(channel_name) > 256)
2950 channel_name[255] = '\0';
2952 if (silc_server_command_bad_chars(channel_name) == TRUE) {
2953 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2954 SILC_STATUS_ERR_BAD_CHANNEL);
2955 silc_free(channel_name);
2959 /* Get Client ID of the client who is joining to the channel */
2960 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2962 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2963 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2966 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2968 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2969 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2973 /* Get cipher and hmac name */
2974 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2975 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2977 /* See if the channel exists */
2978 channel = silc_idlist_find_channel_by_name(server->local_list,
2979 channel_name, NULL);
2981 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2982 /* If this is coming from client the Client ID in the command packet must
2983 be same as the client's ID. */
2984 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2985 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2986 if (!SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
2987 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2988 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2993 if (!channel || !channel->id) {
2994 /* Channel not found */
2996 /* If we are standalone server we don't have a router, we just create
2997 the channel by ourselves. */
2998 if (server->standalone) {
2999 channel = silc_server_create_new_channel(server, server->id, cipher,
3000 hmac, channel_name, TRUE);
3002 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3003 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3007 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3012 /* The channel does not exist on our server. If we are normal server
3013 we will send JOIN command to our router which will handle the
3014 joining procedure (either creates the channel if it doesn't exist
3015 or joins the client to it). */
3016 if (server->server_type == SILC_SERVER) {
3020 old_ident = silc_command_get_ident(cmd->payload);
3021 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3022 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3024 /* Send JOIN command to our router */
3025 silc_server_packet_send(server, (SilcSocketConnection)
3026 server->router->connection,
3027 SILC_PACKET_COMMAND, cmd->packet->flags,
3028 tmpbuf->data, tmpbuf->len, TRUE);
3030 /* Reprocess this packet after received reply from router */
3031 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3032 silc_command_get_ident(cmd->payload),
3033 silc_server_command_destructor,
3034 silc_server_command_join,
3035 silc_server_command_dup(cmd));
3036 cmd->pending = TRUE;
3040 /* We are router and the channel does not seem exist so we will check
3041 our global list as well for the channel. */
3042 channel = silc_idlist_find_channel_by_name(server->global_list,
3043 channel_name, NULL);
3045 /* Channel really does not exist, create it */
3046 channel = silc_server_create_new_channel(server, server->id, cipher,
3047 hmac, channel_name, TRUE);
3049 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3050 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3054 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3061 /* Channel not found */
3063 /* If the command came from router and/or we are normal server then
3064 something went wrong with the joining as the channel was not found.
3065 We can't do anything else but ignore this. */
3066 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3067 server->server_type == SILC_SERVER)
3070 /* We are router and the channel does not seem exist so we will check
3071 our global list as well for the channel. */
3072 channel = silc_idlist_find_channel_by_name(server->global_list,
3073 channel_name, NULL);
3075 /* Channel really does not exist, create it */
3076 channel = silc_server_create_new_channel(server, server->id, cipher,
3077 hmac, channel_name, TRUE);
3079 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3080 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3084 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3090 /* If the channel does not have global users and is also empty it means the
3091 channel was created globally (by our router) and the client will be the
3092 channel founder and operator. */
3093 if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
3094 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3095 created = TRUE; /* Created globally by our router */
3098 /* Join to the channel */
3099 silc_server_command_join_channel(server, cmd, channel, client_id,
3102 silc_free(client_id);
3105 silc_server_command_free(cmd);
3108 /* Server side of command MOTD. Sends server's current "message of the
3109 day" to the client. */
3111 SILC_SERVER_CMD_FUNC(motd)
3113 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3114 SilcServer server = cmd->server;
3115 SilcBuffer packet, idp;
3116 char *motd, *dest_server;
3118 uint16 ident = silc_command_get_ident(cmd->payload);
3120 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 1);
3122 /* Get server name */
3123 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3125 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3126 SILC_STATUS_ERR_NO_SUCH_SERVER);
3130 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3133 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3135 if (server->config && server->config->motd &&
3136 server->config->motd->motd_file) {
3138 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
3143 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3144 SILC_STATUS_OK, ident, 2,
3150 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3151 SILC_STATUS_OK, ident, 1,
3155 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3156 packet->data, packet->len, FALSE);
3157 silc_buffer_free(packet);
3158 silc_buffer_free(idp);
3160 SilcServerEntry entry;
3162 /* Check whether we have this server cached */
3163 entry = silc_idlist_find_server_by_name(server->global_list,
3166 entry = silc_idlist_find_server_by_name(server->local_list,
3170 if (server->server_type == SILC_ROUTER && !cmd->pending &&
3171 entry && !entry->motd) {
3172 /* Send to the server */
3176 old_ident = silc_command_get_ident(cmd->payload);
3177 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3178 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3180 silc_server_packet_send(server, entry->connection,
3181 SILC_PACKET_COMMAND, cmd->packet->flags,
3182 tmpbuf->data, tmpbuf->len, TRUE);
3184 /* Reprocess this packet after received reply from router */
3185 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3186 silc_command_get_ident(cmd->payload),
3187 silc_server_command_destructor,
3188 silc_server_command_motd,
3189 silc_server_command_dup(cmd));
3190 cmd->pending = TRUE;
3191 silc_command_set_ident(cmd->payload, old_ident);
3192 silc_buffer_free(tmpbuf);
3196 if (!entry && !cmd->pending && !server->standalone) {
3197 /* Send to the primary router */
3201 old_ident = silc_command_get_ident(cmd->payload);
3202 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3203 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3205 silc_server_packet_send(server, server->router->connection,
3206 SILC_PACKET_COMMAND, cmd->packet->flags,
3207 tmpbuf->data, tmpbuf->len, TRUE);
3209 /* Reprocess this packet after received reply from router */
3210 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3211 silc_command_get_ident(cmd->payload),
3212 silc_server_command_destructor,
3213 silc_server_command_motd,
3214 silc_server_command_dup(cmd));
3215 cmd->pending = TRUE;
3216 silc_command_set_ident(cmd->payload, old_ident);
3217 silc_buffer_free(tmpbuf);
3222 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3223 SILC_STATUS_ERR_NO_SUCH_SERVER);
3227 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3230 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3231 SILC_STATUS_OK, ident, 2,
3234 strlen(entry->motd));
3236 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3237 SILC_STATUS_OK, ident, 1,
3240 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3241 packet->data, packet->len, FALSE);
3242 silc_buffer_free(packet);
3243 silc_buffer_free(idp);
3247 silc_server_command_free(cmd);
3250 /* Server side of command UMODE. Client can use this command to set/unset
3251 user mode. Client actually cannot set itself to be as server/router
3252 operator so this can be used only to unset the modes. */
3254 SILC_SERVER_CMD_FUNC(umode)
3256 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3257 SilcServer server = cmd->server;
3258 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3260 unsigned char *tmp_mask;
3262 uint16 ident = silc_command_get_ident(cmd->payload);
3264 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3267 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_UMODE, cmd, 2, 2);
3269 /* Get the client's mode mask */
3270 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3272 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3273 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3276 SILC_GET32_MSB(mask, tmp_mask);
3282 if (mask & SILC_UMODE_SERVER_OPERATOR) {
3283 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR)) {
3284 /* Cannot operator mode */
3285 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3286 SILC_STATUS_ERR_PERM_DENIED);
3290 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
3291 /* Remove the server operator rights */
3292 client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3295 if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3296 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
3297 /* Cannot operator mode */
3298 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3299 SILC_STATUS_ERR_PERM_DENIED);
3303 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
3304 /* Remove the router operator rights */
3305 client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3308 if (mask & SILC_UMODE_GONE) {
3309 client->mode |= SILC_UMODE_GONE;
3311 if (client->mode & SILC_UMODE_GONE)
3312 /* Remove the gone status */
3313 client->mode &= ~SILC_UMODE_GONE;
3316 /* Send UMODE change to primary router */
3317 if (!server->standalone)
3318 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3319 client->id, client->mode);
3321 /* Send command reply to sender */
3322 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3323 SILC_STATUS_OK, ident, 1,
3325 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3326 packet->data, packet->len, FALSE);
3327 silc_buffer_free(packet);
3330 silc_server_command_free(cmd);
3333 /* Checks that client has rights to add or remove channel modes. If any
3334 of the checks fails FALSE is returned. */
3336 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3337 SilcChannelClientEntry client,
3340 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3341 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3343 /* Check whether has rights to change anything */
3344 if (!is_op && !is_fo)
3347 /* Check whether has rights to change everything */
3351 /* We know that client is channel operator, check that they are not
3352 changing anything that requires channel founder rights. Rest of the
3353 modes are available automatically for channel operator. */
3355 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3356 if (is_op && !is_fo)
3359 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3360 if (is_op && !is_fo)
3365 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3366 if (is_op && !is_fo)
3369 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3370 if (is_op && !is_fo)
3375 if (mode & SILC_CHANNEL_MODE_CIPHER) {
3376 if (is_op && !is_fo)
3379 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3380 if (is_op && !is_fo)
3385 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3386 if (is_op && !is_fo)
3389 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3390 if (is_op && !is_fo)
3398 /* Server side command of CMODE. Changes channel mode */
3400 SILC_SERVER_CMD_FUNC(cmode)
3402 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3403 SilcServer server = cmd->server;
3404 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3405 SilcIDListData idata = (SilcIDListData)client;
3406 SilcChannelID *channel_id;
3407 SilcChannelEntry channel;
3408 SilcChannelClientEntry chl;
3409 SilcBuffer packet, cidp;
3410 unsigned char *tmp, *tmp_id, *tmp_mask;
3411 char *cipher = NULL, *hmac = NULL;
3412 uint32 mode_mask, tmp_len, tmp_len2;
3413 uint16 ident = silc_command_get_ident(cmd->payload);
3415 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CMODE, cmd, 2, 7);
3417 /* Get Channel ID */
3418 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3420 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3421 SILC_STATUS_ERR_NO_CHANNEL_ID);
3424 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3426 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3427 SILC_STATUS_ERR_NO_CHANNEL_ID);
3431 /* Get the channel mode mask */
3432 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3434 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3435 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3438 SILC_GET32_MSB(mode_mask, tmp_mask);
3440 /* Get channel entry */
3441 channel = silc_idlist_find_channel_by_id(server->local_list,
3444 channel = silc_idlist_find_channel_by_id(server->global_list,
3447 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3448 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3453 /* Check whether this client is on the channel */
3454 if (!silc_server_client_on_channel(client, channel)) {
3455 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3456 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3460 /* Get entry to the channel user list */
3461 silc_list_start(channel->user_list);
3462 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
3463 if (chl->client == client)
3466 /* Check that client has rights to change any requested channel modes */
3467 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3468 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3469 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3474 * Check the modes. Modes that requires nothing special operation are
3478 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3479 /* Channel uses private keys to protect traffic. Client(s) has set the
3480 key locally they want to use, server does not know that key. */
3481 /* Nothing interesting to do here */
3483 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3484 /* The mode is removed and we need to generate and distribute
3485 new channel key. Clients are not using private channel keys
3486 anymore after this. */
3488 /* Re-generate channel key */
3489 silc_server_create_channel_key(server, channel, 0);
3491 /* Send the channel key. This sends it to our local clients and if
3492 we are normal server to our router as well. */
3493 silc_server_send_channel_key(server, NULL, channel,
3494 server->server_type == SILC_ROUTER ?
3495 FALSE : !server->standalone);
3497 cipher = channel->channel_key->cipher->name;
3498 hmac = channel->hmac->hmac->name;
3502 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3503 /* User limit is set on channel */
3506 /* Get user limit */
3507 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3509 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3510 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3511 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3515 SILC_GET32_MSB(user_limit, tmp);
3516 channel->user_limit = user_limit;
3519 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3520 /* User limit mode is unset. Remove user limit */
3521 channel->user_limit = 0;
3524 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3525 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3526 /* Passphrase has been set to channel */
3528 /* Get the passphrase */
3529 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3531 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3532 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3536 /* Save the passphrase */
3537 channel->passphrase = strdup(tmp);
3540 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3541 /* Passphrase mode is unset. remove the passphrase */
3542 if (channel->passphrase) {
3543 silc_free(channel->passphrase);
3544 channel->passphrase = NULL;
3549 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3550 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3551 /* Cipher to use protect the traffic */
3554 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3556 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3557 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3561 /* Delete old cipher and allocate the new one */
3562 silc_cipher_free(channel->channel_key);
3563 if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
3564 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3565 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3569 /* Re-generate channel key */
3570 silc_server_create_channel_key(server, channel, 0);
3572 /* Send the channel key. This sends it to our local clients and if
3573 we are normal server to our router as well. */
3574 silc_server_send_channel_key(server, NULL, channel,
3575 server->server_type == SILC_ROUTER ?
3576 FALSE : !server->standalone);
3579 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3580 /* Cipher mode is unset. Remove the cipher and revert back to
3582 cipher = channel->cipher;
3584 /* Delete old cipher and allocate default one */
3585 silc_cipher_free(channel->channel_key);
3586 if (!silc_cipher_alloc(cipher ? cipher : "aes-256-cbc",
3587 &channel->channel_key)) {
3588 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3589 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3593 /* Re-generate channel key */
3594 silc_server_create_channel_key(server, channel, 0);
3596 /* Send the channel key. This sends it to our local clients and if
3597 we are normal server to our router as well. */
3598 silc_server_send_channel_key(server, NULL, channel,
3599 server->server_type == SILC_ROUTER ?
3600 FALSE : !server->standalone);
3604 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3605 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3606 /* HMAC to use protect the traffic */
3607 unsigned char hash[32];
3610 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3612 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3613 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3617 /* Delete old hmac and allocate the new one */
3618 silc_hmac_free(channel->hmac);
3619 if (!silc_hmac_alloc(hmac, NULL, &channel->hmac)) {
3620 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3621 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3625 /* Set the HMAC key out of current channel key. The client must do
3627 silc_hash_make(channel->hmac->hash, channel->key, channel->key_len / 8,
3629 silc_hmac_set_key(channel->hmac, hash,
3630 silc_hash_len(channel->hmac->hash));
3631 memset(hash, 0, sizeof(hash));
3634 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
3635 /* Hmac mode is unset. Remove the hmac and revert back to
3637 unsigned char hash[32];
3638 hmac = channel->hmac_name;
3640 /* Delete old hmac and allocate default one */
3641 silc_hmac_free(channel->hmac);
3642 if (!silc_hmac_alloc(hmac ? hmac : "hmac-sha1-96", NULL,
3644 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3645 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3649 /* Set the HMAC key out of current channel key. The client must do
3651 silc_hash_make(channel->hmac->hash, channel->key, channel->key_len / 8,
3653 silc_hmac_set_key(channel->hmac, hash,
3654 silc_hash_len(channel->hmac->hash));
3655 memset(hash, 0, sizeof(hash));
3659 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3660 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3661 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
3662 /* Set the founder authentication */
3663 SilcAuthPayload auth;
3665 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
3667 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3668 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3672 auth = silc_auth_payload_parse(tmp, tmp_len);
3674 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3675 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3679 /* Save the public key */
3680 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
3681 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
3684 channel->founder_method = silc_auth_get_method(auth);
3686 if (channel->founder_method == SILC_AUTH_PASSWORD) {
3687 tmp = silc_auth_get_data(auth, &tmp_len);
3688 channel->founder_passwd =
3689 silc_calloc(tmp_len + 1, sizeof(*channel->founder_passwd));
3690 memcpy(channel->founder_passwd, tmp, tmp_len);
3691 channel->founder_passwd_len = tmp_len;
3694 silc_auth_payload_free(auth);
3698 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3699 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3700 if (channel->founder_key)
3701 silc_pkcs_public_key_free(channel->founder_key);
3702 if (channel->founder_passwd) {
3703 silc_free(channel->founder_passwd);
3704 channel->founder_passwd = NULL;
3710 /* Finally, set the mode */
3711 channel->mode = mode_mask;
3713 /* Send CMODE_CHANGE notify */
3714 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3715 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3716 SILC_NOTIFY_TYPE_CMODE_CHANGE, 4,
3717 cidp->data, cidp->len,
3719 cipher, cipher ? strlen(cipher) : 0,
3720 hmac, hmac ? strlen(hmac) : 0);
3722 /* Set CMODE notify type to network */
3723 if (!server->standalone)
3724 silc_server_send_notify_cmode(server, server->router->connection,
3725 server->server_type == SILC_ROUTER ?
3726 TRUE : FALSE, channel,
3727 mode_mask, client->id, SILC_ID_CLIENT,
3730 /* Send command reply to sender */
3731 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3732 SILC_STATUS_OK, ident, 1,
3734 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3735 packet->data, packet->len, FALSE);
3737 silc_buffer_free(packet);
3738 silc_free(channel_id);
3742 silc_server_command_free(cmd);
3745 /* Server side of CUMODE command. Changes client's mode on a channel. */
3747 SILC_SERVER_CMD_FUNC(cumode)
3749 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3750 SilcServer server = cmd->server;
3751 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3752 SilcIDListData idata = (SilcIDListData)client;
3753 SilcChannelID *channel_id;
3754 SilcClientID *client_id;
3755 SilcChannelEntry channel;
3756 SilcClientEntry target_client;
3757 SilcChannelClientEntry chl;
3758 SilcBuffer packet, idp;
3759 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
3760 uint32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
3762 uint16 ident = silc_command_get_ident(cmd->payload);
3764 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 4);
3766 /* Get Channel ID */
3767 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3769 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3770 SILC_STATUS_ERR_NO_CHANNEL_ID);
3773 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
3775 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3776 SILC_STATUS_ERR_NO_CHANNEL_ID);
3780 /* Get channel entry */
3781 channel = silc_idlist_find_channel_by_id(server->local_list,
3784 channel = silc_idlist_find_channel_by_id(server->global_list,
3787 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3788 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3793 /* Check whether sender is on the channel */
3794 if (!silc_server_client_on_channel(client, channel)) {
3795 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3796 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3800 /* Check that client has rights to change other's rights */
3801 silc_list_start(channel->user_list);
3802 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3803 if (chl->client == client) {
3804 sender_mask = chl->mode;
3809 /* Get the target client's channel mode mask */
3810 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3812 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3813 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3816 SILC_GET32_MSB(target_mask, tmp_mask);
3818 /* Get target Client ID */
3819 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3821 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3822 SILC_STATUS_ERR_NO_CLIENT_ID);
3825 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
3827 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3828 SILC_STATUS_ERR_NO_CLIENT_ID);
3832 /* Get target client's entry */
3833 target_client = silc_idlist_find_client_by_id(server->local_list,
3835 if (!target_client) {
3836 target_client = silc_idlist_find_client_by_id(server->global_list,
3840 if (target_client != client &&
3841 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
3842 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
3843 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3844 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3848 /* Check whether target client is on the channel */
3849 if (target_client != client) {
3850 if (!silc_server_client_on_channel(target_client, channel)) {
3851 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3852 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
3856 /* Get entry to the channel user list */
3857 silc_list_start(channel->user_list);
3858 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
3859 if (chl->client == target_client)
3867 /* If the target client is founder, no one else can change their mode
3869 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
3870 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3871 SILC_STATUS_ERR_NOT_YOU);
3875 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
3876 /* The client tries to claim the founder rights. */
3877 unsigned char *tmp_auth;
3878 uint32 tmp_auth_len, auth_len;
3881 if (target_client != client) {
3882 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3883 SILC_STATUS_ERR_NOT_YOU);
3887 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
3888 !channel->founder_key) {
3889 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3890 SILC_STATUS_ERR_NOT_YOU);
3894 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
3896 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3897 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3901 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
3902 (void *)channel->founder_passwd : (void *)channel->founder_key);
3903 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
3904 channel->founder_passwd_len : 0);
3906 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
3907 channel->founder_method, auth, auth_len,
3908 idata->hash, client->id, SILC_ID_CLIENT)) {
3909 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3910 SILC_STATUS_ERR_AUTH_FAILED);
3914 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
3917 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3918 if (target_client == client) {
3919 /* Remove channel founder rights from itself */
3920 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3923 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3924 SILC_STATUS_ERR_NOT_YOU);
3930 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
3931 /* Promote to operator */
3932 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3933 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3934 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3935 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3936 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3940 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
3944 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
3945 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3946 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3947 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3948 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3952 /* Demote to normal user */
3953 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
3958 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3959 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3961 /* Send notify to channel, notify only if mode was actually changed. */
3963 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3964 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3965 idp->data, idp->len,
3969 /* Set CUMODE notify type to network */
3970 if (!server->standalone)
3971 silc_server_send_notify_cumode(server, server->router->connection,
3972 server->server_type == SILC_ROUTER ?
3973 TRUE : FALSE, channel,
3974 target_mask, client->id,
3979 /* Send command reply to sender */
3980 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
3981 SILC_STATUS_OK, ident, 2,
3983 3, tmp_id, tmp_len);
3984 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3985 packet->data, packet->len, FALSE);
3987 silc_buffer_free(packet);
3988 silc_free(channel_id);
3989 silc_free(client_id);
3990 silc_buffer_free(idp);
3993 silc_server_command_free(cmd);
3996 /* Server side of KICK command. Kicks client out of channel. */
3998 SILC_SERVER_CMD_FUNC(kick)
4000 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4001 SilcServer server = cmd->server;
4002 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4003 SilcClientEntry target_client;
4004 SilcChannelID *channel_id;
4005 SilcClientID *client_id;
4006 SilcChannelEntry channel;
4007 SilcChannelClientEntry chl;
4010 unsigned char *tmp, *comment;
4012 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 3);
4014 /* Get Channel ID */
4015 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4017 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4018 SILC_STATUS_ERR_NO_CHANNEL_ID);
4021 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
4023 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4024 SILC_STATUS_ERR_NO_CHANNEL_ID);
4028 /* Get channel entry */
4029 channel = silc_idlist_find_channel_by_id(server->local_list,
4032 channel = silc_idlist_find_channel_by_id(server->local_list,
4035 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4036 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4041 /* Check whether sender is on the channel */
4042 if (!silc_server_client_on_channel(client, channel)) {
4043 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4044 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4048 /* Check that the kicker is channel operator or channel founder */
4049 silc_list_start(channel->user_list);
4050 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
4051 if (chl->client == client) {
4052 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4053 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4054 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4061 /* Get target Client ID */
4062 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4064 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4065 SILC_STATUS_ERR_NO_CLIENT_ID);
4068 client_id = silc_id_payload_parse_id(tmp, tmp_len);
4070 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4071 SILC_STATUS_ERR_NO_CLIENT_ID);
4075 /* Get target client's entry */
4076 target_client = silc_idlist_find_client_by_id(server->local_list,
4078 if (!target_client) {
4079 target_client = silc_idlist_find_client_by_id(server->global_list,
4083 /* Check that the target client is not channel founder. Channel founder
4084 cannot be kicked from the channel. */
4085 silc_list_start(channel->user_list);
4086 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
4087 if (chl->client == target_client) {
4088 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4089 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4090 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4097 /* Check whether target client is on the channel */
4098 if (!silc_server_client_on_channel(target_client, channel)) {
4099 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4100 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4106 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4110 /* Send command reply to sender */
4111 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4114 /* Send KICKED notify to local clients on the channel */
4115 idp = silc_id_payload_encode(target_client->id, SILC_ID_CLIENT);
4116 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4117 SILC_NOTIFY_TYPE_KICKED,
4119 idp->data, idp->len,
4120 comment, comment ? strlen(comment) : 0);
4121 silc_buffer_free(idp);
4123 /* Remove the client from the channel. If the channel does not exist
4124 after removing the client then the client kicked itself off the channel
4125 and we don't have to send anything after that. */
4126 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4127 target_client, FALSE))
4130 /* Send KICKED notify to primary route */
4131 if (!server->standalone)
4132 silc_server_send_notify_kicked(server, server->router->connection,
4133 server->server_type == SILC_ROUTER ?
4134 TRUE : FALSE, channel,
4135 target_client->id, comment);
4137 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4138 /* Re-generate channel key */
4139 silc_server_create_channel_key(server, channel, 0);
4141 /* Send the channel key to the channel. The key of course is not sent
4142 to the client who was kicked off the channel. */
4143 silc_server_send_channel_key(server, target_client->connection, channel,
4144 server->server_type == SILC_ROUTER ?
4145 FALSE : !server->standalone);
4149 silc_server_command_free(cmd);
4152 /* Server side of OPER command. Client uses this comand to obtain server
4153 operator privileges to this server/router. */
4155 SILC_SERVER_CMD_FUNC(oper)
4157 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4158 SilcServer server = cmd->server;
4159 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4160 unsigned char *username, *auth;
4162 SilcServerConfigSectionAdminConnection *admin;
4163 SilcIDListData idata = (SilcIDListData)client;
4165 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_OPER, cmd, 1, 2);
4167 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4170 /* Get the username */
4171 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4173 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4174 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4178 /* Get the admin configuration */
4179 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4180 username, client->nickname);
4182 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4183 username, client->nickname);
4185 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4186 SILC_STATUS_ERR_AUTH_FAILED);
4191 /* Get the authentication payload */
4192 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4194 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4195 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4199 /* Verify the authentication data */
4200 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4201 admin->auth_data, admin->auth_data_len,
4202 idata->hash, client->id, SILC_ID_CLIENT)) {
4203 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4204 SILC_STATUS_ERR_AUTH_FAILED);
4208 /* Client is now server operator */
4209 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4211 /* Send UMODE change to primary router */
4212 if (!server->standalone)
4213 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4214 client->id, client->mode);
4216 /* Send reply to the sender */
4217 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4221 silc_server_command_free(cmd);
4224 /* Server side of SILCOPER command. Client uses this comand to obtain router
4225 operator privileges to this router. */
4227 SILC_SERVER_CMD_FUNC(silcoper)
4229 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4230 SilcServer server = cmd->server;
4231 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4232 unsigned char *username, *auth;
4234 SilcServerConfigSectionAdminConnection *admin;
4235 SilcIDListData idata = (SilcIDListData)client;
4237 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4239 if (server->server_type == SILC_SERVER)
4242 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4245 /* Get the username */
4246 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4248 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4249 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4253 /* Get the admin configuration */
4254 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4255 username, client->nickname);
4257 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4258 username, client->nickname);
4260 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4261 SILC_STATUS_ERR_AUTH_FAILED);
4266 /* Get the authentication payload */
4267 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4269 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4270 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4274 /* Verify the authentication data */
4275 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4276 admin->auth_data, admin->auth_data_len,
4277 idata->hash, client->id, SILC_ID_CLIENT)) {
4278 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4279 SILC_STATUS_ERR_AUTH_FAILED);
4283 /* Client is now router operator */
4284 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4286 /* Send UMODE change to primary router */
4287 if (!server->standalone)
4288 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4289 client->id, client->mode);
4291 /* Send reply to the sender */
4292 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4296 silc_server_command_free(cmd);
4299 /* Server side command of CONNECT. Connects us to the specified remote
4300 server or router. */
4302 SILC_SERVER_CMD_FUNC(connect)
4304 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4305 SilcServer server = cmd->server;
4306 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4307 unsigned char *tmp, *host;
4309 uint32 port = SILC_PORT;
4311 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CONNECT, cmd, 1, 2);
4313 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4316 /* Check whether client has the permissions. */
4317 if (client->mode == SILC_UMODE_NONE) {
4318 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4319 SILC_STATUS_ERR_NO_SERVER_PRIV);
4323 if (server->server_type == SILC_ROUTER &&
4324 client->mode & SILC_UMODE_SERVER_OPERATOR) {
4325 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4326 SILC_STATUS_ERR_NO_ROUTER_PRIV);
4330 /* Get the remote server */
4331 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4333 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4334 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4339 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4341 SILC_GET32_MSB(port, tmp);
4343 /* Create the connection. It is done with timeout and is async. */
4344 silc_server_create_connection(server, host, port);
4346 /* Send reply to the sender */
4347 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4351 silc_server_command_free(cmd);
4354 /* Server side of command BAN. This is used to manage the ban list of the
4355 channel. To add clients and remove clients from the ban list. */
4357 SILC_SERVER_CMD_FUNC(ban)
4359 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4360 SilcServer server = cmd->server;
4361 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4363 SilcChannelEntry channel;
4364 SilcChannelClientEntry chl;
4365 SilcChannelID *channel_id = NULL;
4366 unsigned char *id, *add, *del;
4367 uint32 id_len, tmp_len;
4368 uint16 ident = silc_command_get_ident(cmd->payload);
4370 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4373 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_BAN, cmd, 0, 3);
4375 /* Get Channel ID */
4376 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4378 channel_id = silc_id_payload_parse_id(id, id_len);
4380 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4381 SILC_STATUS_ERR_NO_CHANNEL_ID);
4386 /* Get channel entry. The server must know about the channel since the
4387 client is expected to be on the channel. */
4388 channel = silc_idlist_find_channel_by_id(server->local_list,
4391 channel = silc_idlist_find_channel_by_id(server->global_list,
4394 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4395 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4400 /* Check whether this client is on the channel */
4401 if (!silc_server_client_on_channel(client, channel)) {
4402 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4403 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4407 /* Get entry to the channel user list */
4408 silc_list_start(channel->user_list);
4409 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
4410 if (chl->client == client)
4413 /* The client must be at least channel operator. */
4414 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4415 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4416 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4420 /* Get the new ban and add it to the ban list */
4421 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4423 if (!channel->ban_list)
4424 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4426 channel->ban_list = silc_realloc(channel->ban_list,
4427 sizeof(*channel->ban_list) *
4429 strlen(channel->ban_list) + 2));
4430 if (add[tmp_len - 1] == ',')
4431 add[tmp_len - 1] = '\0';
4433 strncat(channel->ban_list, add, tmp_len);
4434 strncat(channel->ban_list, ",", 1);
4437 /* Get the ban to be removed and remove it from the list */
4438 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4439 if (del && channel->ban_list) {
4440 char *start, *end, *n;
4442 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4443 silc_free(channel->ban_list);
4444 channel->ban_list = NULL;
4446 start = strstr(channel->ban_list, del);
4447 if (start && strlen(start) >= tmp_len) {
4448 end = start + tmp_len;
4449 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4450 strncat(n, channel->ban_list, start - channel->ban_list);
4451 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4453 silc_free(channel->ban_list);
4454 channel->ban_list = n;
4459 /* Send the BAN notify type to our primary router. */
4460 if (!server->standalone && (add || del))
4461 silc_server_send_notify_ban(server, server->router->connection,
4462 server->server_type == SILC_ROUTER ?
4463 TRUE : FALSE, channel, add, del);
4465 /* Send the reply back to the client */
4466 if (channel->ban_list)
4468 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4469 SILC_STATUS_OK, ident, 2,
4471 3, channel->ban_list,
4472 strlen(channel->ban_list) - 1);
4475 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4476 SILC_STATUS_OK, ident, 1,
4479 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4480 packet->data, packet->len, FALSE);
4482 silc_buffer_free(packet);
4486 silc_free(channel_id);
4487 silc_server_command_free(cmd);
4490 /* Server side command of CLOSE. Closes connection to a specified server. */
4492 SILC_SERVER_CMD_FUNC(close)
4494 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4495 SilcServer server = cmd->server;
4496 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4497 SilcServerEntry server_entry;
4498 SilcSocketConnection sock;
4501 unsigned char *name;
4502 uint32 port = SILC_PORT;
4504 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CLOSE, cmd, 1, 2);
4506 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4509 /* Check whether client has the permissions. */
4510 if (client->mode == SILC_UMODE_NONE) {
4511 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4512 SILC_STATUS_ERR_NO_SERVER_PRIV);
4516 /* Get the remote server */
4517 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4519 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4520 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4525 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4527 SILC_GET32_MSB(port, tmp);
4529 server_entry = silc_idlist_find_server_by_conn(server->local_list,
4531 if (!server_entry) {
4532 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4533 SILC_STATUS_ERR_NO_SERVER_ID);
4537 /* Send reply to the sender */
4538 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4541 /* Close the connection to the server */
4542 sock = (SilcSocketConnection)server_entry->connection;
4543 silc_server_free_sock_user_data(server, sock);
4544 silc_server_close_connection(server, sock);
4547 silc_server_command_free(cmd);
4550 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4551 active connections. */
4553 SILC_SERVER_CMD_FUNC(shutdown)
4555 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4556 SilcServer server = cmd->server;
4557 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4559 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4561 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4564 /* Check whether client has the permission. */
4565 if (client->mode == SILC_UMODE_NONE) {
4566 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4567 SILC_STATUS_ERR_NO_SERVER_PRIV);
4571 /* Send reply to the sender */
4572 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4575 /* Then, gracefully, or not, bring the server down. */
4576 silc_server_stop(server);
4580 silc_server_command_free(cmd);
4583 /* Server side command of LEAVE. Removes client from a channel. */
4585 SILC_SERVER_CMD_FUNC(leave)
4587 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4588 SilcServer server = cmd->server;
4589 SilcSocketConnection sock = cmd->sock;
4590 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4591 SilcChannelID *id = NULL;
4592 SilcChannelEntry channel;
4596 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
4598 /* Get Channel ID */
4599 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4601 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4602 SILC_STATUS_ERR_NO_CHANNEL_ID);
4605 id = silc_id_payload_parse_id(tmp, len);
4607 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4608 SILC_STATUS_ERR_NO_CHANNEL_ID);
4612 /* Get channel entry */
4613 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4615 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4617 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4618 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4623 /* Check whether this client is on the channel */
4624 if (!silc_server_client_on_channel(id_entry, channel)) {
4625 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4626 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4630 /* Notify routers that they should remove this client from their list
4631 of clients on the channel. Send LEAVE notify type. */
4632 if (!server->standalone)
4633 silc_server_send_notify_leave(server, server->router->connection,
4634 server->server_type == SILC_ROUTER ?
4635 TRUE : FALSE, channel, id_entry->id);
4637 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4640 /* Remove client from channel */
4641 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4643 /* If the channel does not exist anymore we won't send anything */
4646 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4647 /* Re-generate channel key */
4648 silc_server_create_channel_key(server, channel, 0);
4650 /* Send the channel key */
4651 silc_server_send_channel_key(server, NULL, channel,
4652 server->server_type == SILC_ROUTER ?
4653 FALSE : !server->standalone);
4659 silc_server_command_free(cmd);
4662 /* Server side of command USERS. Resolves clients and their USERS currently
4663 joined on the requested channel. The list of Client ID's and their modes
4664 on the channel is sent back. */
4666 SILC_SERVER_CMD_FUNC(users)
4668 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4669 SilcServer server = cmd->server;
4670 SilcChannelEntry channel;
4673 unsigned char *channel_id;
4674 uint32 channel_id_len;
4675 SilcBuffer client_id_list;
4676 SilcBuffer client_mode_list;
4677 unsigned char lc[4];
4678 uint32 list_count = 0;
4679 uint16 ident = silc_command_get_ident(cmd->payload);
4681 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
4683 /* Get Channel ID */
4684 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4686 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4687 SILC_STATUS_ERR_NO_CHANNEL_ID);
4690 id = silc_id_payload_parse_id(channel_id, channel_id_len);
4692 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4693 SILC_STATUS_ERR_NO_CHANNEL_ID);
4697 /* If we are server and we don't know about this channel we will send
4698 the command to our router. If we know about the channel then we also
4699 have the list of users already. */
4700 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4702 if (server->server_type == SILC_SERVER && !server->standalone &&
4706 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
4707 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4709 /* Send USERS command */
4710 silc_server_packet_send(server, server->router->connection,
4711 SILC_PACKET_COMMAND, cmd->packet->flags,
4712 tmpbuf->data, tmpbuf->len, TRUE);
4714 /* Reprocess this packet after received reply */
4715 silc_server_command_pending(server, SILC_COMMAND_USERS,
4716 silc_command_get_ident(cmd->payload),
4717 silc_server_command_destructor,
4718 silc_server_command_users,
4719 silc_server_command_dup(cmd));
4720 cmd->pending = TRUE;
4721 silc_command_set_ident(cmd->payload, ident);
4723 silc_buffer_free(tmpbuf);
4728 /* We are router and we will check the global list as well. */
4729 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4731 /* Channel really does not exist */
4732 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4733 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4738 /* Get the users list */
4739 silc_server_get_users_on_channel(server, channel, &client_id_list,
4740 &client_mode_list, &list_count);
4743 SILC_PUT32_MSB(list_count, lc);
4746 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
4747 SILC_STATUS_OK, ident, 4,
4748 2, channel_id, channel_id_len,
4750 4, client_id_list->data,
4751 client_id_list->len,
4752 5, client_mode_list->data,
4753 client_mode_list->len);
4754 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4755 packet->data, packet->len, FALSE);
4757 silc_buffer_free(packet);
4758 silc_buffer_free(client_id_list);
4759 silc_buffer_free(client_mode_list);
4763 silc_server_command_free(cmd);
4766 /* Server side of command GETKEY. This fetches the client's public key
4767 from the server where to the client is connected. */
4769 SILC_SERVER_CMD_FUNC(getkey)
4771 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4772 SilcServer server = cmd->server;
4774 SilcClientEntry client;
4775 SilcServerEntry server_entry;
4776 SilcClientID *client_id = NULL;
4777 SilcServerID *server_id = NULL;
4778 SilcIDPayload idp = NULL;
4779 uint16 ident = silc_command_get_ident(cmd->payload);
4785 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4787 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4788 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4791 idp = silc_id_payload_parse_data(tmp, tmp_len);
4793 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4794 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4798 id_type = silc_id_payload_get_type(idp);
4799 if (id_type == SILC_ID_CLIENT) {
4800 client_id = silc_id_payload_get_id(idp);
4802 /* If the client is not found from local list there is no chance it
4803 would be locally connected client so send the command further. */
4804 client = silc_idlist_find_client_by_id(server->local_list,
4807 if ((!client && !cmd->pending && !server->standalone) ||
4808 (client && !client->connection)) {
4811 SilcSocketConnection dest_sock;
4813 dest_sock = silc_server_get_client_route(server, NULL, 0,
4818 old_ident = silc_command_get_ident(cmd->payload);
4819 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
4820 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4822 silc_server_packet_send(server, dest_sock,
4823 SILC_PACKET_COMMAND, cmd->packet->flags,
4824 tmpbuf->data, tmpbuf->len, TRUE);
4826 /* Reprocess this packet after received reply from router */
4827 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
4828 silc_command_get_ident(cmd->payload),
4829 silc_server_command_destructor,
4830 silc_server_command_getkey,
4831 silc_server_command_dup(cmd));
4832 cmd->pending = TRUE;
4834 silc_command_set_ident(cmd->payload, old_ident);
4835 silc_buffer_free(tmpbuf);
4839 if (!client && cmd->pending) {
4840 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4841 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
4845 /* The client is locally connected, just get the public key and
4847 tmp = silc_pkcs_public_key_encode(client->data.public_key, &tmp_len);
4848 pk = silc_buffer_alloc(4 + tmp_len);
4849 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
4850 silc_buffer_format(pk,
4851 SILC_STR_UI_SHORT(tmp_len),
4852 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
4853 SILC_STR_UI_XNSTRING(tmp, tmp_len),
4857 } else if (id_type == SILC_ID_SERVER) {
4858 server_id = silc_id_payload_get_id(idp);
4860 /* If the server is not found from local list there is no chance it
4861 would be locally connected server so send the command further. */
4862 server_entry = silc_idlist_find_server_by_id(server->local_list,
4865 if ((!server_entry && !cmd->pending && !server->standalone) ||
4866 (server_entry && !server_entry->connection)) {
4870 old_ident = silc_command_get_ident(cmd->payload);
4871 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
4872 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4874 silc_server_packet_send(server, server->router->connection,
4875 SILC_PACKET_COMMAND, cmd->packet->flags,
4876 tmpbuf->data, tmpbuf->len, TRUE);
4878 /* Reprocess this packet after received reply from router */
4879 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
4880 silc_command_get_ident(cmd->payload),
4881 silc_server_command_destructor,
4882 silc_server_command_getkey,
4883 silc_server_command_dup(cmd));
4884 cmd->pending = TRUE;
4886 silc_command_set_ident(cmd->payload, old_ident);
4887 silc_buffer_free(tmpbuf);
4891 if (!server_entry && cmd->pending) {
4892 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4893 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
4897 /* The client is locally connected, just get the public key and
4899 tmp = silc_pkcs_public_key_encode(server_entry->data.public_key, &tmp_len);
4900 pk = silc_buffer_alloc(4 + tmp_len);
4901 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
4902 silc_buffer_format(pk,
4903 SILC_STR_UI_SHORT(tmp_len),
4904 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
4905 SILC_STR_UI_XNSTRING(tmp, tmp_len),
4912 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4913 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
4914 SILC_STATUS_OK, ident, 2,
4916 3, pk->data, pk->len);
4917 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4918 packet->data, packet->len, FALSE);
4919 silc_buffer_free(packet);
4920 silc_buffer_free(pk);
4924 silc_id_payload_free(idp);
4925 silc_free(client_id);
4926 silc_free(server_id);
4927 silc_server_command_free(cmd);