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_payload_free(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[256], uh[256];
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_hash_table_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_hash_table_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 the client is on channel and has rights to change topic */
2054 if (!silc_hash_table_find(channel->user_list, client, NULL,
2056 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2057 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2061 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2062 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2063 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2064 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2069 /* Set the topic for channel */
2071 silc_free(channel->topic);
2072 channel->topic = strdup(tmp);
2074 /* Send TOPIC_SET notify type to the network */
2075 if (!server->standalone)
2076 silc_server_send_notify_topic_set(server, server->router->connection,
2077 server->server_type == SILC_ROUTER ?
2078 TRUE : FALSE, channel, client->id,
2081 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2083 /* Send notify about topic change to all clients on the channel */
2084 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2085 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2086 idp->data, idp->len,
2087 channel->topic, strlen(channel->topic));
2088 silc_buffer_free(idp);
2091 /* Send the topic to client as reply packet */
2092 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2094 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2095 SILC_STATUS_OK, ident, 2,
2096 2, idp->data, idp->len,
2098 strlen(channel->topic));
2100 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2101 SILC_STATUS_OK, ident, 1,
2102 2, idp->data, idp->len);
2103 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2104 0, packet->data, packet->len, FALSE);
2106 silc_buffer_free(packet);
2107 silc_buffer_free(idp);
2108 silc_free(channel_id);
2111 silc_server_command_free(cmd);
2114 /* Server side of INVITE command. Invites some client to join some channel.
2115 This command is also used to manage the invite list of the channel. */
2117 SILC_SERVER_CMD_FUNC(invite)
2119 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2120 SilcServer server = cmd->server;
2121 SilcSocketConnection sock = cmd->sock, dest_sock;
2122 SilcChannelClientEntry chl;
2123 SilcClientEntry sender, dest;
2124 SilcClientID *dest_id = NULL;
2125 SilcChannelEntry channel;
2126 SilcChannelID *channel_id = NULL;
2127 SilcIDListData idata;
2128 SilcBuffer idp, idp2, packet;
2129 unsigned char *tmp, *add, *del;
2131 uint16 ident = silc_command_get_ident(cmd->payload);
2133 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 4);
2135 /* Get Channel ID */
2136 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2138 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2139 SILC_STATUS_ERR_NO_CHANNEL_ID);
2142 channel_id = silc_id_payload_parse_id(tmp, len);
2144 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2145 SILC_STATUS_ERR_NO_CHANNEL_ID);
2149 /* Get the channel entry */
2150 channel = silc_idlist_find_channel_by_id(server->local_list,
2153 channel = silc_idlist_find_channel_by_id(server->global_list,
2156 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2157 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2162 /* Check whether the sender of this command is on the channel. */
2163 sender = (SilcClientEntry)sock->user_data;
2164 if (!silc_server_client_on_channel(sender, channel)) {
2165 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2166 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2170 /* Check whether the channel is invite-only channel. If yes then the
2171 sender of this command must be at least channel operator. */
2172 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2173 silc_hash_table_find(channel->user_list, sender, NULL, (void *)&chl);
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);
2181 /* Get destination client ID */
2182 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2186 dest_id = silc_id_payload_parse_id(tmp, len);
2188 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2189 SILC_STATUS_ERR_NO_CLIENT_ID);
2193 /* Get the client entry */
2194 dest = silc_server_get_client_resolve(server, dest_id);
2196 if (server->server_type == SILC_ROUTER) {
2197 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2198 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2202 /* The client info is being resolved. Reprocess this packet after
2203 receiving the reply to the query. */
2204 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2206 silc_server_command_destructor,
2207 silc_server_command_invite,
2208 silc_server_command_dup(cmd));
2209 cmd->pending = TRUE;
2210 silc_free(channel_id);
2215 /* Check whether the requested client is already on the channel. */
2216 if (silc_server_client_on_channel(dest, channel)) {
2217 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2218 SILC_STATUS_ERR_USER_ON_CHANNEL);
2222 /* Get route to the client */
2223 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2225 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2226 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2230 memset(invite, 0, sizeof(invite));
2231 strncat(invite, dest->nickname, strlen(dest->nickname));
2232 strncat(invite, "!", 1);
2233 strncat(invite, dest->username, strlen(dest->username));
2234 if (!strchr(dest->username, '@')) {
2235 strncat(invite, "@", 1);
2236 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2239 len = strlen(invite);
2240 if (!channel->invite_list)
2241 channel->invite_list = silc_calloc(len + 2,
2242 sizeof(*channel->invite_list));
2244 channel->invite_list = silc_realloc(channel->invite_list,
2245 sizeof(*channel->invite_list) *
2247 strlen(channel->invite_list) + 2));
2248 strncat(channel->invite_list, invite, len);
2249 strncat(channel->invite_list, ",", 1);
2251 /* Send notify to the client that is invited to the channel */
2252 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2253 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2254 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2256 SILC_NOTIFY_TYPE_INVITE, 3,
2257 idp->data, idp->len,
2258 channel->channel_name,
2259 strlen(channel->channel_name),
2260 idp2->data, idp2->len);
2261 silc_buffer_free(idp);
2262 silc_buffer_free(idp2);
2265 /* Add the client to the invite list of the channel */
2266 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2268 if (!channel->invite_list)
2269 channel->invite_list = silc_calloc(len + 2,
2270 sizeof(*channel->invite_list));
2272 channel->invite_list = silc_realloc(channel->invite_list,
2273 sizeof(*channel->invite_list) *
2275 strlen(channel->invite_list) + 2));
2276 if (add[len - 1] == ',')
2277 add[len - 1] = '\0';
2279 strncat(channel->invite_list, add, len);
2280 strncat(channel->invite_list, ",", 1);
2283 /* Get the invite to be removed and remove it from the list */
2284 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2285 if (del && channel->invite_list) {
2286 char *start, *end, *n;
2288 if (!strncmp(channel->invite_list, del,
2289 strlen(channel->invite_list) - 1)) {
2290 silc_free(channel->invite_list);
2291 channel->invite_list = NULL;
2293 start = strstr(channel->invite_list, del);
2294 if (start && strlen(start) >= len) {
2296 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2297 strncat(n, channel->invite_list, start - channel->invite_list);
2298 strncat(n, end + 1, ((channel->invite_list +
2299 strlen(channel->invite_list)) - end) - 1);
2300 silc_free(channel->invite_list);
2301 channel->invite_list = n;
2306 /* Send notify to the primary router */
2307 if (!server->standalone)
2308 silc_server_send_notify_invite(server, server->router->connection,
2309 server->server_type == SILC_ROUTER ?
2310 TRUE : FALSE, channel,
2311 sender->id, add, del);
2313 /* Send command reply */
2314 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2318 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2319 SILC_STATUS_OK, ident, 2,
2321 3, channel->invite_list,
2322 channel->invite_list ?
2323 strlen(channel->invite_list) : 0);
2326 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2327 SILC_STATUS_OK, ident, 1,
2329 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2330 packet->data, packet->len, FALSE);
2331 silc_buffer_free(packet);
2337 silc_free(channel_id);
2338 silc_server_command_free(cmd);
2343 SilcSocketConnection sock;
2347 /* Quits connection to client. This gets called if client won't
2348 close the connection even when it has issued QUIT command. */
2350 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2352 QuitInternal q = (QuitInternal)context;
2354 /* Free all client specific data, such as client entry and entires
2355 on channels this client may be on. */
2356 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2358 q->sock->user_data = NULL;
2360 /* Close the connection on our side */
2361 silc_server_close_connection(q->server, q->sock);
2363 silc_free(q->signoff);
2367 /* Quits SILC session. This is the normal way to disconnect client. */
2369 SILC_SERVER_CMD_FUNC(quit)
2371 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2372 SilcServer server = cmd->server;
2373 SilcSocketConnection sock = cmd->sock;
2375 unsigned char *tmp = NULL;
2378 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_QUIT, cmd, 0, 1);
2380 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2383 /* Get destination ID */
2384 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2388 q = silc_calloc(1, sizeof(*q));
2391 q->signoff = tmp ? strdup(tmp) : NULL;
2393 /* We quit the connection with little timeout */
2394 silc_task_register(server->timeout_queue, sock->sock,
2395 silc_server_command_quit_cb, (void *)q,
2396 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2399 silc_server_command_free(cmd);
2402 /* Server side of command KILL. This command is used by router operator
2403 to remove an client from the SILC Network temporarily. */
2405 SILC_SERVER_CMD_FUNC(kill)
2407 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2408 SilcServer server = cmd->server;
2409 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2410 SilcClientEntry remote_client;
2411 SilcClientID *client_id;
2412 unsigned char *tmp, *comment;
2413 uint32 tmp_len, tmp_len2;
2415 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_KILL, cmd, 1, 2);
2417 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2420 /* KILL command works only on router */
2421 if (server->server_type != SILC_ROUTER) {
2422 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2423 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2427 /* Check whether client has the permissions. */
2428 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2429 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2430 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2434 /* Get the client ID */
2435 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2437 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2438 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2441 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2443 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2444 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2448 /* Get the client entry */
2449 remote_client = silc_idlist_find_client_by_id(server->local_list,
2451 if (!remote_client) {
2452 remote_client = silc_idlist_find_client_by_id(server->global_list,
2454 if (!remote_client) {
2455 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2456 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2461 if (remote_client->data.registered == FALSE) {
2462 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2463 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2468 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2472 /* Send reply to the sender */
2473 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2476 /* Send the KILL notify packets. First send it to the channel, then
2477 to our primary router and then directly to the client who is being
2478 killed right now. */
2480 /* Send KILLED notify to the channels. It is not sent to the client
2481 as it will be sent differently destined directly to the client and not
2483 silc_server_send_notify_on_channels(server, remote_client,
2484 remote_client, SILC_NOTIFY_TYPE_KILLED,
2487 comment, comment ? tmp_len2 : 0);
2489 /* Send KILLED notify to primary route */
2490 if (!server->standalone)
2491 silc_server_send_notify_killed(server, server->router->connection, TRUE,
2492 remote_client->id, comment);
2494 /* Send KILLED notify to the client directly */
2495 silc_server_send_notify_killed(server, remote_client->connection ?
2496 remote_client->connection :
2497 remote_client->router->connection, FALSE,
2498 remote_client->id, comment);
2500 /* Remove the client from all channels. This generates new keys to the
2501 channels as well. */
2502 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2505 /* Remove the client entry, If it is locally connected then we will also
2506 disconnect the client here */
2507 if (remote_client->data.registered && remote_client->connection) {
2508 /* Remove locally conneted client */
2509 SilcSocketConnection sock = remote_client->connection;
2510 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2511 silc_server_close_connection(server, sock);
2513 /* Remove remote client */
2514 if (!silc_idlist_del_client(server->global_list, remote_client))
2515 silc_idlist_del_client(server->local_list, remote_client);
2519 silc_server_command_free(cmd);
2522 /* Server side of command INFO. This sends information about us to
2523 the client. If client requested specific server we will send the
2524 command to that server. */
2526 SILC_SERVER_CMD_FUNC(info)
2528 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2529 SilcServer server = cmd->server;
2530 SilcBuffer packet, idp;
2533 char *dest_server, *server_info = NULL, *server_name;
2534 uint16 ident = silc_command_get_ident(cmd->payload);
2535 SilcServerEntry entry = NULL;
2536 SilcServerID *server_id = NULL;
2538 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 0, 2);
2540 /* Get server name */
2541 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2544 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2546 server_id = silc_id_payload_parse_id(tmp, tmp_len);
2548 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2549 SILC_STATUS_ERR_NO_SERVER_ID);
2555 /* Check whether we have this server cached */
2556 entry = silc_idlist_find_server_by_id(server->local_list,
2559 entry = silc_idlist_find_server_by_id(server->global_list,
2561 if (!entry && server->server_type == SILC_ROUTER) {
2562 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2563 SILC_STATUS_ERR_NO_SUCH_SERVER);
2569 if ((!dest_server && !server_id) ||
2570 (dest_server && !cmd->pending &&
2571 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2572 /* Send our reply */
2573 char info_string[256];
2575 memset(info_string, 0, sizeof(info_string));
2576 snprintf(info_string, sizeof(info_string),
2577 "location: %s server: %s admin: %s <%s>",
2578 server->config->admin_info->location,
2579 server->config->admin_info->server_type,
2580 server->config->admin_info->admin_name,
2581 server->config->admin_info->admin_email);
2583 server_info = info_string;
2584 entry = server->id_entry;
2586 /* Check whether we have this server cached */
2587 if (!entry && dest_server) {
2588 entry = silc_idlist_find_server_by_name(server->global_list,
2591 entry = silc_idlist_find_server_by_name(server->local_list,
2596 if (!cmd->pending &&
2597 server->server_type == SILC_ROUTER && entry && !entry->server_info) {
2598 /* Send to the server */
2602 old_ident = silc_command_get_ident(cmd->payload);
2603 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2604 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2606 silc_server_packet_send(server, entry->connection,
2607 SILC_PACKET_COMMAND, cmd->packet->flags,
2608 tmpbuf->data, tmpbuf->len, TRUE);
2610 /* Reprocess this packet after received reply from router */
2611 silc_server_command_pending(server, SILC_COMMAND_INFO,
2612 silc_command_get_ident(cmd->payload),
2613 silc_server_command_destructor,
2614 silc_server_command_info,
2615 silc_server_command_dup(cmd));
2616 cmd->pending = TRUE;
2617 silc_command_set_ident(cmd->payload, old_ident);
2618 silc_buffer_free(tmpbuf);
2622 if (!entry && !cmd->pending && !server->standalone) {
2623 /* Send to the primary router */
2627 old_ident = silc_command_get_ident(cmd->payload);
2628 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2629 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2631 silc_server_packet_send(server, server->router->connection,
2632 SILC_PACKET_COMMAND, cmd->packet->flags,
2633 tmpbuf->data, tmpbuf->len, TRUE);
2635 /* Reprocess this packet after received reply from router */
2636 silc_server_command_pending(server, SILC_COMMAND_INFO,
2637 silc_command_get_ident(cmd->payload),
2638 silc_server_command_destructor,
2639 silc_server_command_info,
2640 silc_server_command_dup(cmd));
2641 cmd->pending = TRUE;
2642 silc_command_set_ident(cmd->payload, old_ident);
2643 silc_buffer_free(tmpbuf);
2649 silc_free(server_id);
2652 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2653 SILC_STATUS_ERR_NO_SUCH_SERVER);
2657 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2659 server_info = entry->server_info;
2660 server_name = entry->server_name;
2662 /* Send the reply */
2664 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2665 SILC_STATUS_OK, ident, 3,
2666 2, idp->data, idp->len,
2668 strlen(server_name),
2670 strlen(server_info));
2672 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2673 SILC_STATUS_OK, ident, 2,
2674 2, idp->data, idp->len,
2676 strlen(server_name));
2677 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2678 packet->data, packet->len, FALSE);
2680 silc_buffer_free(packet);
2681 silc_buffer_free(idp);
2684 silc_server_command_free(cmd);
2687 /* Server side of command PING. This just replies to the ping. */
2689 SILC_SERVER_CMD_FUNC(ping)
2691 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2692 SilcServer server = cmd->server;
2697 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
2700 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2702 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2703 SILC_STATUS_ERR_NO_SERVER_ID);
2706 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2710 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2711 /* Send our reply */
2712 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2715 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2716 SILC_STATUS_ERR_NO_SUCH_SERVER);
2723 silc_server_command_free(cmd);
2726 /* Internal routine to join channel. The channel sent to this function
2727 has been either created or resolved from ID lists. This joins the sent
2728 client to the channel. */
2730 static void silc_server_command_join_channel(SilcServer server,
2731 SilcServerCommandContext cmd,
2732 SilcChannelEntry channel,
2733 SilcClientID *client_id,
2737 SilcSocketConnection sock = cmd->sock;
2739 uint32 tmp_len, user_count;
2740 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
2741 SilcClientEntry client;
2742 SilcChannelClientEntry chl;
2743 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
2744 uint16 ident = silc_command_get_ident(cmd->payload);
2747 SILC_LOG_DEBUG(("Start"));
2752 /* Get the client entry */
2753 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2754 client = (SilcClientEntry)sock->user_data;
2756 client = silc_idlist_find_client_by_id(server->local_list, client_id,
2763 * Check channel modes
2766 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2767 strncat(check, client->nickname, strlen(client->nickname));
2768 if (!strchr(client->nickname, '@')) {
2769 strncat(check, "@", 1);
2770 strncat(check, server->server_name, strlen(server->server_name));
2772 strncat(check, "!", 1);
2773 strncat(check, client->username, strlen(client->username));
2774 if (!strchr(client->username, '@')) {
2775 strncat(check, "@", 1);
2776 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
2780 /* Check invite list if channel is invite-only channel */
2781 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
2782 channel->mode & SILC_CHANNEL_MODE_INVITE) {
2783 if (!channel->invite_list ||
2784 !silc_string_match(channel->invite_list, check)) {
2785 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2786 SILC_STATUS_ERR_NOT_INVITED);
2791 /* Check ban list if it exists. If the client's nickname, server,
2792 username and/or hostname is in the ban list the access to the
2793 channel is denied. */
2794 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && channel->ban_list) {
2795 if (silc_string_match(channel->ban_list, check)) {
2796 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2797 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
2802 /* Get passphrase */
2803 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2805 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
2806 memcpy(passphrase, tmp, tmp_len);
2809 /* Check the channel passphrase if set. */
2810 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2811 if (!passphrase || memcmp(channel->passphrase, passphrase,
2812 strlen(channel->passphrase))) {
2813 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2814 SILC_STATUS_ERR_BAD_PASSWORD);
2819 /* Check user count limit if set. */
2820 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
2821 if (silc_hash_table_count(channel->user_list) + 1 >
2822 channel->user_limit) {
2823 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2824 SILC_STATUS_ERR_CHANNEL_IS_FULL);
2830 * Client is allowed to join to the channel. Make it happen.
2833 /* Check whether the client already is on the channel */
2834 if (silc_server_client_on_channel(client, channel)) {
2835 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2836 SILC_STATUS_ERR_USER_ON_CHANNEL);
2840 /* Generate new channel key as protocol dictates */
2841 if ((!created && silc_hash_table_count(channel->user_list) > 0) ||
2842 !channel->channel_key)
2843 silc_server_create_channel_key(server, channel, 0);
2845 /* Send the channel key. This is broadcasted to the channel but is not
2846 sent to the client who is joining to the channel. */
2847 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
2848 silc_server_send_channel_key(server, NULL, channel,
2849 server->server_type == SILC_ROUTER ?
2850 FALSE : !server->standalone);
2852 /* Join the client to the channel by adding it to channel's user list.
2853 Add also the channel to client entry's channels list for fast cross-
2855 chl = silc_calloc(1, sizeof(*chl));
2857 chl->client = client;
2858 chl->channel = channel;
2859 silc_hash_table_add(channel->user_list, client, chl);
2860 silc_hash_table_add(client->channels, channel, chl);
2862 /* Get users on the channel */
2863 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
2866 /* Encode Client ID Payload of the original client who wants to join */
2867 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2869 /* Encode command reply packet */
2870 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2871 SILC_PUT32_MSB(channel->mode, mode);
2872 SILC_PUT32_MSB(created, tmp2);
2873 SILC_PUT32_MSB(user_count, tmp3);
2875 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
2876 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
2877 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
2878 strlen(channel->channel_key->
2880 channel->channel_key->cipher->name,
2881 channel->key_len / 8, channel->key);
2886 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2887 SILC_STATUS_OK, ident, 13,
2888 2, channel->channel_name,
2889 strlen(channel->channel_name),
2890 3, chidp->data, chidp->len,
2891 4, clidp->data, clidp->len,
2894 7, keyp ? keyp->data : NULL,
2895 keyp ? keyp->len : 0,
2896 8, channel->ban_list,
2898 strlen(channel->ban_list) : 0,
2899 9, channel->invite_list,
2900 channel->invite_list ?
2901 strlen(channel->invite_list) : 0,
2904 strlen(channel->topic) : 0,
2905 11, channel->hmac->hmac->name,
2906 strlen(channel->hmac->hmac->name),
2908 13, user_list->data, user_list->len,
2909 14, mode_list->data,
2912 /* Send command reply */
2913 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
2914 reply->data, reply->len, FALSE);
2916 if (!cmd->pending) {
2917 /* Send JOIN notify to locally connected clients on the channel */
2918 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2919 SILC_NOTIFY_TYPE_JOIN, 2,
2920 clidp->data, clidp->len,
2921 chidp->data, chidp->len);
2923 /* Send JOIN notify packet to our primary router */
2924 if (!server->standalone)
2925 silc_server_send_notify_join(server, server->router->connection,
2926 server->server_type == SILC_ROUTER ?
2927 TRUE : FALSE, channel, client->id);
2930 silc_buffer_free(reply);
2931 silc_buffer_free(clidp);
2932 silc_buffer_free(chidp);
2933 silc_buffer_free(keyp);
2934 silc_buffer_free(user_list);
2935 silc_buffer_free(mode_list);
2939 silc_free(passphrase);
2942 /* Server side of command JOIN. Joins client into requested channel. If
2943 the channel does not exist it will be created. */
2945 SILC_SERVER_CMD_FUNC(join)
2947 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2948 SilcServer server = cmd->server;
2950 char *tmp, *channel_name = NULL, *cipher, *hmac;
2951 SilcChannelEntry channel;
2953 int created = FALSE;
2954 SilcClientID *client_id;
2956 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
2958 /* Get channel name */
2959 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2961 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2962 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2967 if (strlen(channel_name) > 256)
2968 channel_name[255] = '\0';
2970 if (silc_server_command_bad_chars(channel_name) == TRUE) {
2971 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2972 SILC_STATUS_ERR_BAD_CHANNEL);
2973 silc_free(channel_name);
2977 /* Get Client ID of the client who is joining to the channel */
2978 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2980 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2981 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2984 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2986 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2987 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2991 /* Get cipher and hmac name */
2992 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2993 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2995 /* See if the channel exists */
2996 channel = silc_idlist_find_channel_by_name(server->local_list,
2997 channel_name, NULL);
2999 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3000 /* If this is coming from client the Client ID in the command packet must
3001 be same as the client's ID. */
3002 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3003 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3004 if (!SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
3005 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3006 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3011 if (!channel || !channel->id) {
3012 /* Channel not found */
3014 /* If we are standalone server we don't have a router, we just create
3015 the channel by ourselves. */
3016 if (server->standalone) {
3017 channel = silc_server_create_new_channel(server, server->id, cipher,
3018 hmac, channel_name, TRUE);
3020 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3021 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3025 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3030 /* The channel does not exist on our server. If we are normal server
3031 we will send JOIN command to our router which will handle the
3032 joining procedure (either creates the channel if it doesn't exist
3033 or joins the client to it). */
3034 if (server->server_type == SILC_SERVER) {
3038 old_ident = silc_command_get_ident(cmd->payload);
3039 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3040 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3042 /* Send JOIN command to our router */
3043 silc_server_packet_send(server, (SilcSocketConnection)
3044 server->router->connection,
3045 SILC_PACKET_COMMAND, cmd->packet->flags,
3046 tmpbuf->data, tmpbuf->len, TRUE);
3048 /* Reprocess this packet after received reply from router */
3049 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3050 silc_command_get_ident(cmd->payload),
3051 silc_server_command_destructor,
3052 silc_server_command_join,
3053 silc_server_command_dup(cmd));
3054 cmd->pending = TRUE;
3058 /* We are router and the channel does not seem exist so we will check
3059 our global list as well for the channel. */
3060 channel = silc_idlist_find_channel_by_name(server->global_list,
3061 channel_name, NULL);
3063 /* Channel really does not exist, create it */
3064 channel = silc_server_create_new_channel(server, server->id, cipher,
3065 hmac, channel_name, TRUE);
3067 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3068 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3072 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3079 /* Channel not found */
3081 /* If the command came from router and/or we are normal server then
3082 something went wrong with the joining as the channel was not found.
3083 We can't do anything else but ignore this. */
3084 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3085 server->server_type == SILC_SERVER)
3088 /* We are router and the channel does not seem exist so we will check
3089 our global list as well for the channel. */
3090 channel = silc_idlist_find_channel_by_name(server->global_list,
3091 channel_name, NULL);
3093 /* Channel really does not exist, create it */
3094 channel = silc_server_create_new_channel(server, server->id, cipher,
3095 hmac, channel_name, TRUE);
3097 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3098 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3102 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3108 /* If the channel does not have global users and is also empty it means the
3109 channel was created globally (by our router) and the client will be the
3110 channel founder and operator. */
3111 if (!channel->global_users && !silc_hash_table_count(channel->user_list)) {
3112 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3113 created = TRUE; /* Created globally by our router */
3116 /* Join to the channel */
3117 silc_server_command_join_channel(server, cmd, channel, client_id,
3120 silc_free(client_id);
3123 silc_server_command_free(cmd);
3126 /* Server side of command MOTD. Sends server's current "message of the
3127 day" to the client. */
3129 SILC_SERVER_CMD_FUNC(motd)
3131 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3132 SilcServer server = cmd->server;
3133 SilcBuffer packet, idp;
3134 char *motd, *dest_server;
3136 uint16 ident = silc_command_get_ident(cmd->payload);
3138 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 1);
3140 /* Get server name */
3141 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3143 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3144 SILC_STATUS_ERR_NO_SUCH_SERVER);
3148 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3151 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3153 if (server->config && server->config->motd &&
3154 server->config->motd->motd_file) {
3156 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
3161 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3162 SILC_STATUS_OK, ident, 2,
3168 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3169 SILC_STATUS_OK, ident, 1,
3173 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3174 packet->data, packet->len, FALSE);
3175 silc_buffer_free(packet);
3176 silc_buffer_free(idp);
3178 SilcServerEntry entry;
3180 /* Check whether we have this server cached */
3181 entry = silc_idlist_find_server_by_name(server->global_list,
3184 entry = silc_idlist_find_server_by_name(server->local_list,
3188 if (server->server_type == SILC_ROUTER && !cmd->pending &&
3189 entry && !entry->motd) {
3190 /* Send to the server */
3194 old_ident = silc_command_get_ident(cmd->payload);
3195 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3196 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3198 silc_server_packet_send(server, entry->connection,
3199 SILC_PACKET_COMMAND, cmd->packet->flags,
3200 tmpbuf->data, tmpbuf->len, TRUE);
3202 /* Reprocess this packet after received reply from router */
3203 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3204 silc_command_get_ident(cmd->payload),
3205 silc_server_command_destructor,
3206 silc_server_command_motd,
3207 silc_server_command_dup(cmd));
3208 cmd->pending = TRUE;
3209 silc_command_set_ident(cmd->payload, old_ident);
3210 silc_buffer_free(tmpbuf);
3214 if (!entry && !cmd->pending && !server->standalone) {
3215 /* Send to the primary router */
3219 old_ident = silc_command_get_ident(cmd->payload);
3220 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3221 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3223 silc_server_packet_send(server, server->router->connection,
3224 SILC_PACKET_COMMAND, cmd->packet->flags,
3225 tmpbuf->data, tmpbuf->len, TRUE);
3227 /* Reprocess this packet after received reply from router */
3228 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3229 silc_command_get_ident(cmd->payload),
3230 silc_server_command_destructor,
3231 silc_server_command_motd,
3232 silc_server_command_dup(cmd));
3233 cmd->pending = TRUE;
3234 silc_command_set_ident(cmd->payload, old_ident);
3235 silc_buffer_free(tmpbuf);
3240 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3241 SILC_STATUS_ERR_NO_SUCH_SERVER);
3245 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3248 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3249 SILC_STATUS_OK, ident, 2,
3252 strlen(entry->motd));
3254 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3255 SILC_STATUS_OK, ident, 1,
3258 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3259 packet->data, packet->len, FALSE);
3260 silc_buffer_free(packet);
3261 silc_buffer_free(idp);
3265 silc_server_command_free(cmd);
3268 /* Server side of command UMODE. Client can use this command to set/unset
3269 user mode. Client actually cannot set itself to be as server/router
3270 operator so this can be used only to unset the modes. */
3272 SILC_SERVER_CMD_FUNC(umode)
3274 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3275 SilcServer server = cmd->server;
3276 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3278 unsigned char *tmp_mask;
3280 uint16 ident = silc_command_get_ident(cmd->payload);
3282 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3285 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_UMODE, cmd, 2, 2);
3287 /* Get the client's mode mask */
3288 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3290 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3291 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3294 SILC_GET32_MSB(mask, tmp_mask);
3300 if (mask & SILC_UMODE_SERVER_OPERATOR) {
3301 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR)) {
3302 /* Cannot operator mode */
3303 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3304 SILC_STATUS_ERR_PERM_DENIED);
3308 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
3309 /* Remove the server operator rights */
3310 client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3313 if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3314 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
3315 /* Cannot operator mode */
3316 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3317 SILC_STATUS_ERR_PERM_DENIED);
3321 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
3322 /* Remove the router operator rights */
3323 client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3326 if (mask & SILC_UMODE_GONE) {
3327 client->mode |= SILC_UMODE_GONE;
3329 if (client->mode & SILC_UMODE_GONE)
3330 /* Remove the gone status */
3331 client->mode &= ~SILC_UMODE_GONE;
3334 /* Send UMODE change to primary router */
3335 if (!server->standalone)
3336 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3337 client->id, client->mode);
3339 /* Send command reply to sender */
3340 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3341 SILC_STATUS_OK, ident, 1,
3343 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3344 packet->data, packet->len, FALSE);
3345 silc_buffer_free(packet);
3348 silc_server_command_free(cmd);
3351 /* Checks that client has rights to add or remove channel modes. If any
3352 of the checks fails FALSE is returned. */
3354 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3355 SilcChannelClientEntry client,
3358 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3359 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3361 /* Check whether has rights to change anything */
3362 if (!is_op && !is_fo)
3365 /* Check whether has rights to change everything */
3369 /* We know that client is channel operator, check that they are not
3370 changing anything that requires channel founder rights. Rest of the
3371 modes are available automatically for channel operator. */
3373 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3374 if (is_op && !is_fo)
3377 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3378 if (is_op && !is_fo)
3383 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3384 if (is_op && !is_fo)
3387 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3388 if (is_op && !is_fo)
3393 if (mode & SILC_CHANNEL_MODE_CIPHER) {
3394 if (is_op && !is_fo)
3397 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3398 if (is_op && !is_fo)
3403 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3404 if (is_op && !is_fo)
3407 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3408 if (is_op && !is_fo)
3416 /* Server side command of CMODE. Changes channel mode */
3418 SILC_SERVER_CMD_FUNC(cmode)
3420 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3421 SilcServer server = cmd->server;
3422 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3423 SilcIDListData idata = (SilcIDListData)client;
3424 SilcChannelID *channel_id;
3425 SilcChannelEntry channel;
3426 SilcChannelClientEntry chl;
3427 SilcBuffer packet, cidp;
3428 unsigned char *tmp, *tmp_id, *tmp_mask;
3429 char *cipher = NULL, *hmac = NULL;
3430 uint32 mode_mask, tmp_len, tmp_len2;
3431 uint16 ident = silc_command_get_ident(cmd->payload);
3433 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CMODE, cmd, 2, 7);
3435 /* Get Channel ID */
3436 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3438 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3439 SILC_STATUS_ERR_NO_CHANNEL_ID);
3442 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3444 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3445 SILC_STATUS_ERR_NO_CHANNEL_ID);
3449 /* Get the channel mode mask */
3450 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3452 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3453 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3456 SILC_GET32_MSB(mode_mask, tmp_mask);
3458 /* Get channel entry */
3459 channel = silc_idlist_find_channel_by_id(server->local_list,
3462 channel = silc_idlist_find_channel_by_id(server->global_list,
3465 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3466 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3471 /* Check whether this client is on the channel */
3472 if (!silc_server_client_on_channel(client, channel)) {
3473 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3474 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3478 /* Get entry to the channel user list */
3479 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
3481 /* Check that client has rights to change any requested channel modes */
3482 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3483 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3484 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3489 * Check the modes. Modes that requires nothing special operation are
3493 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3494 /* Channel uses private keys to protect traffic. Client(s) has set the
3495 key locally they want to use, server does not know that key. */
3496 /* Nothing interesting to do here */
3498 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3499 /* The mode is removed and we need to generate and distribute
3500 new channel key. Clients are not using private channel keys
3501 anymore after this. */
3503 /* Re-generate channel key */
3504 silc_server_create_channel_key(server, channel, 0);
3506 /* Send the channel key. This sends it to our local clients and if
3507 we are normal server to our router as well. */
3508 silc_server_send_channel_key(server, NULL, channel,
3509 server->server_type == SILC_ROUTER ?
3510 FALSE : !server->standalone);
3512 cipher = channel->channel_key->cipher->name;
3513 hmac = channel->hmac->hmac->name;
3517 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3518 /* User limit is set on channel */
3521 /* Get user limit */
3522 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3524 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3525 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3526 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3530 SILC_GET32_MSB(user_limit, tmp);
3531 channel->user_limit = user_limit;
3534 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3535 /* User limit mode is unset. Remove user limit */
3536 channel->user_limit = 0;
3539 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3540 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3541 /* Passphrase has been set to channel */
3543 /* Get the passphrase */
3544 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3546 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3547 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3551 /* Save the passphrase */
3552 channel->passphrase = strdup(tmp);
3555 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3556 /* Passphrase mode is unset. remove the passphrase */
3557 if (channel->passphrase) {
3558 silc_free(channel->passphrase);
3559 channel->passphrase = NULL;
3564 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3565 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3566 /* Cipher to use protect the traffic */
3569 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3571 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3572 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3576 /* Delete old cipher and allocate the new one */
3577 silc_cipher_free(channel->channel_key);
3578 if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
3579 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3580 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3584 /* Re-generate channel key */
3585 silc_server_create_channel_key(server, channel, 0);
3587 /* Send the channel key. This sends it to our local clients and if
3588 we are normal server to our router as well. */
3589 silc_server_send_channel_key(server, NULL, channel,
3590 server->server_type == SILC_ROUTER ?
3591 FALSE : !server->standalone);
3594 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3595 /* Cipher mode is unset. Remove the cipher and revert back to
3597 cipher = channel->cipher;
3599 /* Delete old cipher and allocate default one */
3600 silc_cipher_free(channel->channel_key);
3601 if (!silc_cipher_alloc(cipher ? cipher : "aes-256-cbc",
3602 &channel->channel_key)) {
3603 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3604 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3608 /* Re-generate channel key */
3609 silc_server_create_channel_key(server, channel, 0);
3611 /* Send the channel key. This sends it to our local clients and if
3612 we are normal server to our router as well. */
3613 silc_server_send_channel_key(server, NULL, channel,
3614 server->server_type == SILC_ROUTER ?
3615 FALSE : !server->standalone);
3619 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3620 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3621 /* HMAC to use protect the traffic */
3622 unsigned char hash[32];
3625 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3627 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3628 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3632 /* Delete old hmac and allocate the new one */
3633 silc_hmac_free(channel->hmac);
3634 if (!silc_hmac_alloc(hmac, NULL, &channel->hmac)) {
3635 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3636 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3640 /* Set the HMAC key out of current channel key. The client must do
3642 silc_hash_make(channel->hmac->hash, channel->key, channel->key_len / 8,
3644 silc_hmac_set_key(channel->hmac, hash,
3645 silc_hash_len(channel->hmac->hash));
3646 memset(hash, 0, sizeof(hash));
3649 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
3650 /* Hmac mode is unset. Remove the hmac and revert back to
3652 unsigned char hash[32];
3653 hmac = channel->hmac_name;
3655 /* Delete old hmac and allocate default one */
3656 silc_hmac_free(channel->hmac);
3657 if (!silc_hmac_alloc(hmac ? hmac : "hmac-sha1-96", NULL,
3659 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3660 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3664 /* Set the HMAC key out of current channel key. The client must do
3666 silc_hash_make(channel->hmac->hash, channel->key, channel->key_len / 8,
3668 silc_hmac_set_key(channel->hmac, hash,
3669 silc_hash_len(channel->hmac->hash));
3670 memset(hash, 0, sizeof(hash));
3674 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3675 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3676 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
3677 /* Set the founder authentication */
3678 SilcAuthPayload auth;
3680 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
3682 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3683 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3687 auth = silc_auth_payload_parse(tmp, tmp_len);
3689 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3690 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3694 /* Save the public key */
3695 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
3696 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
3699 channel->founder_method = silc_auth_get_method(auth);
3701 if (channel->founder_method == SILC_AUTH_PASSWORD) {
3702 tmp = silc_auth_get_data(auth, &tmp_len);
3703 channel->founder_passwd =
3704 silc_calloc(tmp_len + 1, sizeof(*channel->founder_passwd));
3705 memcpy(channel->founder_passwd, tmp, tmp_len);
3706 channel->founder_passwd_len = tmp_len;
3709 silc_auth_payload_free(auth);
3713 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3714 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3715 if (channel->founder_key)
3716 silc_pkcs_public_key_free(channel->founder_key);
3717 if (channel->founder_passwd) {
3718 silc_free(channel->founder_passwd);
3719 channel->founder_passwd = NULL;
3725 /* Finally, set the mode */
3726 channel->mode = mode_mask;
3728 /* Send CMODE_CHANGE notify */
3729 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3730 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3731 SILC_NOTIFY_TYPE_CMODE_CHANGE, 4,
3732 cidp->data, cidp->len,
3734 cipher, cipher ? strlen(cipher) : 0,
3735 hmac, hmac ? strlen(hmac) : 0);
3737 /* Set CMODE notify type to network */
3738 if (!server->standalone)
3739 silc_server_send_notify_cmode(server, server->router->connection,
3740 server->server_type == SILC_ROUTER ?
3741 TRUE : FALSE, channel,
3742 mode_mask, client->id, SILC_ID_CLIENT,
3745 /* Send command reply to sender */
3746 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3747 SILC_STATUS_OK, ident, 1,
3749 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3750 packet->data, packet->len, FALSE);
3752 silc_buffer_free(packet);
3753 silc_free(channel_id);
3757 silc_server_command_free(cmd);
3760 /* Server side of CUMODE command. Changes client's mode on a channel. */
3762 SILC_SERVER_CMD_FUNC(cumode)
3764 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3765 SilcServer server = cmd->server;
3766 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3767 SilcIDListData idata = (SilcIDListData)client;
3768 SilcChannelID *channel_id;
3769 SilcClientID *client_id;
3770 SilcChannelEntry channel;
3771 SilcClientEntry target_client;
3772 SilcChannelClientEntry chl;
3773 SilcBuffer packet, idp;
3774 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
3775 uint32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
3777 uint16 ident = silc_command_get_ident(cmd->payload);
3779 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 4);
3781 /* Get Channel ID */
3782 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3784 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3785 SILC_STATUS_ERR_NO_CHANNEL_ID);
3788 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
3790 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3791 SILC_STATUS_ERR_NO_CHANNEL_ID);
3795 /* Get channel entry */
3796 channel = silc_idlist_find_channel_by_id(server->local_list,
3799 channel = silc_idlist_find_channel_by_id(server->global_list,
3802 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3803 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3808 /* Check whether sender is on the channel */
3809 if (!silc_server_client_on_channel(client, channel)) {
3810 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3811 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3815 /* Check that client has rights to change other's rights */
3816 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
3817 sender_mask = chl->mode;
3819 /* Get the target client's channel mode mask */
3820 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3822 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3823 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3826 SILC_GET32_MSB(target_mask, tmp_mask);
3828 /* Get target Client ID */
3829 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3831 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3832 SILC_STATUS_ERR_NO_CLIENT_ID);
3835 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
3837 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3838 SILC_STATUS_ERR_NO_CLIENT_ID);
3842 /* Get target client's entry */
3843 target_client = silc_idlist_find_client_by_id(server->local_list,
3845 if (!target_client) {
3846 target_client = silc_idlist_find_client_by_id(server->global_list,
3850 if (target_client != client &&
3851 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
3852 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
3853 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3854 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3858 /* Check whether target client is on the channel */
3859 if (target_client != client) {
3860 if (!silc_server_client_on_channel(target_client, channel)) {
3861 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3862 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
3866 /* Get entry to the channel user list */
3867 silc_hash_table_find(channel->user_list, target_client, NULL,
3875 /* If the target client is founder, no one else can change their mode
3877 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
3878 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3879 SILC_STATUS_ERR_NOT_YOU);
3883 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
3884 /* The client tries to claim the founder rights. */
3885 unsigned char *tmp_auth;
3886 uint32 tmp_auth_len, auth_len;
3889 if (target_client != client) {
3890 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3891 SILC_STATUS_ERR_NOT_YOU);
3895 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
3896 !channel->founder_key) {
3897 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3898 SILC_STATUS_ERR_NOT_YOU);
3902 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
3904 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3905 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3909 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
3910 (void *)channel->founder_passwd : (void *)channel->founder_key);
3911 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
3912 channel->founder_passwd_len : 0);
3914 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
3915 channel->founder_method, auth, auth_len,
3916 idata->hash, client->id, SILC_ID_CLIENT)) {
3917 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3918 SILC_STATUS_ERR_AUTH_FAILED);
3922 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
3925 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3926 if (target_client == client) {
3927 /* Remove channel founder rights from itself */
3928 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3931 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3932 SILC_STATUS_ERR_NOT_YOU);
3938 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
3939 /* Promote to operator */
3940 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3941 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3942 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3943 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3944 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3948 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
3952 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
3953 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3954 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3955 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3956 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3960 /* Demote to normal user */
3961 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
3966 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3967 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3969 /* Send notify to channel, notify only if mode was actually changed. */
3971 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3972 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3973 idp->data, idp->len,
3977 /* Set CUMODE notify type to network */
3978 if (!server->standalone)
3979 silc_server_send_notify_cumode(server, server->router->connection,
3980 server->server_type == SILC_ROUTER ?
3981 TRUE : FALSE, channel,
3982 target_mask, client->id,
3987 /* Send command reply to sender */
3988 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
3989 SILC_STATUS_OK, ident, 2,
3991 3, tmp_id, tmp_len);
3992 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3993 packet->data, packet->len, FALSE);
3995 silc_buffer_free(packet);
3996 silc_free(channel_id);
3997 silc_free(client_id);
3998 silc_buffer_free(idp);
4001 silc_server_command_free(cmd);
4004 /* Server side of KICK command. Kicks client out of channel. */
4006 SILC_SERVER_CMD_FUNC(kick)
4008 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4009 SilcServer server = cmd->server;
4010 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4011 SilcClientEntry target_client;
4012 SilcChannelID *channel_id;
4013 SilcClientID *client_id;
4014 SilcChannelEntry channel;
4015 SilcChannelClientEntry chl;
4018 unsigned char *tmp, *comment;
4020 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 3);
4022 /* Get Channel ID */
4023 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4025 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4026 SILC_STATUS_ERR_NO_CHANNEL_ID);
4029 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
4031 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4032 SILC_STATUS_ERR_NO_CHANNEL_ID);
4036 /* Get channel entry */
4037 channel = silc_idlist_find_channel_by_id(server->local_list,
4040 channel = silc_idlist_find_channel_by_id(server->local_list,
4043 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4044 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4049 /* Check whether sender is on the channel */
4050 if (!silc_server_client_on_channel(client, channel)) {
4051 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4052 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4056 /* Check that the kicker is channel operator or channel founder */
4057 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4058 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4059 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4060 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4064 /* Get target Client ID */
4065 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4067 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4068 SILC_STATUS_ERR_NO_CLIENT_ID);
4071 client_id = silc_id_payload_parse_id(tmp, tmp_len);
4073 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4074 SILC_STATUS_ERR_NO_CLIENT_ID);
4078 /* Get target client's entry */
4079 target_client = silc_idlist_find_client_by_id(server->local_list,
4081 if (!target_client) {
4082 target_client = silc_idlist_find_client_by_id(server->global_list,
4086 /* Check that the target client is not channel founder. Channel founder
4087 cannot be kicked from the channel. */
4088 silc_hash_table_find(channel->user_list, target_client, NULL, (void *)&chl);
4089 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4090 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4091 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4095 /* Check whether target client is on the channel */
4096 if (!silc_server_client_on_channel(target_client, channel)) {
4097 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4098 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4104 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4108 /* Send command reply to sender */
4109 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4112 /* Send KICKED notify to local clients on the channel */
4113 idp = silc_id_payload_encode(target_client->id, SILC_ID_CLIENT);
4114 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4115 SILC_NOTIFY_TYPE_KICKED,
4117 idp->data, idp->len,
4118 comment, comment ? strlen(comment) : 0);
4119 silc_buffer_free(idp);
4121 /* Remove the client from the channel. If the channel does not exist
4122 after removing the client then the client kicked itself off the channel
4123 and we don't have to send anything after that. */
4124 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4125 target_client, FALSE))
4128 /* Send KICKED notify to primary route */
4129 if (!server->standalone)
4130 silc_server_send_notify_kicked(server, server->router->connection,
4131 server->server_type == SILC_ROUTER ?
4132 TRUE : FALSE, channel,
4133 target_client->id, comment);
4135 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4136 /* Re-generate channel key */
4137 silc_server_create_channel_key(server, channel, 0);
4139 /* Send the channel key to the channel. The key of course is not sent
4140 to the client who was kicked off the channel. */
4141 silc_server_send_channel_key(server, target_client->connection, channel,
4142 server->server_type == SILC_ROUTER ?
4143 FALSE : !server->standalone);
4147 silc_server_command_free(cmd);
4150 /* Server side of OPER command. Client uses this comand to obtain server
4151 operator privileges to this server/router. */
4153 SILC_SERVER_CMD_FUNC(oper)
4155 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4156 SilcServer server = cmd->server;
4157 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4158 unsigned char *username, *auth;
4160 SilcServerConfigSectionAdminConnection *admin;
4161 SilcIDListData idata = (SilcIDListData)client;
4163 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_OPER, cmd, 1, 2);
4165 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4168 /* Get the username */
4169 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4171 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4172 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4176 /* Get the admin configuration */
4177 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4178 username, client->nickname);
4180 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4181 username, client->nickname);
4183 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4184 SILC_STATUS_ERR_AUTH_FAILED);
4189 /* Get the authentication payload */
4190 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4192 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4193 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4197 /* Verify the authentication data */
4198 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4199 admin->auth_data, admin->auth_data_len,
4200 idata->hash, client->id, SILC_ID_CLIENT)) {
4201 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4202 SILC_STATUS_ERR_AUTH_FAILED);
4206 /* Client is now server operator */
4207 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4209 /* Send UMODE change to primary router */
4210 if (!server->standalone)
4211 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4212 client->id, client->mode);
4214 /* Send reply to the sender */
4215 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4219 silc_server_command_free(cmd);
4222 /* Server side of SILCOPER command. Client uses this comand to obtain router
4223 operator privileges to this router. */
4225 SILC_SERVER_CMD_FUNC(silcoper)
4227 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4228 SilcServer server = cmd->server;
4229 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4230 unsigned char *username, *auth;
4232 SilcServerConfigSectionAdminConnection *admin;
4233 SilcIDListData idata = (SilcIDListData)client;
4235 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4237 if (server->server_type == SILC_SERVER)
4240 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4243 /* Get the username */
4244 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4246 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4247 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4251 /* Get the admin configuration */
4252 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4253 username, client->nickname);
4255 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4256 username, client->nickname);
4258 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4259 SILC_STATUS_ERR_AUTH_FAILED);
4264 /* Get the authentication payload */
4265 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4267 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4268 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4272 /* Verify the authentication data */
4273 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4274 admin->auth_data, admin->auth_data_len,
4275 idata->hash, client->id, SILC_ID_CLIENT)) {
4276 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4277 SILC_STATUS_ERR_AUTH_FAILED);
4281 /* Client is now router operator */
4282 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4284 /* Send UMODE change to primary router */
4285 if (!server->standalone)
4286 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4287 client->id, client->mode);
4289 /* Send reply to the sender */
4290 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4294 silc_server_command_free(cmd);
4297 /* Server side command of CONNECT. Connects us to the specified remote
4298 server or router. */
4300 SILC_SERVER_CMD_FUNC(connect)
4302 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4303 SilcServer server = cmd->server;
4304 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4305 unsigned char *tmp, *host;
4307 uint32 port = SILC_PORT;
4309 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CONNECT, cmd, 1, 2);
4311 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4314 /* Check whether client has the permissions. */
4315 if (client->mode == SILC_UMODE_NONE) {
4316 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4317 SILC_STATUS_ERR_NO_SERVER_PRIV);
4321 if (server->server_type == SILC_ROUTER &&
4322 client->mode & SILC_UMODE_SERVER_OPERATOR) {
4323 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4324 SILC_STATUS_ERR_NO_ROUTER_PRIV);
4328 /* Get the remote server */
4329 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4331 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4332 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4337 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4339 SILC_GET32_MSB(port, tmp);
4341 /* Create the connection. It is done with timeout and is async. */
4342 silc_server_create_connection(server, host, port);
4344 /* Send reply to the sender */
4345 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4349 silc_server_command_free(cmd);
4352 /* Server side of command BAN. This is used to manage the ban list of the
4353 channel. To add clients and remove clients from the ban list. */
4355 SILC_SERVER_CMD_FUNC(ban)
4357 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4358 SilcServer server = cmd->server;
4359 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4361 SilcChannelEntry channel;
4362 SilcChannelClientEntry chl;
4363 SilcChannelID *channel_id = NULL;
4364 unsigned char *id, *add, *del;
4365 uint32 id_len, tmp_len;
4366 uint16 ident = silc_command_get_ident(cmd->payload);
4368 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4371 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_BAN, cmd, 0, 3);
4373 /* Get Channel ID */
4374 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4376 channel_id = silc_id_payload_parse_id(id, id_len);
4378 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4379 SILC_STATUS_ERR_NO_CHANNEL_ID);
4384 /* Get channel entry. The server must know about the channel since the
4385 client is expected to be on the channel. */
4386 channel = silc_idlist_find_channel_by_id(server->local_list,
4389 channel = silc_idlist_find_channel_by_id(server->global_list,
4392 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4393 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4398 /* Check whether this client is on the channel */
4399 if (!silc_server_client_on_channel(client, channel)) {
4400 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4401 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4405 /* Get entry to the channel user list */
4406 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4408 /* The client must be at least channel operator. */
4409 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4410 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4411 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4415 /* Get the new ban and add it to the ban list */
4416 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4418 if (!channel->ban_list)
4419 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4421 channel->ban_list = silc_realloc(channel->ban_list,
4422 sizeof(*channel->ban_list) *
4424 strlen(channel->ban_list) + 2));
4425 if (add[tmp_len - 1] == ',')
4426 add[tmp_len - 1] = '\0';
4428 strncat(channel->ban_list, add, tmp_len);
4429 strncat(channel->ban_list, ",", 1);
4432 /* Get the ban to be removed and remove it from the list */
4433 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4434 if (del && channel->ban_list) {
4435 char *start, *end, *n;
4437 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4438 silc_free(channel->ban_list);
4439 channel->ban_list = NULL;
4441 start = strstr(channel->ban_list, del);
4442 if (start && strlen(start) >= tmp_len) {
4443 end = start + tmp_len;
4444 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4445 strncat(n, channel->ban_list, start - channel->ban_list);
4446 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4448 silc_free(channel->ban_list);
4449 channel->ban_list = n;
4454 /* Send the BAN notify type to our primary router. */
4455 if (!server->standalone && (add || del))
4456 silc_server_send_notify_ban(server, server->router->connection,
4457 server->server_type == SILC_ROUTER ?
4458 TRUE : FALSE, channel, add, del);
4460 /* Send the reply back to the client */
4461 if (channel->ban_list)
4463 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4464 SILC_STATUS_OK, ident, 2,
4466 3, channel->ban_list,
4467 strlen(channel->ban_list) - 1);
4470 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4471 SILC_STATUS_OK, ident, 1,
4474 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4475 packet->data, packet->len, FALSE);
4477 silc_buffer_free(packet);
4481 silc_free(channel_id);
4482 silc_server_command_free(cmd);
4485 /* Server side command of CLOSE. Closes connection to a specified server. */
4487 SILC_SERVER_CMD_FUNC(close)
4489 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4490 SilcServer server = cmd->server;
4491 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4492 SilcServerEntry server_entry;
4493 SilcSocketConnection sock;
4496 unsigned char *name;
4497 uint32 port = SILC_PORT;
4499 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CLOSE, cmd, 1, 2);
4501 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4504 /* Check whether client has the permissions. */
4505 if (client->mode == SILC_UMODE_NONE) {
4506 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4507 SILC_STATUS_ERR_NO_SERVER_PRIV);
4511 /* Get the remote server */
4512 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4514 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4515 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4520 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4522 SILC_GET32_MSB(port, tmp);
4524 server_entry = silc_idlist_find_server_by_conn(server->local_list,
4526 if (!server_entry) {
4527 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4528 SILC_STATUS_ERR_NO_SERVER_ID);
4532 /* Send reply to the sender */
4533 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4536 /* Close the connection to the server */
4537 sock = (SilcSocketConnection)server_entry->connection;
4538 silc_server_free_sock_user_data(server, sock);
4539 silc_server_close_connection(server, sock);
4542 silc_server_command_free(cmd);
4545 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4546 active connections. */
4548 SILC_SERVER_CMD_FUNC(shutdown)
4550 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4551 SilcServer server = cmd->server;
4552 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4554 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4556 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4559 /* Check whether client has the permission. */
4560 if (client->mode == SILC_UMODE_NONE) {
4561 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4562 SILC_STATUS_ERR_NO_SERVER_PRIV);
4566 /* Send reply to the sender */
4567 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4570 /* Then, gracefully, or not, bring the server down. */
4571 silc_server_stop(server);
4575 silc_server_command_free(cmd);
4578 /* Server side command of LEAVE. Removes client from a channel. */
4580 SILC_SERVER_CMD_FUNC(leave)
4582 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4583 SilcServer server = cmd->server;
4584 SilcSocketConnection sock = cmd->sock;
4585 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4586 SilcChannelID *id = NULL;
4587 SilcChannelEntry channel;
4591 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
4593 /* Get Channel ID */
4594 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4596 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4597 SILC_STATUS_ERR_NO_CHANNEL_ID);
4600 id = silc_id_payload_parse_id(tmp, len);
4602 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4603 SILC_STATUS_ERR_NO_CHANNEL_ID);
4607 /* Get channel entry */
4608 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4610 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4612 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4613 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4618 /* Check whether this client is on the channel */
4619 if (!silc_server_client_on_channel(id_entry, channel)) {
4620 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4621 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4625 /* Notify routers that they should remove this client from their list
4626 of clients on the channel. Send LEAVE notify type. */
4627 if (!server->standalone)
4628 silc_server_send_notify_leave(server, server->router->connection,
4629 server->server_type == SILC_ROUTER ?
4630 TRUE : FALSE, channel, id_entry->id);
4632 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4635 /* Remove client from channel */
4636 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4638 /* If the channel does not exist anymore we won't send anything */
4641 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4642 /* Re-generate channel key */
4643 silc_server_create_channel_key(server, channel, 0);
4645 /* Send the channel key */
4646 silc_server_send_channel_key(server, NULL, channel,
4647 server->server_type == SILC_ROUTER ?
4648 FALSE : !server->standalone);
4654 silc_server_command_free(cmd);
4657 /* Server side of command USERS. Resolves clients and their USERS currently
4658 joined on the requested channel. The list of Client ID's and their modes
4659 on the channel is sent back. */
4661 SILC_SERVER_CMD_FUNC(users)
4663 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4664 SilcServer server = cmd->server;
4665 SilcChannelEntry channel;
4668 unsigned char *channel_id;
4669 uint32 channel_id_len;
4670 SilcBuffer client_id_list;
4671 SilcBuffer client_mode_list;
4672 unsigned char lc[4];
4673 uint32 list_count = 0;
4674 uint16 ident = silc_command_get_ident(cmd->payload);
4676 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
4678 /* Get Channel ID */
4679 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4681 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4682 SILC_STATUS_ERR_NO_CHANNEL_ID);
4685 id = silc_id_payload_parse_id(channel_id, channel_id_len);
4687 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4688 SILC_STATUS_ERR_NO_CHANNEL_ID);
4692 /* If we are server and we don't know about this channel we will send
4693 the command to our router. If we know about the channel then we also
4694 have the list of users already. */
4695 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4697 if (server->server_type == SILC_SERVER && !server->standalone &&
4701 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
4702 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4704 /* Send USERS command */
4705 silc_server_packet_send(server, server->router->connection,
4706 SILC_PACKET_COMMAND, cmd->packet->flags,
4707 tmpbuf->data, tmpbuf->len, TRUE);
4709 /* Reprocess this packet after received reply */
4710 silc_server_command_pending(server, SILC_COMMAND_USERS,
4711 silc_command_get_ident(cmd->payload),
4712 silc_server_command_destructor,
4713 silc_server_command_users,
4714 silc_server_command_dup(cmd));
4715 cmd->pending = TRUE;
4716 silc_command_set_ident(cmd->payload, ident);
4718 silc_buffer_free(tmpbuf);
4723 /* We are router and we will check the global list as well. */
4724 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4726 /* Channel really does not exist */
4727 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4728 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4733 /* Get the users list */
4734 silc_server_get_users_on_channel(server, channel, &client_id_list,
4735 &client_mode_list, &list_count);
4738 SILC_PUT32_MSB(list_count, lc);
4741 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
4742 SILC_STATUS_OK, ident, 4,
4743 2, channel_id, channel_id_len,
4745 4, client_id_list->data,
4746 client_id_list->len,
4747 5, client_mode_list->data,
4748 client_mode_list->len);
4749 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4750 packet->data, packet->len, FALSE);
4752 silc_buffer_free(packet);
4753 silc_buffer_free(client_id_list);
4754 silc_buffer_free(client_mode_list);
4758 silc_server_command_free(cmd);
4761 /* Server side of command GETKEY. This fetches the client's public key
4762 from the server where to the client is connected. */
4764 SILC_SERVER_CMD_FUNC(getkey)
4766 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4767 SilcServer server = cmd->server;
4769 SilcClientEntry client;
4770 SilcServerEntry server_entry;
4771 SilcClientID *client_id = NULL;
4772 SilcServerID *server_id = NULL;
4773 SilcIDPayload idp = NULL;
4774 uint16 ident = silc_command_get_ident(cmd->payload);
4780 SILC_LOG_DEBUG(("Start"));
4782 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4784 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4785 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4788 idp = silc_id_payload_parse_data(tmp, tmp_len);
4790 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4791 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4795 id_type = silc_id_payload_get_type(idp);
4796 if (id_type == SILC_ID_CLIENT) {
4797 client_id = silc_id_payload_get_id(idp);
4799 /* If the client is not found from local list there is no chance it
4800 would be locally connected client so send the command further. */
4801 client = silc_idlist_find_client_by_id(server->local_list,
4804 client = silc_idlist_find_client_by_id(server->global_list,
4807 if ((!client && !cmd->pending && !server->standalone) ||
4808 (client && !client->connection && !cmd->pending &&
4809 !server->standalone) ||
4810 (client && !client->data.public_key && !cmd->pending &&
4811 !server->standalone)) {
4814 SilcSocketConnection dest_sock;
4816 dest_sock = silc_server_get_client_route(server, NULL, 0,
4821 old_ident = silc_command_get_ident(cmd->payload);
4822 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
4823 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4825 silc_server_packet_send(server, dest_sock,
4826 SILC_PACKET_COMMAND, cmd->packet->flags,
4827 tmpbuf->data, tmpbuf->len, TRUE);
4829 /* Reprocess this packet after received reply from router */
4830 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
4831 silc_command_get_ident(cmd->payload),
4832 silc_server_command_destructor,
4833 silc_server_command_getkey,
4834 silc_server_command_dup(cmd));
4835 cmd->pending = TRUE;
4837 silc_command_set_ident(cmd->payload, old_ident);
4838 silc_buffer_free(tmpbuf);
4842 if (!client && cmd->pending) {
4843 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4844 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
4848 /* The client is locally connected, just get the public key and
4850 tmp = silc_pkcs_public_key_encode(client->data.public_key, &tmp_len);
4851 pk = silc_buffer_alloc(4 + tmp_len);
4852 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
4853 silc_buffer_format(pk,
4854 SILC_STR_UI_SHORT(tmp_len),
4855 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
4856 SILC_STR_UI_XNSTRING(tmp, tmp_len),
4860 } else if (id_type == SILC_ID_SERVER) {
4861 server_id = silc_id_payload_get_id(idp);
4863 /* If the server is not found from local list there is no chance it
4864 would be locally connected server so send the command further. */
4865 server_entry = silc_idlist_find_server_by_id(server->local_list,
4868 server_entry = silc_idlist_find_server_by_id(server->global_list,
4871 if ((!server_entry && !cmd->pending && !server->standalone) ||
4872 (server_entry && !server_entry->connection && !cmd->pending &&
4873 !server->standalone) ||
4874 (server_entry && !server_entry->data.public_key && !cmd->pending &&
4875 !server->standalone)) {
4879 old_ident = silc_command_get_ident(cmd->payload);
4880 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
4881 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4883 silc_server_packet_send(server, server->router->connection,
4884 SILC_PACKET_COMMAND, cmd->packet->flags,
4885 tmpbuf->data, tmpbuf->len, TRUE);
4887 /* Reprocess this packet after received reply from router */
4888 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
4889 silc_command_get_ident(cmd->payload),
4890 silc_server_command_destructor,
4891 silc_server_command_getkey,
4892 silc_server_command_dup(cmd));
4893 cmd->pending = TRUE;
4895 silc_command_set_ident(cmd->payload, old_ident);
4896 silc_buffer_free(tmpbuf);
4900 if (!server_entry && cmd->pending) {
4901 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4902 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
4906 /* The client is locally connected, just get the public key and
4908 tmp = silc_pkcs_public_key_encode(server_entry->data.public_key, &tmp_len);
4909 pk = silc_buffer_alloc(4 + tmp_len);
4910 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
4911 silc_buffer_format(pk,
4912 SILC_STR_UI_SHORT(tmp_len),
4913 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
4914 SILC_STR_UI_XNSTRING(tmp, tmp_len),
4921 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4922 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
4923 SILC_STATUS_OK, ident, 2,
4925 3, pk->data, pk->len);
4926 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4927 packet->data, packet->len, FALSE);
4928 silc_buffer_free(packet);
4929 silc_buffer_free(pk);
4933 silc_id_payload_free(idp);
4934 silc_free(client_id);
4935 silc_free(server_id);
4936 silc_server_command_free(cmd);