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,
41 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
42 SilcServerCommandReplyContext cmdr,
44 SILC_TASK_CALLBACK(silc_server_command_process_timeout);
46 /* Server command list. */
47 SilcServerCommand silc_command_list[] =
49 SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
50 SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
51 SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
52 SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
53 SILC_SERVER_CMD(list, LIST, SILC_CF_LAG_STRICT | SILC_CF_REG),
54 SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
55 SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
56 SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
57 SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG_STRICT | SILC_CF_REG | SILC_CF_OPER),
58 SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
59 SILC_SERVER_CMD(connect, CONNECT,
60 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
61 SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
62 SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
63 SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG_STRICT | SILC_CF_REG),
64 SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
65 SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
66 SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG_STRICT | SILC_CF_REG),
67 SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
68 SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
69 SILC_SERVER_CMD(ban, BAN, SILC_CF_LAG_STRICT | SILC_CF_REG),
70 SILC_SERVER_CMD(close, CLOSE,
71 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
72 SILC_SERVER_CMD(shutdown, SHUTDOWN, SILC_CF_LAG | SILC_CF_REG |
74 SILC_SERVER_CMD(silcoper, SILCOPER,
75 SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
76 SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
77 SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
78 SILC_SERVER_CMD(getkey, GETKEY, SILC_CF_LAG | SILC_CF_REG),
83 /* Performs several checks to the command. It first checks whether this
84 command was called as pending command callback. If it was then it checks
85 whether error occurred in the command reply where the pending command
88 It also checks that the requested command includes correct amount
90 #define SILC_SERVER_COMMAND_CHECK(command, context, min, max) \
94 SILC_LOG_DEBUG(("Start")); \
96 if (silc_server_command_pending_error_check(cmd, context2, command)) { \
97 silc_server_command_free(cmd); \
101 _argc = silc_argument_get_arg_num(cmd->args); \
103 silc_server_command_send_status_reply(cmd, command, \
104 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
105 silc_server_command_free(cmd); \
109 silc_server_command_send_status_reply(cmd, command, \
110 SILC_STATUS_ERR_TOO_MANY_PARAMS); \
111 silc_server_command_free(cmd); \
116 /* Returns TRUE if the connection is registered. Unregistered connections
117 usually cannot send commands hence the check. */
119 static int silc_server_is_registered(SilcServer server,
120 SilcSocketConnection sock,
121 SilcServerCommandContext cmd,
124 SilcIDListData idata = (SilcIDListData)sock->user_data;
125 if (idata->registered)
128 silc_server_command_send_status_reply(cmd, command,
129 SILC_STATUS_ERR_NOT_REGISTERED);
130 silc_server_command_free(cmd);
134 /* Internal context to hold data when executed command with timeout. */
136 SilcServerCommandContext ctx;
137 SilcServerCommand *cmd;
138 } *SilcServerCommandTimeout;
140 /* Timeout callback to process commands with timeout for client. Client's
141 commands are always executed with timeout. */
143 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
145 SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
146 SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data;
148 /* Update access time */
149 client->last_command = time(NULL);
151 if (!(timeout->cmd->flags & SILC_CF_REG))
152 timeout->cmd->cb(timeout->ctx, NULL);
153 else if (silc_server_is_registered(timeout->ctx->server,
157 timeout->cmd->cb(timeout->ctx, NULL);
162 /* Processes received command packet. */
164 void silc_server_command_process(SilcServer server,
165 SilcSocketConnection sock,
166 SilcPacketContext *packet)
168 SilcServerCommandContext ctx;
169 SilcServerCommand *cmd;
172 /* Allocate command context. This must be free'd by the
173 command routine receiving it. */
174 ctx = silc_server_command_alloc();
175 ctx->server = server;
176 ctx->sock = silc_socket_dup(sock);
177 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
179 /* Parse the command payload in the packet */
180 ctx->payload = silc_command_payload_parse(packet->buffer);
182 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
183 silc_buffer_free(packet->buffer);
184 silc_packet_context_free(packet);
185 silc_socket_free(ctx->sock);
189 ctx->args = silc_command_get_args(ctx->payload);
191 /* Get the command */
192 command = silc_command_get(ctx->payload);
193 for (cmd = silc_command_list; cmd->cb; cmd++)
194 if (cmd->cmd == command)
198 silc_server_command_send_status_reply(ctx, command,
199 SILC_STATUS_ERR_UNKNOWN_COMMAND);
200 silc_server_command_free(ctx);
204 /* Execute client's commands always with timeout. Normally they are
205 executed with zero (0) timeout but if client is sending command more
206 frequently than once in 2 seconds, then the timeout may be 0 to 2
208 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
209 SilcClientEntry client = (SilcClientEntry)sock->user_data;
210 SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
216 if (client->last_command && (time(NULL) - client->last_command) < 2) {
217 client->fast_command++;
220 client->fast_command = ((client->fast_command - 1) <= 0 ? 0 :
221 client->fast_command--);
225 if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
226 (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
227 silc_task_register(server->timeout_queue, sock->sock,
228 silc_server_command_process_timeout,
230 2 - (time(NULL) - client->last_command), 0,
232 SILC_TASK_PRI_NORMAL);
234 silc_task_register(server->timeout_queue, sock->sock,
235 silc_server_command_process_timeout,
239 SILC_TASK_PRI_NORMAL);
243 /* Execute for server */
245 if (!(cmd->flags & SILC_CF_REG))
247 else if (silc_server_is_registered(server, sock, ctx, cmd->cmd))
251 /* Allocate Command Context */
253 SilcServerCommandContext silc_server_command_alloc()
255 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
260 /* Free's the command context allocated before executing the command */
262 void silc_server_command_free(SilcServerCommandContext ctx)
265 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
267 if (ctx->users < 1) {
269 silc_command_payload_free(ctx->payload);
271 silc_packet_context_free(ctx->packet);
273 silc_socket_free(ctx->sock); /* Decrease reference counter */
278 /* Duplicate Command Context by adding reference counter. The context won't
279 be free'd untill it hits zero. */
281 SilcServerCommandContext
282 silc_server_command_dup(SilcServerCommandContext ctx)
285 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
290 /* Add new pending command to be executed when reply to a command has been
291 received. The `reply_cmd' is the command that will call the `callback'
292 with `context' when reply has been received. If `ident' is non-zero
293 the `callback' will be executed when received reply with command
294 identifier `ident'. */
296 void silc_server_command_pending(SilcServer server,
297 SilcCommand reply_cmd,
299 SilcServerPendingDestructor destructor,
300 SilcCommandCb callback,
303 SilcServerCommandPending *reply;
305 reply = silc_calloc(1, sizeof(*reply));
306 reply->reply_cmd = reply_cmd;
307 reply->ident = ident;
308 reply->context = context;
309 reply->callback = callback;
310 reply->destructor = destructor;
311 silc_dlist_add(server->pending_commands, reply);
314 /* Deletes pending command by reply command type. */
316 void silc_server_command_pending_del(SilcServer server,
317 SilcCommand reply_cmd,
320 SilcServerCommandPending *r;
322 silc_dlist_start(server->pending_commands);
323 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
324 if (r->reply_cmd == reply_cmd && r->ident == ident) {
325 silc_dlist_del(server->pending_commands, r);
331 /* Checks for pending commands and marks callbacks to be called from
332 the command reply function. Returns TRUE if there were pending command. */
334 int silc_server_command_pending_check(SilcServer server,
335 SilcServerCommandReplyContext ctx,
339 SilcServerCommandPending *r;
341 silc_dlist_start(server->pending_commands);
342 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
343 if (r->reply_cmd == command && r->ident == ident) {
344 ctx->context = r->context;
345 ctx->callback = r->callback;
346 ctx->destructor = r->destructor;
355 /* Destructor function for pending callbacks. This is called when using
356 pending commands to free the context given for the pending command. */
358 static void silc_server_command_destructor(void *context)
360 silc_server_command_free((SilcServerCommandContext)context);
363 /* Sends simple status message as command reply packet */
366 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
368 SilcCommandStatus status)
372 SILC_LOG_DEBUG(("Sending command status %d", status));
375 silc_command_reply_payload_encode_va(command, status,
376 silc_command_get_ident(cmd->payload),
378 silc_server_packet_send(cmd->server, cmd->sock,
379 SILC_PACKET_COMMAND_REPLY, 0,
380 buffer->data, buffer->len, FALSE);
381 silc_buffer_free(buffer);
384 /* Sends command status reply with one extra argument. The argument
385 type must be sent as argument. */
388 silc_server_command_send_status_data(SilcServerCommandContext cmd,
390 SilcCommandStatus status,
397 SILC_LOG_DEBUG(("Sending command status %d", status));
400 silc_command_reply_payload_encode_va(command, status,
401 silc_command_get_ident(cmd->payload),
402 1, arg_type, arg, arg_len);
403 silc_server_packet_send(cmd->server, cmd->sock,
404 SILC_PACKET_COMMAND_REPLY, 0,
405 buffer->data, buffer->len, FALSE);
406 silc_buffer_free(buffer);
409 /* This function can be called to check whether in the command reply
410 an error occurred. This function has no effect if this is called
411 when the command function was not called as pending command callback.
412 This returns TRUE if error had occurred. */
415 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
416 SilcServerCommandReplyContext cmdr,
419 SilcCommandStatus status;
421 if (!cmd->pending || !cmdr)
424 SILC_GET16_MSB(status, silc_argument_get_arg_type(cmdr->args, 1, NULL));
425 if (status != SILC_STATUS_OK) {
426 /* Send the error message */
427 silc_server_command_send_status_reply(cmd, command, status);
434 /******************************************************************************
438 ******************************************************************************/
441 silc_server_command_whois_parse(SilcServerCommandContext cmd,
442 SilcClientID ***client_id,
443 uint32 *client_id_count,
451 uint32 argc = silc_argument_get_arg_num(cmd->args);
454 /* If client ID is in the command it must be used instead of nickname */
455 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
457 /* No ID, get the nickname@server string and parse it. */
458 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
460 if (strchr(tmp, '@')) {
461 len = strcspn(tmp, "@");
462 *nickname = silc_calloc(len + 1, sizeof(char));
463 memcpy(*nickname, tmp, len);
464 *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
465 memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
467 *nickname = strdup(tmp);
470 silc_server_command_send_status_reply(cmd, command,
471 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
475 /* Command includes ID, we must use that. Also check whether the command
476 has more than one ID set - take them all. */
478 *client_id = silc_calloc(1, sizeof(**client_id));
479 (*client_id)[0] = silc_id_payload_parse_id(tmp, len);
480 if ((*client_id)[0] == NULL) {
481 silc_free(*client_id);
484 *client_id_count = 1;
486 /* Take all ID's from the command packet */
488 for (k = 1, i = 1; i < argc; i++) {
489 tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
491 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
492 (*client_id_count + 1));
493 (*client_id)[k] = silc_id_payload_parse_id(tmp, len);
494 if ((*client_id)[k] == NULL) {
495 /* Cleanup all and fail */
496 for (i = 0; i < *client_id_count; i++)
497 silc_free((*client_id)[i]);
498 silc_free(*client_id);
501 (*client_id_count)++;
507 /* Command includes ID, use that */
510 /* Get the max count of reply messages allowed */
511 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
521 silc_server_command_whois_check(SilcServerCommandContext cmd,
522 SilcClientEntry *clients,
523 uint32 clients_count)
525 SilcServer server = cmd->server;
527 SilcClientEntry entry;
529 for (i = 0; i < clients_count; i++) {
532 if (!entry || entry->data.registered == FALSE)
535 if (!entry->nickname || !entry->username || !entry->userinfo) {
542 old_ident = silc_command_get_ident(cmd->payload);
543 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
544 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
546 /* Send WHOIS command */
547 silc_server_packet_send(server, entry->router->connection,
548 SILC_PACKET_COMMAND, cmd->packet->flags,
549 tmpbuf->data, tmpbuf->len, TRUE);
551 /* Reprocess this packet after received reply */
552 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
553 silc_command_get_ident(cmd->payload),
554 silc_server_command_destructor,
555 silc_server_command_whois,
556 silc_server_command_dup(cmd));
559 silc_command_set_ident(cmd->payload, old_ident);
561 silc_buffer_free(tmpbuf);
570 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
571 SilcClientEntry *clients,
572 uint32 clients_count,
575 SilcServer server = cmd->server;
578 SilcBuffer packet, idp, channels;
579 SilcClientEntry entry;
580 SilcCommandStatus status;
581 uint16 ident = silc_command_get_ident(cmd->payload);
582 char nh[256], uh[256];
583 unsigned char idle[4], mode[4];
584 SilcSocketConnection hsock;
587 for (i = 0; i < clients_count; i++)
588 if (clients[i]->data.registered)
591 status = SILC_STATUS_OK;
593 status = SILC_STATUS_LIST_START;
595 for (i = 0, k = 0; i < clients_count; i++) {
598 if (entry->data.registered == FALSE) {
599 if (clients_count == 1) {
600 if (entry->nickname) {
601 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
602 SILC_STATUS_ERR_NO_SUCH_NICK,
604 strlen(entry->nickname));
606 SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
607 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
608 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
609 2, idp->data, idp->len);
610 silc_buffer_free(idp);
617 status = SILC_STATUS_LIST_ITEM;
619 if (clients_count > 1 && k == clients_count - 1)
620 status = SILC_STATUS_LIST_END;
622 if (count && k - 1 == count)
623 status = SILC_STATUS_LIST_END;
625 if (count && k - 1 > count)
628 /* Sanity check, however these should never fail. However, as
629 this sanity check has been added here they have failed. */
630 if (!entry->nickname || !entry->username || !entry->userinfo)
633 /* Send WHOIS reply */
634 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
635 tmp = silc_argument_get_first_arg(cmd->args, NULL);
637 memset(uh, 0, sizeof(uh));
638 memset(nh, 0, sizeof(nh));
639 memset(idle, 0, sizeof(idle));
641 strncat(nh, entry->nickname, strlen(entry->nickname));
642 if (!strchr(entry->nickname, '@')) {
644 if (entry->servername) {
645 strncat(nh, entry->servername, strlen(entry->servername));
647 len = entry->router ? strlen(entry->router->server_name) :
648 strlen(server->server_name);
649 strncat(nh, entry->router ? entry->router->server_name :
650 server->server_name, len);
654 strncat(uh, entry->username, strlen(entry->username));
655 if (!strchr(entry->username, '@')) {
657 hsock = (SilcSocketConnection)entry->connection;
658 len = strlen(hsock->hostname);
659 strncat(uh, hsock->hostname, len);
662 channels = silc_server_get_client_channel_list(server, entry);
664 SILC_PUT32_MSB(entry->mode, mode);
666 if (entry->connection) {
667 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
671 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
673 2, idp->data, idp->len,
677 strlen(entry->userinfo),
683 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
685 2, idp->data, idp->len,
689 strlen(entry->userinfo),
693 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
694 0, packet->data, packet->len, FALSE);
696 silc_buffer_free(packet);
697 silc_buffer_free(idp);
699 silc_buffer_free(channels);
706 silc_server_command_whois_from_client(SilcServerCommandContext cmd)
708 SilcServer server = cmd->server;
709 char *nick = NULL, *server_name = NULL;
711 SilcClientEntry *clients = NULL, entry;
712 SilcClientID **client_id = NULL;
713 uint32 client_id_count = 0, clients_count = 0;
716 /* Protocol dictates that we must always send the received WHOIS request
717 to our router if we are normal server, so let's do it now unless we
718 are standalone. We will not send any replies to the client until we
719 have received reply from the router. */
720 if (server->server_type == SILC_SERVER && !cmd->pending &&
721 !server->standalone) {
725 old_ident = silc_command_get_ident(cmd->payload);
726 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
727 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
729 /* Send WHOIS command to our router */
730 silc_server_packet_send(server, (SilcSocketConnection)
731 server->router->connection,
732 SILC_PACKET_COMMAND, cmd->packet->flags,
733 tmpbuf->data, tmpbuf->len, TRUE);
735 /* Reprocess this packet after received reply from router */
736 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
737 silc_command_get_ident(cmd->payload),
738 silc_server_command_destructor,
739 silc_server_command_whois,
740 silc_server_command_dup(cmd));
743 silc_command_set_ident(cmd->payload, old_ident);
745 silc_buffer_free(tmpbuf);
750 /* We are ready to process the command request. Let's search for the
751 requested client and send reply to the requesting client. */
753 /* Parse the whois request */
754 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
755 &nick, &server_name, &count,
759 /* Get all clients matching that ID or nickname from local list */
760 if (client_id_count) {
761 /* Check all Client ID's received in the command packet */
762 for (i = 0; i < client_id_count; i++) {
763 entry = silc_idlist_find_client_by_id(server->local_list,
766 clients = silc_realloc(clients, sizeof(*clients) *
767 (clients_count + 1));
768 clients[clients_count++] = entry;
772 if (!silc_idlist_get_clients_by_hash(server->local_list,
773 nick, server->md5hash,
774 &clients, &clients_count))
775 silc_idlist_get_clients_by_nickname(server->local_list,
777 &clients, &clients_count);
780 /* Check global list as well */
781 if (client_id_count) {
782 /* Check all Client ID's received in the command packet */
783 for (i = 0; i < client_id_count; i++) {
784 entry = silc_idlist_find_client_by_id(server->global_list,
787 clients = silc_realloc(clients, sizeof(*clients) *
788 (clients_count + 1));
789 clients[clients_count++] = entry;
793 if (!silc_idlist_get_clients_by_hash(server->global_list,
794 nick, server->md5hash,
795 &clients, &clients_count))
796 silc_idlist_get_clients_by_nickname(server->global_list,
798 &clients, &clients_count);
802 /* Such client(s) really does not exist in the SILC network. */
803 if (!client_id_count) {
804 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
805 SILC_STATUS_ERR_NO_SUCH_NICK,
806 3, nick, strlen(nick));
808 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
809 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
810 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
811 2, idp->data, idp->len);
812 silc_buffer_free(idp);
817 /* Router always finds the client entry if it exists in the SILC network.
818 However, it might be incomplete entry and does not include all the
819 mandatory fields that WHOIS command reply requires. Check for these and
820 make query from the server who owns the client if some fields are
822 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
827 /* Send the command reply to the client */
828 silc_server_command_whois_send_reply(cmd, clients, clients_count,
832 if (client_id_count) {
833 for (i = 0; i < client_id_count; i++)
834 silc_free(client_id[i]);
835 silc_free(client_id);
842 silc_free(server_name);
848 silc_server_command_whois_from_server(SilcServerCommandContext cmd)
850 SilcServer server = cmd->server;
851 char *nick = NULL, *server_name = NULL;
853 SilcClientEntry *clients = NULL, entry;
854 SilcClientID **client_id = NULL;
855 uint32 client_id_count = 0, clients_count = 0;
858 /* Parse the whois request */
859 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
860 &nick, &server_name, &count,
864 /* Process the command request. Let's search for the requested client and
865 send reply to the requesting server. */
867 if (client_id_count) {
868 /* Check all Client ID's received in the command packet */
869 for (i = 0; i < client_id_count; i++) {
870 entry = silc_idlist_find_client_by_id(server->local_list,
873 clients = silc_realloc(clients, sizeof(*clients) *
874 (clients_count + 1));
875 clients[clients_count++] = entry;
879 if (!silc_idlist_get_clients_by_hash(server->local_list,
880 nick, server->md5hash,
881 &clients, &clients_count))
882 silc_idlist_get_clients_by_nickname(server->local_list,
884 &clients, &clients_count);
887 /* If we are router we will check our global list as well. */
888 if (server->server_type == SILC_ROUTER) {
889 if (client_id_count) {
890 /* Check all Client ID's received in the command packet */
891 for (i = 0; i < client_id_count; i++) {
892 entry = silc_idlist_find_client_by_id(server->global_list,
895 clients = silc_realloc(clients, sizeof(*clients) *
896 (clients_count + 1));
897 clients[clients_count++] = entry;
901 if (!silc_idlist_get_clients_by_hash(server->global_list,
902 nick, server->md5hash,
903 &clients, &clients_count))
904 silc_idlist_get_clients_by_nickname(server->global_list,
906 &clients, &clients_count);
911 /* Such a client really does not exist in the SILC network. */
912 if (!client_id_count) {
913 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
914 SILC_STATUS_ERR_NO_SUCH_NICK,
915 3, nick, strlen(nick));
917 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
918 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
919 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
920 2, idp->data, idp->len);
921 silc_buffer_free(idp);
926 /* Router always finds the client entry if it exists in the SILC network.
927 However, it might be incomplete entry and does not include all the
928 mandatory fields that WHOIS command reply requires. Check for these and
929 make query from the server who owns the client if some fields are
931 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
936 /* Send the command reply to the client */
937 silc_server_command_whois_send_reply(cmd, clients, clients_count,
941 if (client_id_count) {
942 for (i = 0; i < client_id_count; i++)
943 silc_free(client_id[i]);
944 silc_free(client_id);
951 silc_free(server_name);
956 /* Server side of command WHOIS. Processes user's query and sends found
957 results as command replies back to the client. */
959 SILC_SERVER_CMD_FUNC(whois)
961 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
964 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 3328);
966 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
967 ret = silc_server_command_whois_from_client(cmd);
968 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
969 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
970 ret = silc_server_command_whois_from_server(cmd);
973 silc_server_command_free(cmd);
976 /******************************************************************************
980 ******************************************************************************/
983 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
991 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
993 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
994 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
998 /* Get the nickname@server string and parse it. */
999 if (strchr(tmp, '@')) {
1000 len = strcspn(tmp, "@");
1001 *nickname = silc_calloc(len + 1, sizeof(char));
1002 memcpy(*nickname, tmp, len);
1003 *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
1004 memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
1006 *nickname = strdup(tmp);
1008 /* Get the max count of reply messages allowed */
1009 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1019 silc_server_command_whowas_check(SilcServerCommandContext cmd,
1020 SilcClientEntry *clients,
1021 uint32 clients_count)
1023 SilcServer server = cmd->server;
1025 SilcClientEntry entry;
1027 for (i = 0; i < clients_count; i++) {
1030 if (!entry->nickname || !entry->username) {
1037 old_ident = silc_command_get_ident(cmd->payload);
1038 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1039 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1041 /* Send WHOWAS command */
1042 silc_server_packet_send(server, entry->router->connection,
1043 SILC_PACKET_COMMAND, cmd->packet->flags,
1044 tmpbuf->data, tmpbuf->len, TRUE);
1046 /* Reprocess this packet after received reply */
1047 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1048 silc_command_get_ident(cmd->payload),
1049 silc_server_command_destructor,
1050 silc_server_command_whowas,
1051 silc_server_command_dup(cmd));
1052 cmd->pending = TRUE;
1054 silc_command_set_ident(cmd->payload, old_ident);
1056 silc_buffer_free(tmpbuf);
1065 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1066 SilcClientEntry *clients,
1067 uint32 clients_count)
1069 SilcServer server = cmd->server;
1071 int i, count = 0, len;
1072 SilcBuffer packet, idp;
1073 SilcClientEntry entry = NULL;
1074 SilcCommandStatus status;
1075 uint16 ident = silc_command_get_ident(cmd->payload);
1077 char nh[256], uh[256];
1079 status = SILC_STATUS_OK;
1080 if (clients_count > 1)
1081 status = SILC_STATUS_LIST_START;
1083 for (i = 0; i < clients_count; i++) {
1086 /* We will take only clients that are not valid anymore. They are the
1087 ones that are not registered anymore but still have a ID. They
1088 have disconnected us, and thus valid for WHOWAS. */
1089 if (entry->data.registered == TRUE)
1091 if (entry->id == NULL)
1094 if (count && i - 1 == count)
1099 if (clients_count > 2)
1100 status = SILC_STATUS_LIST_ITEM;
1102 if (clients_count > 1 && i == clients_count - 1)
1103 status = SILC_STATUS_LIST_END;
1105 /* Sanity check, however these should never fail. However, as
1106 this sanity check has been added here they have failed. */
1107 if (!entry->nickname || !entry->username)
1110 /* Send WHOWAS reply */
1111 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1112 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1114 memset(uh, 0, sizeof(uh));
1115 memset(nh, 0, sizeof(nh));
1117 strncat(nh, entry->nickname, strlen(entry->nickname));
1118 if (!strchr(entry->nickname, '@')) {
1119 strncat(nh, "@", 1);
1120 if (entry->servername) {
1121 strncat(nh, entry->servername, strlen(entry->servername));
1123 len = entry->router ? strlen(entry->router->server_name) :
1124 strlen(server->server_name);
1125 strncat(nh, entry->router ? entry->router->server_name :
1126 server->server_name, len);
1130 strncat(uh, entry->username, strlen(entry->username));
1131 if (!strchr(entry->username, '@')) {
1132 strncat(uh, "@", 1);
1133 strcat(uh, "*private*");
1136 if (entry->userinfo)
1138 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1140 2, idp->data, idp->len,
1144 strlen(entry->userinfo));
1147 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1149 2, idp->data, idp->len,
1153 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1154 0, packet->data, packet->len, FALSE);
1156 silc_buffer_free(packet);
1157 silc_buffer_free(idp);
1160 if (found == FALSE && entry)
1161 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1162 SILC_STATUS_ERR_NO_SUCH_NICK,
1164 strlen(entry->nickname));
1168 silc_server_command_whowas_from_client(SilcServerCommandContext cmd)
1170 SilcServer server = cmd->server;
1171 char *nick = NULL, *server_name = NULL;
1173 SilcClientEntry *clients = NULL;
1174 uint32 clients_count = 0;
1177 /* Protocol dictates that we must always send the received WHOWAS request
1178 to our router if we are normal server, so let's do it now unless we
1179 are standalone. We will not send any replies to the client until we
1180 have received reply from the router. */
1181 if (server->server_type == SILC_SERVER && !cmd->pending &&
1182 !server->standalone) {
1186 old_ident = silc_command_get_ident(cmd->payload);
1187 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1188 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1190 /* Send WHOWAS command to our router */
1191 silc_server_packet_send(server, (SilcSocketConnection)
1192 server->router->connection,
1193 SILC_PACKET_COMMAND, cmd->packet->flags,
1194 tmpbuf->data, tmpbuf->len, TRUE);
1196 /* Reprocess this packet after received reply from router */
1197 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1198 silc_command_get_ident(cmd->payload),
1199 silc_server_command_destructor,
1200 silc_server_command_whowas,
1201 silc_server_command_dup(cmd));
1202 cmd->pending = TRUE;
1204 silc_command_set_ident(cmd->payload, old_ident);
1206 silc_buffer_free(tmpbuf);
1211 /* We are ready to process the command request. Let's search for the
1212 requested client and send reply to the requesting client. */
1214 /* Parse the whowas request */
1215 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1218 /* Get all clients matching that nickname from local list */
1219 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1221 &clients, &clients_count))
1222 silc_idlist_get_clients_by_hash(server->local_list,
1223 nick, server->md5hash,
1224 &clients, &clients_count);
1226 /* Check global list as well */
1227 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1229 &clients, &clients_count))
1230 silc_idlist_get_clients_by_hash(server->global_list,
1231 nick, server->md5hash,
1232 &clients, &clients_count);
1235 /* Such a client really does not exist in the SILC network. */
1236 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1237 SILC_STATUS_ERR_NO_SUCH_NICK,
1238 3, nick, strlen(nick));
1242 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1247 /* Send the command reply to the client */
1248 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1256 silc_free(server_name);
1262 silc_server_command_whowas_from_server(SilcServerCommandContext cmd)
1264 SilcServer server = cmd->server;
1265 char *nick = NULL, *server_name = NULL;
1267 SilcClientEntry *clients = NULL;
1268 uint32 clients_count = 0;
1271 /* Parse the whowas request */
1272 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1275 /* Process the command request. Let's search for the requested client and
1276 send reply to the requesting server. */
1278 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1280 &clients, &clients_count))
1281 silc_idlist_get_clients_by_hash(server->local_list,
1282 nick, server->md5hash,
1283 &clients, &clients_count);
1285 /* If we are router we will check our global list as well. */
1286 if (server->server_type == SILC_ROUTER) {
1287 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1289 &clients, &clients_count))
1290 silc_idlist_get_clients_by_hash(server->global_list,
1291 nick, server->md5hash,
1292 &clients, &clients_count);
1296 /* Such a client really does not exist in the SILC network. */
1297 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1298 SILC_STATUS_ERR_NO_SUCH_NICK,
1299 3, nick, strlen(nick));
1303 /* Send the command reply to the client */
1304 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1312 silc_free(server_name);
1317 /* Server side of command WHOWAS. */
1319 SILC_SERVER_CMD_FUNC(whowas)
1321 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1324 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1326 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1327 ret = silc_server_command_whowas_from_client(cmd);
1328 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
1329 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1330 ret = silc_server_command_whowas_from_server(cmd);
1333 silc_server_command_free(cmd);
1336 /******************************************************************************
1340 ******************************************************************************/
1342 /* Checks that all mandatory fields are present. If not then send WHOIS
1343 request to the server who owns the client. We use WHOIS because we want
1344 to get as much information as possible at once. */
1347 silc_server_command_identify_check(SilcServerCommandContext cmd,
1348 SilcClientEntry *clients,
1349 uint32 clients_count)
1351 SilcServer server = cmd->server;
1353 SilcClientEntry entry;
1355 for (i = 0; i < clients_count; i++) {
1358 if (!entry || entry->data.registered == FALSE)
1361 if (!entry->nickname) {
1368 old_ident = silc_command_get_ident(cmd->payload);
1369 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1370 silc_command_set_command(cmd->payload, SILC_COMMAND_WHOIS);
1371 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1373 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1374 now anyway so make it a good one. */
1375 silc_server_packet_send(server, entry->router->connection,
1376 SILC_PACKET_COMMAND, cmd->packet->flags,
1377 tmpbuf->data, tmpbuf->len, TRUE);
1379 /* Reprocess this packet after received reply */
1380 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1381 silc_command_get_ident(cmd->payload),
1382 silc_server_command_destructor,
1383 silc_server_command_identify,
1384 silc_server_command_dup(cmd));
1386 cmd->pending = TRUE;
1388 /* Put old data back to the Command Payload we just changed */
1389 silc_command_set_ident(cmd->payload, old_ident);
1390 silc_command_set_command(cmd->payload, SILC_COMMAND_IDENTIFY);
1392 silc_buffer_free(tmpbuf);
1401 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1402 SilcClientEntry *clients,
1403 uint32 clients_count,
1406 SilcServer server = cmd->server;
1409 SilcBuffer packet, idp;
1410 SilcClientEntry entry;
1411 SilcCommandStatus status;
1412 uint16 ident = silc_command_get_ident(cmd->payload);
1413 char nh[256], uh[256];
1414 SilcSocketConnection hsock;
1417 for (i = 0; i < clients_count; i++)
1418 if (clients[i]->data.registered)
1421 status = SILC_STATUS_OK;
1423 status = SILC_STATUS_LIST_START;
1425 for (i = 0, k = 0; i < clients_count; i++) {
1428 if (entry->data.registered == FALSE) {
1429 if (clients_count == 1) {
1430 SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1431 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1432 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1433 2, idp->data, idp->len);
1434 silc_buffer_free(idp);
1440 status = SILC_STATUS_LIST_ITEM;
1442 if (clients_count > 1 && k == clients_count - 1)
1443 status = SILC_STATUS_LIST_END;
1445 if (count && k - 1 == count)
1446 status = SILC_STATUS_LIST_END;
1448 if (count && k - 1 > count)
1451 /* Send IDENTIFY reply */
1452 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1453 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1455 memset(uh, 0, sizeof(uh));
1456 memset(nh, 0, sizeof(nh));
1458 strncat(nh, entry->nickname, strlen(entry->nickname));
1459 if (!strchr(entry->nickname, '@')) {
1460 strncat(nh, "@", 1);
1461 if (entry->servername) {
1462 strncat(nh, entry->servername, strlen(entry->servername));
1464 len = entry->router ? strlen(entry->router->server_name) :
1465 strlen(server->server_name);
1466 strncat(nh, entry->router ? entry->router->server_name :
1467 server->server_name, len);
1471 if (!entry->username) {
1472 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1474 2, idp->data, idp->len,
1477 strncat(uh, entry->username, strlen(entry->username));
1478 if (!strchr(entry->username, '@')) {
1479 strncat(uh, "@", 1);
1480 hsock = (SilcSocketConnection)entry->connection;
1481 len = strlen(hsock->hostname);
1482 strncat(uh, hsock->hostname, len);
1485 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1487 2, idp->data, idp->len,
1492 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1493 0, packet->data, packet->len, FALSE);
1495 silc_buffer_free(packet);
1496 silc_buffer_free(idp);
1503 silc_server_command_identify_from_client(SilcServerCommandContext cmd)
1505 SilcServer server = cmd->server;
1506 char *nick = NULL, *server_name = NULL;
1508 SilcClientEntry *clients = NULL, entry;
1509 SilcClientID **client_id = NULL;
1510 uint32 client_id_count = 0, clients_count = 0;
1513 /* Protocol dictates that we must always send the received IDENTIFY request
1514 to our router if we are normal server, so let's do it now unless we
1515 are standalone. We will not send any replies to the client until we
1516 have received reply from the router. */
1517 if (server->server_type == SILC_SERVER &&
1518 !cmd->pending && !server->standalone) {
1522 old_ident = silc_command_get_ident(cmd->payload);
1523 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1524 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1526 /* Send IDENTIFY command to our router */
1527 silc_server_packet_send(server, (SilcSocketConnection)
1528 server->router->connection,
1529 SILC_PACKET_COMMAND, cmd->packet->flags,
1530 tmpbuf->data, tmpbuf->len, TRUE);
1532 /* Reprocess this packet after received reply from router */
1533 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1534 silc_command_get_ident(cmd->payload),
1535 silc_server_command_destructor,
1536 silc_server_command_identify,
1537 silc_server_command_dup(cmd));
1538 cmd->pending = TRUE;
1540 silc_command_set_ident(cmd->payload, old_ident);
1542 silc_buffer_free(tmpbuf);
1547 /* We are ready to process the command request. Let's search for the
1548 requested client and send reply to the requesting client. */
1550 /* Parse the IDENTIFY request */
1551 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1552 &nick, &server_name, &count,
1553 SILC_COMMAND_IDENTIFY))
1556 /* Get all clients matching that ID or nickname from local list */
1557 if (client_id_count) {
1558 /* Check all Client ID's received in the command packet */
1559 for (i = 0; i < client_id_count; i++) {
1560 entry = silc_idlist_find_client_by_id(server->local_list,
1561 client_id[i], NULL);
1563 clients = silc_realloc(clients, sizeof(*clients) *
1564 (clients_count + 1));
1565 clients[clients_count++] = entry;
1569 if (!silc_idlist_get_clients_by_hash(server->local_list,
1570 nick, server->md5hash,
1571 &clients, &clients_count))
1572 silc_idlist_get_clients_by_nickname(server->local_list,
1574 &clients, &clients_count);
1577 /* Check global list as well */
1578 if (client_id_count) {
1579 /* Check all Client ID's received in the command packet */
1580 for (i = 0; i < client_id_count; i++) {
1581 entry = silc_idlist_find_client_by_id(server->global_list,
1582 client_id[i], NULL);
1584 clients = silc_realloc(clients, sizeof(*clients) *
1585 (clients_count + 1));
1586 clients[clients_count++] = entry;
1590 if (!silc_idlist_get_clients_by_hash(server->global_list,
1591 nick, server->md5hash,
1592 &clients, &clients_count))
1593 silc_idlist_get_clients_by_nickname(server->global_list,
1595 &clients, &clients_count);
1599 /* Such a client really does not exist in the SILC network. */
1600 if (!client_id_count) {
1601 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1602 SILC_STATUS_ERR_NO_SUCH_NICK,
1603 3, nick, strlen(nick));
1605 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1606 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1607 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1608 2, idp->data, idp->len);
1609 silc_buffer_free(idp);
1614 /* Check that all mandatory fields are present and request those data
1615 from the server who owns the client if necessary. */
1616 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1621 /* Send the command reply to the client */
1622 silc_server_command_identify_send_reply(cmd, clients, clients_count,
1626 if (client_id_count) {
1627 for (i = 0; i < client_id_count; i++)
1628 silc_free(client_id[i]);
1629 silc_free(client_id);
1636 silc_free(server_name);
1642 silc_server_command_identify_from_server(SilcServerCommandContext cmd)
1644 SilcServer server = cmd->server;
1645 char *nick = NULL, *server_name = NULL;
1647 SilcClientEntry *clients = NULL, entry;
1648 SilcClientID **client_id = NULL;
1649 uint32 client_id_count = 0, clients_count = 0;
1652 /* Parse the IDENTIFY request */
1653 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1654 &nick, &server_name, &count,
1655 SILC_COMMAND_IDENTIFY))
1658 /* Process the command request. Let's search for the requested client and
1659 send reply to the requesting server. */
1661 if (client_id_count) {
1662 /* Check all Client ID's received in the command packet */
1663 for (i = 0; i < client_id_count; i++) {
1664 entry = silc_idlist_find_client_by_id(server->local_list,
1665 client_id[i], NULL);
1667 clients = silc_realloc(clients, sizeof(*clients) *
1668 (clients_count + 1));
1669 clients[clients_count++] = entry;
1673 if (!silc_idlist_get_clients_by_hash(server->local_list,
1674 nick, server->md5hash,
1675 &clients, &clients_count))
1676 silc_idlist_get_clients_by_nickname(server->local_list,
1678 &clients, &clients_count);
1681 /* If we are router we will check our global list as well. */
1682 if (server->server_type == SILC_ROUTER) {
1683 if (client_id_count) {
1684 /* Check all Client ID's received in the command packet */
1685 for (i = 0; i < client_id_count; i++) {
1686 entry = silc_idlist_find_client_by_id(server->global_list,
1687 client_id[i], NULL);
1689 clients = silc_realloc(clients, sizeof(*clients) *
1690 (clients_count + 1));
1691 clients[clients_count++] = entry;
1695 if (!silc_idlist_get_clients_by_hash(server->global_list,
1696 nick, server->md5hash,
1697 &clients, &clients_count))
1698 silc_idlist_get_clients_by_nickname(server->global_list,
1700 &clients, &clients_count);
1705 /* Such a client really does not exist in the SILC network. */
1706 if (!client_id_count) {
1707 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1708 SILC_STATUS_ERR_NO_SUCH_NICK,
1709 3, nick, strlen(nick));
1711 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1712 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1713 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1714 2, idp->data, idp->len);
1715 silc_buffer_free(idp);
1720 /* Check that all mandatory fields are present and request those data
1721 from the server who owns the client if necessary. */
1722 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1727 /* Send the command reply */
1728 silc_server_command_identify_send_reply(cmd, clients, clients_count, count);
1731 if (client_id_count) {
1732 for (i = 0; i < client_id_count; i++)
1733 silc_free(client_id[i]);
1734 silc_free(client_id);
1741 silc_free(server_name);
1746 SILC_SERVER_CMD_FUNC(identify)
1748 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1751 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1753 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1754 ret = silc_server_command_identify_from_client(cmd);
1755 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) |
1756 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1757 ret = silc_server_command_identify_from_server(cmd);
1760 silc_server_command_free(cmd);
1763 /* Checks string for bad characters and returns TRUE if they are found. */
1765 static int silc_server_command_bad_chars(char *nick)
1767 if (strchr(nick, '\\')) return TRUE;
1768 if (strchr(nick, '\"')) return TRUE;
1769 if (strchr(nick, '´')) return TRUE;
1770 if (strchr(nick, '`')) return TRUE;
1771 if (strchr(nick, '\'')) return TRUE;
1772 if (strchr(nick, '*')) return TRUE;
1773 if (strchr(nick, '/')) return TRUE;
1774 if (strchr(nick, '@')) return TRUE;
1779 /* Server side of command NICK. Sets nickname for user. Setting
1780 nickname causes generation of a new client ID for the client. The
1781 new client ID is sent to the client after changing the nickname. */
1783 SILC_SERVER_CMD_FUNC(nick)
1785 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1786 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1787 SilcServer server = cmd->server;
1788 SilcBuffer packet, nidp, oidp;
1789 SilcClientID *new_id;
1791 uint16 ident = silc_command_get_ident(cmd->payload);
1793 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1796 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
1798 /* Check nickname */
1799 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1800 if (silc_server_command_bad_chars(nick) == TRUE) {
1801 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1802 SILC_STATUS_ERR_BAD_NICKNAME);
1806 if (strlen(nick) > 128)
1809 /* Create new Client ID */
1810 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
1811 cmd->server->md5hash, nick,
1814 /* Send notify about nickname change to our router. We send the new
1815 ID and ask to replace it with the old one. If we are router the
1816 packet is broadcasted. Send NICK_CHANGE notify. */
1817 if (!server->standalone)
1818 silc_server_send_notify_nick_change(server, server->router->connection,
1819 server->server_type == SILC_SERVER ?
1820 FALSE : TRUE, client->id,
1823 /* Remove old cache entry */
1824 silc_idcache_del_by_context(server->local_list->clients, client);
1826 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1830 silc_free(client->id);
1832 /* Save the nickname as this client is our local client */
1833 if (client->nickname)
1834 silc_free(client->nickname);
1836 client->nickname = strdup(nick);
1837 client->id = new_id;
1839 /* Update client cache */
1840 silc_idcache_add(server->local_list->clients, client->nickname,
1841 client->id, (void *)client, FALSE);
1843 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1845 /* Send NICK_CHANGE notify to the client's channels */
1846 silc_server_send_notify_on_channels(server, NULL, client,
1847 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1848 oidp->data, oidp->len,
1849 nidp->data, nidp->len);
1851 /* Send the new Client ID as reply command back to client */
1852 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
1853 SILC_STATUS_OK, ident, 1,
1854 2, nidp->data, nidp->len);
1855 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1856 0, packet->data, packet->len, FALSE);
1858 silc_buffer_free(packet);
1859 silc_buffer_free(nidp);
1860 silc_buffer_free(oidp);
1863 silc_server_command_free(cmd);
1866 /* Sends the LIST command reply */
1869 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
1870 SilcChannelEntry *lch,
1872 SilcChannelEntry *gch,
1876 SilcBuffer packet, idp;
1877 SilcChannelEntry entry;
1878 SilcCommandStatus status;
1879 uint16 ident = silc_command_get_ident(cmd->payload);
1881 unsigned char usercount[4];
1884 for (i = 0; i < lch_count; i++)
1885 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
1887 for (i = 0; i < gch_count; i++)
1888 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
1891 status = SILC_STATUS_OK;
1892 if ((lch_count + gch_count) > 1)
1893 status = SILC_STATUS_LIST_START;
1896 for (i = 0; i < lch_count; i++) {
1903 status = SILC_STATUS_LIST_ITEM;
1905 if (i == lch_count - 1 && gch_count)
1907 if (lch_count > 1 && i == lch_count - 1)
1908 status = SILC_STATUS_LIST_END;
1910 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1912 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
1913 topic = "*private*";
1914 memset(usercount, 0, sizeof(usercount));
1916 topic = entry->topic;
1917 users = silc_hash_table_count(entry->user_list);
1918 SILC_PUT32_MSB(users, usercount);
1921 /* Send the reply */
1924 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1926 2, idp->data, idp->len,
1927 3, entry->channel_name,
1928 strlen(entry->channel_name),
1929 4, topic, strlen(topic),
1933 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1935 2, idp->data, idp->len,
1936 3, entry->channel_name,
1937 strlen(entry->channel_name),
1939 silc_server_packet_send(cmd->server, cmd->sock,
1940 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
1941 packet->len, FALSE);
1942 silc_buffer_free(packet);
1943 silc_buffer_free(idp);
1946 status = i ? SILC_STATUS_LIST_ITEM : SILC_STATUS_OK;
1949 for (i = 0; i < gch_count; i++) {
1956 status = SILC_STATUS_LIST_ITEM;
1958 if (gch_count > 1 && i == lch_count - 1)
1959 status = SILC_STATUS_LIST_END;
1961 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1963 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
1964 topic = "*private*";
1965 memset(usercount, 0, sizeof(usercount));
1967 topic = entry->topic;
1968 users = silc_hash_table_count(entry->user_list);
1969 SILC_PUT32_MSB(users, usercount);
1972 /* Send the reply */
1975 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1977 2, idp->data, idp->len,
1978 3, entry->channel_name,
1979 strlen(entry->channel_name),
1980 4, topic, strlen(topic),
1984 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1986 2, idp->data, idp->len,
1987 3, entry->channel_name,
1988 strlen(entry->channel_name),
1990 silc_server_packet_send(cmd->server, cmd->sock,
1991 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
1992 packet->len, FALSE);
1993 silc_buffer_free(packet);
1994 silc_buffer_free(idp);
1998 /* Server side of LIST command. This lists the channel of the requested
1999 server. Secret channels are not listed. */
2001 SILC_SERVER_CMD_FUNC(list)
2003 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2004 SilcServer server = cmd->server;
2005 SilcChannelID *channel_id = NULL;
2008 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2009 uint32 lch_count = 0, gch_count = 0;
2011 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 2);
2013 /* Get Channel ID */
2014 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2016 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2018 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2019 SILC_STATUS_ERR_NO_CHANNEL_ID);
2024 /* Get the channels from local list */
2025 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2028 /* Get the channels from global list if we are router */
2029 if (server->server_type == SILC_ROUTER)
2030 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2033 /* Send the reply */
2034 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2035 gchannels, gch_count);
2038 silc_server_command_free(cmd);
2041 /* Server side of TOPIC command. Sets topic for channel and/or returns
2042 current topic to client. */
2044 SILC_SERVER_CMD_FUNC(topic)
2046 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2047 SilcServer server = cmd->server;
2048 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2049 SilcChannelID *channel_id;
2050 SilcChannelEntry channel;
2051 SilcChannelClientEntry chl;
2052 SilcBuffer packet, idp;
2054 uint32 argc, tmp_len;
2055 uint16 ident = silc_command_get_ident(cmd->payload);
2057 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2059 argc = silc_argument_get_arg_num(cmd->args);
2061 /* Get Channel ID */
2062 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2064 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2065 SILC_STATUS_ERR_NO_CHANNEL_ID);
2068 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2070 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2071 SILC_STATUS_ERR_NO_CHANNEL_ID);
2075 /* Check whether the channel exists */
2076 channel = silc_idlist_find_channel_by_id(server->local_list,
2079 channel = silc_idlist_find_channel_by_id(server->global_list,
2082 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2083 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2090 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2092 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2093 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2097 if (strlen(tmp) > 256) {
2098 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2099 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2103 /* See whether the client is on channel and has rights to change topic */
2104 if (!silc_hash_table_find(channel->user_list, client, NULL,
2106 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2107 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2111 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2112 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2113 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2114 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2119 /* Set the topic for channel */
2121 silc_free(channel->topic);
2122 channel->topic = strdup(tmp);
2124 /* Send TOPIC_SET notify type to the network */
2125 if (!server->standalone)
2126 silc_server_send_notify_topic_set(server, server->router->connection,
2127 server->server_type == SILC_ROUTER ?
2128 TRUE : FALSE, channel, client->id,
2131 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2133 /* Send notify about topic change to all clients on the channel */
2134 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2135 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2136 idp->data, idp->len,
2137 channel->topic, strlen(channel->topic));
2138 silc_buffer_free(idp);
2141 /* Send the topic to client as reply packet */
2142 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2144 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2145 SILC_STATUS_OK, ident, 2,
2146 2, idp->data, idp->len,
2148 strlen(channel->topic));
2150 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2151 SILC_STATUS_OK, ident, 1,
2152 2, idp->data, idp->len);
2153 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2154 0, packet->data, packet->len, FALSE);
2156 silc_buffer_free(packet);
2157 silc_buffer_free(idp);
2158 silc_free(channel_id);
2161 silc_server_command_free(cmd);
2164 /* Server side of INVITE command. Invites some client to join some channel.
2165 This command is also used to manage the invite list of the channel. */
2167 SILC_SERVER_CMD_FUNC(invite)
2169 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2170 SilcServer server = cmd->server;
2171 SilcSocketConnection sock = cmd->sock, dest_sock;
2172 SilcChannelClientEntry chl;
2173 SilcClientEntry sender, dest;
2174 SilcClientID *dest_id = NULL;
2175 SilcChannelEntry channel;
2176 SilcChannelID *channel_id = NULL;
2177 SilcIDListData idata;
2178 SilcBuffer idp, idp2, packet;
2179 unsigned char *tmp, *add, *del;
2181 uint16 ident = silc_command_get_ident(cmd->payload);
2183 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2185 /* Get Channel ID */
2186 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2188 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2189 SILC_STATUS_ERR_NO_CHANNEL_ID);
2192 channel_id = silc_id_payload_parse_id(tmp, len);
2194 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2195 SILC_STATUS_ERR_NO_CHANNEL_ID);
2199 /* Get the channel entry */
2200 channel = silc_idlist_find_channel_by_id(server->local_list,
2203 channel = silc_idlist_find_channel_by_id(server->global_list,
2206 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2207 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2212 /* Check whether the sender of this command is on the channel. */
2213 sender = (SilcClientEntry)sock->user_data;
2214 if (!silc_server_client_on_channel(sender, channel)) {
2215 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2216 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2220 /* Check whether the channel is invite-only channel. If yes then the
2221 sender of this command must be at least channel operator. */
2222 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2223 silc_hash_table_find(channel->user_list, sender, NULL, (void *)&chl);
2224 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2225 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2226 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2231 /* Get destination client ID */
2232 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2236 dest_id = silc_id_payload_parse_id(tmp, len);
2238 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2239 SILC_STATUS_ERR_NO_CLIENT_ID);
2243 /* Get the client entry */
2244 dest = silc_server_get_client_resolve(server, dest_id);
2246 if (server->server_type == SILC_ROUTER) {
2247 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2248 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2252 /* The client info is being resolved. Reprocess this packet after
2253 receiving the reply to the query. */
2254 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2256 silc_server_command_destructor,
2257 silc_server_command_invite,
2258 silc_server_command_dup(cmd));
2259 cmd->pending = TRUE;
2260 silc_free(channel_id);
2265 /* Check whether the requested client is already on the channel. */
2266 if (silc_server_client_on_channel(dest, channel)) {
2267 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2268 SILC_STATUS_ERR_USER_ON_CHANNEL);
2272 /* Get route to the client */
2273 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2275 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2276 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2280 memset(invite, 0, sizeof(invite));
2281 strncat(invite, dest->nickname, strlen(dest->nickname));
2282 strncat(invite, "!", 1);
2283 strncat(invite, dest->username, strlen(dest->username));
2284 if (!strchr(dest->username, '@')) {
2285 strncat(invite, "@", 1);
2286 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2289 len = strlen(invite);
2290 if (!channel->invite_list)
2291 channel->invite_list = silc_calloc(len + 2,
2292 sizeof(*channel->invite_list));
2294 channel->invite_list = silc_realloc(channel->invite_list,
2295 sizeof(*channel->invite_list) *
2297 strlen(channel->invite_list) + 2));
2298 strncat(channel->invite_list, invite, len);
2299 strncat(channel->invite_list, ",", 1);
2301 /* Send notify to the client that is invited to the channel */
2302 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2303 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2304 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2306 SILC_NOTIFY_TYPE_INVITE, 3,
2307 idp->data, idp->len,
2308 channel->channel_name,
2309 strlen(channel->channel_name),
2310 idp2->data, idp2->len);
2311 silc_buffer_free(idp);
2312 silc_buffer_free(idp2);
2315 /* Add the client to the invite list of the channel */
2316 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2318 if (!channel->invite_list)
2319 channel->invite_list = silc_calloc(len + 2,
2320 sizeof(*channel->invite_list));
2322 channel->invite_list = silc_realloc(channel->invite_list,
2323 sizeof(*channel->invite_list) *
2325 strlen(channel->invite_list) + 2));
2326 if (add[len - 1] == ',')
2327 add[len - 1] = '\0';
2329 strncat(channel->invite_list, add, len);
2330 strncat(channel->invite_list, ",", 1);
2333 /* Get the invite to be removed and remove it from the list */
2334 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2335 if (del && channel->invite_list) {
2336 char *start, *end, *n;
2338 if (!strncmp(channel->invite_list, del,
2339 strlen(channel->invite_list) - 1)) {
2340 silc_free(channel->invite_list);
2341 channel->invite_list = NULL;
2343 start = strstr(channel->invite_list, del);
2344 if (start && strlen(start) >= len) {
2346 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2347 strncat(n, channel->invite_list, start - channel->invite_list);
2348 strncat(n, end + 1, ((channel->invite_list +
2349 strlen(channel->invite_list)) - end) - 1);
2350 silc_free(channel->invite_list);
2351 channel->invite_list = n;
2356 /* Send notify to the primary router */
2357 if (!server->standalone)
2358 silc_server_send_notify_invite(server, server->router->connection,
2359 server->server_type == SILC_ROUTER ?
2360 TRUE : FALSE, channel,
2361 sender->id, add, del);
2363 /* Send command reply */
2364 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2368 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2369 SILC_STATUS_OK, ident, 2,
2371 3, channel->invite_list,
2372 channel->invite_list ?
2373 strlen(channel->invite_list) : 0);
2376 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2377 SILC_STATUS_OK, ident, 1,
2379 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2380 packet->data, packet->len, FALSE);
2381 silc_buffer_free(packet);
2387 silc_free(channel_id);
2388 silc_server_command_free(cmd);
2393 SilcSocketConnection sock;
2397 /* Quits connection to client. This gets called if client won't
2398 close the connection even when it has issued QUIT command. */
2400 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2402 QuitInternal q = (QuitInternal)context;
2404 /* Free all client specific data, such as client entry and entires
2405 on channels this client may be on. */
2406 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2408 q->sock->user_data = NULL;
2410 /* Close the connection on our side */
2411 silc_server_close_connection(q->server, q->sock);
2413 silc_free(q->signoff);
2417 /* Quits SILC session. This is the normal way to disconnect client. */
2419 SILC_SERVER_CMD_FUNC(quit)
2421 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2422 SilcServer server = cmd->server;
2423 SilcSocketConnection sock = cmd->sock;
2425 unsigned char *tmp = NULL;
2428 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2430 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2433 /* Get destination ID */
2434 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2438 q = silc_calloc(1, sizeof(*q));
2441 q->signoff = tmp ? strdup(tmp) : NULL;
2443 /* We quit the connection with little timeout */
2444 silc_task_register(server->timeout_queue, sock->sock,
2445 silc_server_command_quit_cb, (void *)q,
2446 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2449 silc_server_command_free(cmd);
2452 /* Server side of command KILL. This command is used by router operator
2453 to remove an client from the SILC Network temporarily. */
2455 SILC_SERVER_CMD_FUNC(kill)
2457 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2458 SilcServer server = cmd->server;
2459 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2460 SilcClientEntry remote_client;
2461 SilcClientID *client_id;
2462 unsigned char *tmp, *comment;
2463 uint32 tmp_len, tmp_len2;
2465 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2467 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2470 /* KILL command works only on router */
2471 if (server->server_type != SILC_ROUTER) {
2472 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2473 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2477 /* Check whether client has the permissions. */
2478 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2479 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2480 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2484 /* Get the client ID */
2485 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2487 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2488 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2491 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2493 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2494 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2498 /* Get the client entry */
2499 remote_client = silc_idlist_find_client_by_id(server->local_list,
2501 if (!remote_client) {
2502 remote_client = silc_idlist_find_client_by_id(server->global_list,
2504 if (!remote_client) {
2505 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2506 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2511 if (remote_client->data.registered == FALSE) {
2512 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2513 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2518 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2522 /* Send reply to the sender */
2523 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2526 /* Send the KILL notify packets. First send it to the channel, then
2527 to our primary router and then directly to the client who is being
2528 killed right now. */
2530 /* Send KILLED notify to the channels. It is not sent to the client
2531 as it will be sent differently destined directly to the client and not
2533 silc_server_send_notify_on_channels(server, remote_client,
2534 remote_client, SILC_NOTIFY_TYPE_KILLED,
2537 comment, comment ? tmp_len2 : 0);
2539 /* Send KILLED notify to primary route */
2540 if (!server->standalone)
2541 silc_server_send_notify_killed(server, server->router->connection, TRUE,
2542 remote_client->id, comment);
2544 /* Send KILLED notify to the client directly */
2545 silc_server_send_notify_killed(server, remote_client->connection ?
2546 remote_client->connection :
2547 remote_client->router->connection, FALSE,
2548 remote_client->id, comment);
2550 /* Remove the client from all channels. This generates new keys to the
2551 channels as well. */
2552 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2555 /* Remove the client entry, If it is locally connected then we will also
2556 disconnect the client here */
2557 if (remote_client->data.registered && remote_client->connection) {
2558 /* Remove locally conneted client */
2559 SilcSocketConnection sock = remote_client->connection;
2560 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2561 silc_server_close_connection(server, sock);
2563 /* Remove remote client */
2564 if (!silc_idlist_del_client(server->global_list, remote_client))
2565 silc_idlist_del_client(server->local_list, remote_client);
2569 silc_server_command_free(cmd);
2572 /* Server side of command INFO. This sends information about us to
2573 the client. If client requested specific server we will send the
2574 command to that server. */
2576 SILC_SERVER_CMD_FUNC(info)
2578 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2579 SilcServer server = cmd->server;
2580 SilcBuffer packet, idp;
2583 char *dest_server, *server_info = NULL, *server_name;
2584 uint16 ident = silc_command_get_ident(cmd->payload);
2585 SilcServerEntry entry = NULL;
2586 SilcServerID *server_id = NULL;
2588 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2590 /* Get server name */
2591 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2594 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2596 server_id = silc_id_payload_parse_id(tmp, tmp_len);
2598 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2599 SILC_STATUS_ERR_NO_SERVER_ID);
2605 /* Check whether we have this server cached */
2606 entry = silc_idlist_find_server_by_id(server->local_list,
2609 entry = silc_idlist_find_server_by_id(server->global_list,
2611 if (!entry && server->server_type == SILC_ROUTER) {
2612 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2613 SILC_STATUS_ERR_NO_SUCH_SERVER);
2619 if ((!dest_server && !server_id) ||
2620 (dest_server && !cmd->pending &&
2621 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2622 /* Send our reply */
2623 char info_string[256];
2625 memset(info_string, 0, sizeof(info_string));
2626 snprintf(info_string, sizeof(info_string),
2627 "location: %s server: %s admin: %s <%s>",
2628 server->config->admin_info->location,
2629 server->config->admin_info->server_type,
2630 server->config->admin_info->admin_name,
2631 server->config->admin_info->admin_email);
2633 server_info = info_string;
2634 entry = server->id_entry;
2636 /* Check whether we have this server cached */
2637 if (!entry && dest_server) {
2638 entry = silc_idlist_find_server_by_name(server->global_list,
2641 entry = silc_idlist_find_server_by_name(server->local_list,
2646 if (!cmd->pending &&
2647 server->server_type == SILC_ROUTER && entry && !entry->server_info) {
2648 /* Send to the server */
2652 old_ident = silc_command_get_ident(cmd->payload);
2653 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2654 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2656 silc_server_packet_send(server, entry->connection,
2657 SILC_PACKET_COMMAND, cmd->packet->flags,
2658 tmpbuf->data, tmpbuf->len, TRUE);
2660 /* Reprocess this packet after received reply from router */
2661 silc_server_command_pending(server, SILC_COMMAND_INFO,
2662 silc_command_get_ident(cmd->payload),
2663 silc_server_command_destructor,
2664 silc_server_command_info,
2665 silc_server_command_dup(cmd));
2666 cmd->pending = TRUE;
2667 silc_command_set_ident(cmd->payload, old_ident);
2668 silc_buffer_free(tmpbuf);
2672 if (!entry && !cmd->pending && !server->standalone) {
2673 /* Send to the primary router */
2677 old_ident = silc_command_get_ident(cmd->payload);
2678 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2679 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2681 silc_server_packet_send(server, server->router->connection,
2682 SILC_PACKET_COMMAND, cmd->packet->flags,
2683 tmpbuf->data, tmpbuf->len, TRUE);
2685 /* Reprocess this packet after received reply from router */
2686 silc_server_command_pending(server, SILC_COMMAND_INFO,
2687 silc_command_get_ident(cmd->payload),
2688 silc_server_command_destructor,
2689 silc_server_command_info,
2690 silc_server_command_dup(cmd));
2691 cmd->pending = TRUE;
2692 silc_command_set_ident(cmd->payload, old_ident);
2693 silc_buffer_free(tmpbuf);
2699 silc_free(server_id);
2702 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2703 SILC_STATUS_ERR_NO_SUCH_SERVER);
2707 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2709 server_info = entry->server_info;
2710 server_name = entry->server_name;
2712 /* Send the reply */
2714 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2715 SILC_STATUS_OK, ident, 3,
2716 2, idp->data, idp->len,
2718 strlen(server_name),
2720 strlen(server_info));
2722 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2723 SILC_STATUS_OK, ident, 2,
2724 2, idp->data, idp->len,
2726 strlen(server_name));
2727 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2728 packet->data, packet->len, FALSE);
2730 silc_buffer_free(packet);
2731 silc_buffer_free(idp);
2734 silc_server_command_free(cmd);
2737 /* Server side of command PING. This just replies to the ping. */
2739 SILC_SERVER_CMD_FUNC(ping)
2741 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2742 SilcServer server = cmd->server;
2747 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
2750 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2752 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2753 SILC_STATUS_ERR_NO_SERVER_ID);
2756 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2760 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2761 /* Send our reply */
2762 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2765 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2766 SILC_STATUS_ERR_NO_SUCH_SERVER);
2773 silc_server_command_free(cmd);
2776 /* Internal routine to join channel. The channel sent to this function
2777 has been either created or resolved from ID lists. This joins the sent
2778 client to the channel. */
2780 static void silc_server_command_join_channel(SilcServer server,
2781 SilcServerCommandContext cmd,
2782 SilcChannelEntry channel,
2783 SilcClientID *client_id,
2787 SilcSocketConnection sock = cmd->sock;
2789 uint32 tmp_len, user_count;
2790 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
2791 SilcClientEntry client;
2792 SilcChannelClientEntry chl;
2793 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
2794 uint16 ident = silc_command_get_ident(cmd->payload);
2795 char check[512], check2[512];
2797 SILC_LOG_DEBUG(("Start"));
2802 /* Get the client entry */
2803 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2804 client = (SilcClientEntry)sock->user_data;
2806 client = silc_server_get_client_resolve(server, client_id);
2811 /* The client info is being resolved. Reprocess this packet after
2812 receiving the reply to the query. */
2813 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2814 server->cmd_ident, NULL,
2815 silc_server_command_join,
2816 silc_server_command_dup(cmd));
2817 cmd->pending = TRUE;
2821 cmd->pending = FALSE;
2825 * Check channel modes
2828 memset(check, 0, sizeof(check));
2829 memset(check2, 0, sizeof(check2));
2830 strncat(check, client->nickname, strlen(client->nickname));
2831 strncat(check, "!", 1);
2832 strncat(check, client->username, strlen(client->username));
2833 if (!strchr(client->username, '@')) {
2834 strncat(check, "@", 1);
2835 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
2838 strncat(check2, client->nickname, strlen(client->nickname));
2839 if (!strchr(client->nickname, '@')) {
2840 strncat(check2, "@", 1);
2841 strncat(check2, server->server_name, strlen(server->server_name));
2843 strncat(check2, "!", 1);
2844 strncat(check2, client->username, strlen(client->username));
2845 if (!strchr(client->username, '@')) {
2846 strncat(check2, "@", 1);
2847 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
2850 /* Check invite list if channel is invite-only channel */
2851 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2852 if (!channel->invite_list ||
2853 (!silc_string_match(channel->invite_list, check) &&
2854 !silc_string_match(channel->invite_list, check2))) {
2855 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2856 SILC_STATUS_ERR_NOT_INVITED);
2861 /* Check ban list if it exists. If the client's nickname, server,
2862 username and/or hostname is in the ban list the access to the
2863 channel is denied. */
2864 if (channel->ban_list) {
2865 if (silc_string_match(channel->ban_list, check) ||
2866 silc_string_match(channel->ban_list, check2)) {
2867 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2868 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
2873 /* Get passphrase */
2874 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2876 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
2877 memcpy(passphrase, tmp, tmp_len);
2880 /* Check the channel passphrase if set. */
2881 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2882 if (!passphrase || memcmp(channel->passphrase, passphrase,
2883 strlen(channel->passphrase))) {
2884 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2885 SILC_STATUS_ERR_BAD_PASSWORD);
2890 /* Check user count limit if set. */
2891 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
2892 if (silc_hash_table_count(channel->user_list) + 1 >
2893 channel->user_limit) {
2894 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2895 SILC_STATUS_ERR_CHANNEL_IS_FULL);
2901 * Client is allowed to join to the channel. Make it happen.
2904 /* Check whether the client already is on the channel */
2905 if (silc_server_client_on_channel(client, channel)) {
2906 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2907 SILC_STATUS_ERR_USER_ON_CHANNEL);
2911 /* Generate new channel key as protocol dictates */
2912 if ((!created && silc_hash_table_count(channel->user_list) > 0) ||
2913 !channel->channel_key)
2914 silc_server_create_channel_key(server, channel, 0);
2916 /* Send the channel key. This is broadcasted to the channel but is not
2917 sent to the client who is joining to the channel. */
2918 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
2919 silc_server_send_channel_key(server, NULL, channel,
2920 server->server_type == SILC_ROUTER ?
2921 FALSE : !server->standalone);
2923 /* Join the client to the channel by adding it to channel's user list.
2924 Add also the channel to client entry's channels list for fast cross-
2926 chl = silc_calloc(1, sizeof(*chl));
2928 chl->client = client;
2929 chl->channel = channel;
2930 silc_hash_table_add(channel->user_list, client, chl);
2931 silc_hash_table_add(client->channels, channel, chl);
2933 /* Get users on the channel */
2934 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
2937 /* Encode Client ID Payload of the original client who wants to join */
2938 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2940 /* Encode command reply packet */
2941 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2942 SILC_PUT32_MSB(channel->mode, mode);
2943 SILC_PUT32_MSB(created, tmp2);
2944 SILC_PUT32_MSB(user_count, tmp3);
2946 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
2947 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
2948 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
2949 strlen(channel->channel_key->
2951 channel->channel_key->cipher->name,
2952 channel->key_len / 8, channel->key);
2957 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2958 SILC_STATUS_OK, ident, 13,
2959 2, channel->channel_name,
2960 strlen(channel->channel_name),
2961 3, chidp->data, chidp->len,
2962 4, clidp->data, clidp->len,
2965 7, keyp ? keyp->data : NULL,
2966 keyp ? keyp->len : 0,
2967 8, channel->ban_list,
2969 strlen(channel->ban_list) : 0,
2970 9, channel->invite_list,
2971 channel->invite_list ?
2972 strlen(channel->invite_list) : 0,
2975 strlen(channel->topic) : 0,
2976 11, channel->hmac->hmac->name,
2977 strlen(channel->hmac->hmac->name),
2979 13, user_list->data, user_list->len,
2980 14, mode_list->data,
2983 /* Send command reply */
2984 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
2985 reply->data, reply->len, FALSE);
2987 if (!cmd->pending) {
2988 /* Send JOIN notify to locally connected clients on the channel */
2989 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2990 SILC_NOTIFY_TYPE_JOIN, 2,
2991 clidp->data, clidp->len,
2992 chidp->data, chidp->len);
2994 /* Send JOIN notify packet to our primary router */
2995 if (!server->standalone)
2996 silc_server_send_notify_join(server, server->router->connection,
2997 server->server_type == SILC_ROUTER ?
2998 TRUE : FALSE, channel, client->id);
3001 silc_buffer_free(reply);
3002 silc_buffer_free(clidp);
3003 silc_buffer_free(chidp);
3004 silc_buffer_free(keyp);
3005 silc_buffer_free(user_list);
3006 silc_buffer_free(mode_list);
3010 silc_free(passphrase);
3013 /* Server side of command JOIN. Joins client into requested channel. If
3014 the channel does not exist it will be created. */
3016 SILC_SERVER_CMD_FUNC(join)
3018 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3019 SilcServer server = cmd->server;
3021 char *tmp, *channel_name = NULL, *cipher, *hmac;
3022 SilcChannelEntry channel;
3024 int created = FALSE;
3025 SilcClientID *client_id;
3027 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 1, 4);
3029 /* Get channel name */
3030 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3032 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3033 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3038 if (strlen(channel_name) > 256)
3039 channel_name[255] = '\0';
3041 if (silc_server_command_bad_chars(channel_name) == TRUE) {
3042 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3043 SILC_STATUS_ERR_BAD_CHANNEL);
3047 /* Get Client ID of the client who is joining to the channel */
3048 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3050 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3051 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3054 client_id = silc_id_payload_parse_id(tmp, tmp_len);
3056 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3057 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3061 /* Get cipher and hmac name */
3062 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3063 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3065 /* See if the channel exists */
3066 channel = silc_idlist_find_channel_by_name(server->local_list,
3067 channel_name, NULL);
3069 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3070 /* If this is coming from client the Client ID in the command packet must
3071 be same as the client's ID. */
3072 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3073 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3074 if (!SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
3075 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3076 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3081 if (!channel || !channel->id) {
3082 /* Channel not found */
3084 /* If we are standalone server we don't have a router, we just create
3085 the channel by ourselves. */
3086 if (server->standalone) {
3087 channel = silc_server_create_new_channel(server, server->id, cipher,
3088 hmac, channel_name, TRUE);
3090 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3091 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3095 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3100 /* The channel does not exist on our server. If we are normal server
3101 we will send JOIN command to our router which will handle the
3102 joining procedure (either creates the channel if it doesn't exist
3103 or joins the client to it). */
3104 if (server->server_type == SILC_SERVER) {
3108 /* If this is pending command callback then we've resolved
3109 it and it didn't work, return since we've notified the
3110 client already in the command reply callback. */
3114 old_ident = silc_command_get_ident(cmd->payload);
3115 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3116 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3118 /* Send JOIN command to our router */
3119 silc_server_packet_send(server, (SilcSocketConnection)
3120 server->router->connection,
3121 SILC_PACKET_COMMAND, cmd->packet->flags,
3122 tmpbuf->data, tmpbuf->len, TRUE);
3124 /* Reprocess this packet after received reply from router */
3125 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3126 silc_command_get_ident(cmd->payload),
3127 silc_server_command_destructor,
3128 silc_server_command_join,
3129 silc_server_command_dup(cmd));
3130 cmd->pending = TRUE;
3134 /* We are router and the channel does not seem exist so we will check
3135 our global list as well for the channel. */
3136 channel = silc_idlist_find_channel_by_name(server->global_list,
3137 channel_name, NULL);
3139 /* Channel really does not exist, create it */
3140 channel = silc_server_create_new_channel(server, server->id, cipher,
3141 hmac, channel_name, TRUE);
3143 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3144 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3148 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3155 /* Channel not found */
3157 /* If the command came from router and/or we are normal server then
3158 something went wrong with the joining as the channel was not found.
3159 We can't do anything else but ignore this. */
3160 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3161 server->server_type == SILC_SERVER)
3164 /* We are router and the channel does not seem exist so we will check
3165 our global list as well for the channel. */
3166 channel = silc_idlist_find_channel_by_name(server->global_list,
3167 channel_name, NULL);
3169 /* Channel really does not exist, create it */
3170 channel = silc_server_create_new_channel(server, server->id, cipher,
3171 hmac, channel_name, TRUE);
3173 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3174 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3178 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3184 /* If the channel does not have global users and is also empty it means the
3185 channel was created globally (by our router) and the client will be the
3186 channel founder and operator. */
3187 if (!channel->global_users && !silc_hash_table_count(channel->user_list)) {
3188 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3189 created = TRUE; /* Created globally by our router */
3192 /* Join to the channel */
3193 silc_server_command_join_channel(server, cmd, channel, client_id,
3196 silc_free(client_id);
3199 silc_server_command_free(cmd);
3202 /* Server side of command MOTD. Sends server's current "message of the
3203 day" to the client. */
3205 SILC_SERVER_CMD_FUNC(motd)
3207 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3208 SilcServer server = cmd->server;
3209 SilcBuffer packet, idp;
3210 char *motd, *dest_server;
3212 uint16 ident = silc_command_get_ident(cmd->payload);
3214 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3216 /* Get server name */
3217 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3219 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3220 SILC_STATUS_ERR_NO_SUCH_SERVER);
3224 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3227 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3229 if (server->config && server->config->motd &&
3230 server->config->motd->motd_file) {
3232 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
3237 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3238 SILC_STATUS_OK, ident, 2,
3244 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3245 SILC_STATUS_OK, ident, 1,
3249 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3250 packet->data, packet->len, FALSE);
3251 silc_buffer_free(packet);
3252 silc_buffer_free(idp);
3254 SilcServerEntry entry;
3256 /* Check whether we have this server cached */
3257 entry = silc_idlist_find_server_by_name(server->global_list,
3260 entry = silc_idlist_find_server_by_name(server->local_list,
3264 if (server->server_type == SILC_ROUTER && !cmd->pending &&
3265 entry && !entry->motd) {
3266 /* Send to the server */
3270 old_ident = silc_command_get_ident(cmd->payload);
3271 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3272 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3274 silc_server_packet_send(server, entry->connection,
3275 SILC_PACKET_COMMAND, cmd->packet->flags,
3276 tmpbuf->data, tmpbuf->len, TRUE);
3278 /* Reprocess this packet after received reply from router */
3279 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3280 silc_command_get_ident(cmd->payload),
3281 silc_server_command_destructor,
3282 silc_server_command_motd,
3283 silc_server_command_dup(cmd));
3284 cmd->pending = TRUE;
3285 silc_command_set_ident(cmd->payload, old_ident);
3286 silc_buffer_free(tmpbuf);
3290 if (!entry && !cmd->pending && !server->standalone) {
3291 /* Send to the primary router */
3295 old_ident = silc_command_get_ident(cmd->payload);
3296 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3297 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3299 silc_server_packet_send(server, server->router->connection,
3300 SILC_PACKET_COMMAND, cmd->packet->flags,
3301 tmpbuf->data, tmpbuf->len, TRUE);
3303 /* Reprocess this packet after received reply from router */
3304 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3305 silc_command_get_ident(cmd->payload),
3306 silc_server_command_destructor,
3307 silc_server_command_motd,
3308 silc_server_command_dup(cmd));
3309 cmd->pending = TRUE;
3310 silc_command_set_ident(cmd->payload, old_ident);
3311 silc_buffer_free(tmpbuf);
3316 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3317 SILC_STATUS_ERR_NO_SUCH_SERVER);
3321 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3324 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3325 SILC_STATUS_OK, ident, 2,
3328 strlen(entry->motd));
3330 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3331 SILC_STATUS_OK, ident, 1,
3334 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3335 packet->data, packet->len, FALSE);
3336 silc_buffer_free(packet);
3337 silc_buffer_free(idp);
3341 silc_server_command_free(cmd);
3344 /* Server side of command UMODE. Client can use this command to set/unset
3345 user mode. Client actually cannot set itself to be as server/router
3346 operator so this can be used only to unset the modes. */
3348 SILC_SERVER_CMD_FUNC(umode)
3350 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3351 SilcServer server = cmd->server;
3352 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3354 unsigned char *tmp_mask;
3356 uint16 ident = silc_command_get_ident(cmd->payload);
3358 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3361 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 2, 2);
3363 /* Get the client's mode mask */
3364 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3366 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3367 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3370 SILC_GET32_MSB(mask, tmp_mask);
3376 if (mask & SILC_UMODE_SERVER_OPERATOR) {
3377 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR)) {
3378 /* Cannot operator mode */
3379 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3380 SILC_STATUS_ERR_PERM_DENIED);
3384 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
3385 /* Remove the server operator rights */
3386 client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3389 if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3390 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
3391 /* Cannot operator mode */
3392 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3393 SILC_STATUS_ERR_PERM_DENIED);
3397 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
3398 /* Remove the router operator rights */
3399 client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3402 if (mask & SILC_UMODE_GONE) {
3403 client->mode |= SILC_UMODE_GONE;
3405 if (client->mode & SILC_UMODE_GONE)
3406 /* Remove the gone status */
3407 client->mode &= ~SILC_UMODE_GONE;
3410 /* Send UMODE change to primary router */
3411 if (!server->standalone)
3412 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3413 client->id, client->mode);
3415 /* Send command reply to sender */
3416 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3417 SILC_STATUS_OK, ident, 1,
3419 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3420 packet->data, packet->len, FALSE);
3421 silc_buffer_free(packet);
3424 silc_server_command_free(cmd);
3427 /* Checks that client has rights to add or remove channel modes. If any
3428 of the checks fails FALSE is returned. */
3430 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3431 SilcChannelClientEntry client,
3434 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3435 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3437 /* Check whether has rights to change anything */
3438 if (!is_op && !is_fo)
3441 /* Check whether has rights to change everything */
3445 /* We know that client is channel operator, check that they are not
3446 changing anything that requires channel founder rights. Rest of the
3447 modes are available automatically for channel operator. */
3449 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3450 if (is_op && !is_fo)
3453 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3454 if (is_op && !is_fo)
3459 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3460 if (is_op && !is_fo)
3463 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3464 if (is_op && !is_fo)
3469 if (mode & SILC_CHANNEL_MODE_CIPHER) {
3470 if (is_op && !is_fo)
3473 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3474 if (is_op && !is_fo)
3479 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3480 if (is_op && !is_fo)
3483 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3484 if (is_op && !is_fo)
3492 /* Server side command of CMODE. Changes channel mode */
3494 SILC_SERVER_CMD_FUNC(cmode)
3496 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3497 SilcServer server = cmd->server;
3498 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3499 SilcIDListData idata = (SilcIDListData)client;
3500 SilcChannelID *channel_id;
3501 SilcChannelEntry channel;
3502 SilcChannelClientEntry chl;
3503 SilcBuffer packet, cidp;
3504 unsigned char *tmp, *tmp_id, *tmp_mask;
3505 char *cipher = NULL, *hmac = NULL;
3506 uint32 mode_mask, tmp_len, tmp_len2;
3507 uint16 ident = silc_command_get_ident(cmd->payload);
3509 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 2, 7);
3511 /* Get Channel ID */
3512 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3514 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3515 SILC_STATUS_ERR_NO_CHANNEL_ID);
3518 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3520 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3521 SILC_STATUS_ERR_NO_CHANNEL_ID);
3525 /* Get the channel mode mask */
3526 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3528 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3529 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3532 SILC_GET32_MSB(mode_mask, tmp_mask);
3534 /* Get channel entry */
3535 channel = silc_idlist_find_channel_by_id(server->local_list,
3538 channel = silc_idlist_find_channel_by_id(server->global_list,
3541 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3542 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3547 /* Check whether this client is on the channel */
3548 if (!silc_server_client_on_channel(client, channel)) {
3549 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3550 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3554 /* Get entry to the channel user list */
3555 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
3557 /* Check that client has rights to change any requested channel modes */
3558 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3559 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3560 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3565 * Check the modes. Modes that requires nothing special operation are
3569 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3570 /* Channel uses private keys to protect traffic. Client(s) has set the
3571 key locally they want to use, server does not know that key. */
3572 /* Nothing interesting to do here */
3574 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3575 /* The mode is removed and we need to generate and distribute
3576 new channel key. Clients are not using private channel keys
3577 anymore after this. */
3579 /* Re-generate channel key */
3580 silc_server_create_channel_key(server, channel, 0);
3582 /* Send the channel key. This sends it to our local clients and if
3583 we are normal server to our router as well. */
3584 silc_server_send_channel_key(server, NULL, channel,
3585 server->server_type == SILC_ROUTER ?
3586 FALSE : !server->standalone);
3588 cipher = channel->channel_key->cipher->name;
3589 hmac = channel->hmac->hmac->name;
3593 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3594 /* User limit is set on channel */
3597 /* Get user limit */
3598 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3600 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3601 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3602 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3606 SILC_GET32_MSB(user_limit, tmp);
3607 channel->user_limit = user_limit;
3610 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3611 /* User limit mode is unset. Remove user limit */
3612 channel->user_limit = 0;
3615 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3616 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3617 /* Passphrase has been set to channel */
3619 /* Get the passphrase */
3620 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3622 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3623 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3627 /* Save the passphrase */
3628 channel->passphrase = strdup(tmp);
3631 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3632 /* Passphrase mode is unset. remove the passphrase */
3633 if (channel->passphrase) {
3634 silc_free(channel->passphrase);
3635 channel->passphrase = NULL;
3640 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3641 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3642 /* Cipher to use protect the traffic */
3645 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3647 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3648 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3652 /* Delete old cipher and allocate the new one */
3653 silc_cipher_free(channel->channel_key);
3654 if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
3655 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3656 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3660 /* Re-generate channel key */
3661 silc_server_create_channel_key(server, channel, 0);
3663 /* Send the channel key. This sends it to our local clients and if
3664 we are normal server to our router as well. */
3665 silc_server_send_channel_key(server, NULL, channel,
3666 server->server_type == SILC_ROUTER ?
3667 FALSE : !server->standalone);
3670 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3671 /* Cipher mode is unset. Remove the cipher and revert back to
3673 cipher = channel->cipher;
3675 /* Delete old cipher and allocate default one */
3676 silc_cipher_free(channel->channel_key);
3677 if (!silc_cipher_alloc(cipher ? cipher : "aes-256-cbc",
3678 &channel->channel_key)) {
3679 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3680 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3684 /* Re-generate channel key */
3685 silc_server_create_channel_key(server, channel, 0);
3687 /* Send the channel key. This sends it to our local clients and if
3688 we are normal server to our router as well. */
3689 silc_server_send_channel_key(server, NULL, channel,
3690 server->server_type == SILC_ROUTER ?
3691 FALSE : !server->standalone);
3695 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3696 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3697 /* HMAC to use protect the traffic */
3698 unsigned char hash[32];
3701 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3703 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3704 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3708 /* Delete old hmac and allocate the new one */
3709 silc_hmac_free(channel->hmac);
3710 if (!silc_hmac_alloc(hmac, NULL, &channel->hmac)) {
3711 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3712 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3716 /* Set the HMAC key out of current channel key. The client must do
3718 silc_hash_make(channel->hmac->hash, channel->key, channel->key_len / 8,
3720 silc_hmac_set_key(channel->hmac, hash,
3721 silc_hash_len(channel->hmac->hash));
3722 memset(hash, 0, sizeof(hash));
3725 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
3726 /* Hmac mode is unset. Remove the hmac and revert back to
3728 unsigned char hash[32];
3729 hmac = channel->hmac_name;
3731 /* Delete old hmac and allocate default one */
3732 silc_hmac_free(channel->hmac);
3733 if (!silc_hmac_alloc(hmac ? hmac : "hmac-sha1-96", NULL,
3735 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3736 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3740 /* Set the HMAC key out of current channel key. The client must do
3742 silc_hash_make(channel->hmac->hash, channel->key, channel->key_len / 8,
3744 silc_hmac_set_key(channel->hmac, hash,
3745 silc_hash_len(channel->hmac->hash));
3746 memset(hash, 0, sizeof(hash));
3750 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3751 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3752 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
3753 /* Set the founder authentication */
3754 SilcAuthPayload auth;
3756 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
3758 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3759 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3763 auth = silc_auth_payload_parse(tmp, tmp_len);
3765 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3766 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3770 /* Save the public key */
3771 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
3772 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
3775 channel->founder_method = silc_auth_get_method(auth);
3777 if (channel->founder_method == SILC_AUTH_PASSWORD) {
3778 tmp = silc_auth_get_data(auth, &tmp_len);
3779 channel->founder_passwd =
3780 silc_calloc(tmp_len + 1, sizeof(*channel->founder_passwd));
3781 memcpy(channel->founder_passwd, tmp, tmp_len);
3782 channel->founder_passwd_len = tmp_len;
3785 silc_auth_payload_free(auth);
3789 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3790 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3791 if (channel->founder_key)
3792 silc_pkcs_public_key_free(channel->founder_key);
3793 if (channel->founder_passwd) {
3794 silc_free(channel->founder_passwd);
3795 channel->founder_passwd = NULL;
3801 /* Finally, set the mode */
3802 channel->mode = mode_mask;
3804 /* Send CMODE_CHANGE notify */
3805 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3806 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3807 SILC_NOTIFY_TYPE_CMODE_CHANGE, 4,
3808 cidp->data, cidp->len,
3810 cipher, cipher ? strlen(cipher) : 0,
3811 hmac, hmac ? strlen(hmac) : 0);
3813 /* Set CMODE notify type to network */
3814 if (!server->standalone)
3815 silc_server_send_notify_cmode(server, server->router->connection,
3816 server->server_type == SILC_ROUTER ?
3817 TRUE : FALSE, channel,
3818 mode_mask, client->id, SILC_ID_CLIENT,
3821 /* Send command reply to sender */
3822 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3823 SILC_STATUS_OK, ident, 2,
3824 2, tmp_id, tmp_len2,
3826 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3827 packet->data, packet->len, FALSE);
3829 silc_buffer_free(packet);
3830 silc_free(channel_id);
3834 silc_server_command_free(cmd);
3837 /* Server side of CUMODE command. Changes client's mode on a channel. */
3839 SILC_SERVER_CMD_FUNC(cumode)
3841 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3842 SilcServer server = cmd->server;
3843 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3844 SilcIDListData idata = (SilcIDListData)client;
3845 SilcChannelID *channel_id;
3846 SilcClientID *client_id;
3847 SilcChannelEntry channel;
3848 SilcClientEntry target_client;
3849 SilcChannelClientEntry chl;
3850 SilcBuffer packet, idp;
3851 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
3852 uint32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
3854 uint16 ident = silc_command_get_ident(cmd->payload);
3856 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
3858 /* Get Channel ID */
3859 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3861 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3862 SILC_STATUS_ERR_NO_CHANNEL_ID);
3865 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
3867 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3868 SILC_STATUS_ERR_NO_CHANNEL_ID);
3872 /* Get channel entry */
3873 channel = silc_idlist_find_channel_by_id(server->local_list,
3876 channel = silc_idlist_find_channel_by_id(server->global_list,
3879 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3880 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3885 /* Check whether sender is on the channel */
3886 if (!silc_server_client_on_channel(client, channel)) {
3887 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3888 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3892 /* Check that client has rights to change other's rights */
3893 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
3894 sender_mask = chl->mode;
3896 /* Get the target client's channel mode mask */
3897 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3899 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3900 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3903 SILC_GET32_MSB(target_mask, tmp_mask);
3905 /* Get target Client ID */
3906 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3908 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3909 SILC_STATUS_ERR_NO_CLIENT_ID);
3912 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
3914 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3915 SILC_STATUS_ERR_NO_CLIENT_ID);
3919 /* Get target client's entry */
3920 target_client = silc_idlist_find_client_by_id(server->local_list,
3922 if (!target_client) {
3923 target_client = silc_idlist_find_client_by_id(server->global_list,
3927 if (target_client != client &&
3928 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
3929 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
3930 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3931 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3935 /* Check whether target client is on the channel */
3936 if (target_client != client) {
3937 if (!silc_server_client_on_channel(target_client, channel)) {
3938 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3939 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
3943 /* Get entry to the channel user list */
3944 silc_hash_table_find(channel->user_list, target_client, NULL,
3952 /* If the target client is founder, no one else can change their mode
3954 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
3955 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3956 SILC_STATUS_ERR_NOT_YOU);
3960 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
3961 /* The client tries to claim the founder rights. */
3962 unsigned char *tmp_auth;
3963 uint32 tmp_auth_len, auth_len;
3966 if (target_client != client) {
3967 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3968 SILC_STATUS_ERR_NOT_YOU);
3972 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
3973 !channel->founder_key) {
3974 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3975 SILC_STATUS_ERR_NOT_YOU);
3979 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
3981 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3982 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3986 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
3987 (void *)channel->founder_passwd : (void *)channel->founder_key);
3988 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
3989 channel->founder_passwd_len : 0);
3991 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
3992 channel->founder_method, auth, auth_len,
3993 idata->hash, client->id, SILC_ID_CLIENT)) {
3994 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3995 SILC_STATUS_ERR_AUTH_FAILED);
3999 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4002 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4003 if (target_client == client) {
4004 /* Remove channel founder rights from itself */
4005 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4008 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4009 SILC_STATUS_ERR_NOT_YOU);
4015 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4016 /* Promote to operator */
4017 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4018 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4019 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4020 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4021 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4025 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4029 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4030 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4031 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4032 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4033 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4037 /* Demote to normal user */
4038 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4043 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4044 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4046 /* Send notify to channel, notify only if mode was actually changed. */
4048 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4049 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4050 idp->data, idp->len,
4054 /* Set CUMODE notify type to network */
4055 if (!server->standalone)
4056 silc_server_send_notify_cumode(server, server->router->connection,
4057 server->server_type == SILC_ROUTER ?
4058 TRUE : FALSE, channel,
4059 target_mask, client->id,
4064 /* Send command reply to sender */
4065 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4066 SILC_STATUS_OK, ident, 3,
4068 3, tmp_ch_id, tmp_ch_len,
4069 4, tmp_id, tmp_len);
4070 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4071 packet->data, packet->len, FALSE);
4073 silc_buffer_free(packet);
4074 silc_free(channel_id);
4075 silc_free(client_id);
4076 silc_buffer_free(idp);
4079 silc_server_command_free(cmd);
4082 /* Server side of KICK command. Kicks client out of channel. */
4084 SILC_SERVER_CMD_FUNC(kick)
4086 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4087 SilcServer server = cmd->server;
4088 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4089 SilcClientEntry target_client;
4090 SilcChannelID *channel_id;
4091 SilcClientID *client_id;
4092 SilcChannelEntry channel;
4093 SilcChannelClientEntry chl;
4096 unsigned char *tmp, *comment;
4098 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4100 /* Get Channel ID */
4101 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4103 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4104 SILC_STATUS_ERR_NO_CHANNEL_ID);
4107 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
4109 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4110 SILC_STATUS_ERR_NO_CHANNEL_ID);
4114 /* Get channel entry */
4115 channel = silc_idlist_find_channel_by_id(server->local_list,
4118 channel = silc_idlist_find_channel_by_id(server->local_list,
4121 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4122 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4127 /* Check whether sender is on the channel */
4128 if (!silc_server_client_on_channel(client, channel)) {
4129 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4130 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4134 /* Check that the kicker is channel operator or channel founder */
4135 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4136 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4137 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4138 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4142 /* Get target Client ID */
4143 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4145 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4146 SILC_STATUS_ERR_NO_CLIENT_ID);
4149 client_id = silc_id_payload_parse_id(tmp, tmp_len);
4151 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4152 SILC_STATUS_ERR_NO_CLIENT_ID);
4156 /* Get target client's entry */
4157 target_client = silc_idlist_find_client_by_id(server->local_list,
4159 if (!target_client) {
4160 target_client = silc_idlist_find_client_by_id(server->global_list,
4164 /* Check that the target client is not channel founder. Channel founder
4165 cannot be kicked from the channel. */
4166 silc_hash_table_find(channel->user_list, target_client, NULL, (void *)&chl);
4167 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4168 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4169 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4173 /* Check whether target client is on the channel */
4174 if (!silc_server_client_on_channel(target_client, channel)) {
4175 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4176 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4182 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4186 /* Send command reply to sender */
4187 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4190 /* Send KICKED notify to local clients on the channel */
4191 idp = silc_id_payload_encode(target_client->id, SILC_ID_CLIENT);
4192 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4193 SILC_NOTIFY_TYPE_KICKED,
4195 idp->data, idp->len,
4196 comment, comment ? strlen(comment) : 0);
4197 silc_buffer_free(idp);
4199 /* Remove the client from the channel. If the channel does not exist
4200 after removing the client then the client kicked itself off the channel
4201 and we don't have to send anything after that. */
4202 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4203 target_client, FALSE))
4206 /* Send KICKED notify to primary route */
4207 if (!server->standalone)
4208 silc_server_send_notify_kicked(server, server->router->connection,
4209 server->server_type == SILC_ROUTER ?
4210 TRUE : FALSE, channel,
4211 target_client->id, comment);
4213 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4214 /* Re-generate channel key */
4215 silc_server_create_channel_key(server, channel, 0);
4217 /* Send the channel key to the channel. The key of course is not sent
4218 to the client who was kicked off the channel. */
4219 silc_server_send_channel_key(server, target_client->connection, channel,
4220 server->server_type == SILC_ROUTER ?
4221 FALSE : !server->standalone);
4225 silc_server_command_free(cmd);
4228 /* Server side of OPER command. Client uses this comand to obtain server
4229 operator privileges to this server/router. */
4231 SILC_SERVER_CMD_FUNC(oper)
4233 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4234 SilcServer server = cmd->server;
4235 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4236 unsigned char *username, *auth;
4238 SilcServerConfigSectionAdminConnection *admin;
4239 SilcIDListData idata = (SilcIDListData)client;
4241 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4243 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4246 /* Get the username */
4247 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4249 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4250 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4254 /* Get the admin configuration */
4255 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4256 username, client->nickname);
4258 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4259 username, client->nickname);
4261 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4262 SILC_STATUS_ERR_AUTH_FAILED);
4267 /* Get the authentication payload */
4268 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4270 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4271 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4275 /* Verify the authentication data */
4276 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4277 admin->auth_data, admin->auth_data_len,
4278 idata->hash, client->id, SILC_ID_CLIENT)) {
4279 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4280 SILC_STATUS_ERR_AUTH_FAILED);
4284 /* Client is now server operator */
4285 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4287 /* Send UMODE change to primary router */
4288 if (!server->standalone)
4289 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4290 client->id, client->mode);
4292 /* Send reply to the sender */
4293 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4297 silc_server_command_free(cmd);
4300 /* Server side of SILCOPER command. Client uses this comand to obtain router
4301 operator privileges to this router. */
4303 SILC_SERVER_CMD_FUNC(silcoper)
4305 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4306 SilcServer server = cmd->server;
4307 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4308 unsigned char *username, *auth;
4310 SilcServerConfigSectionAdminConnection *admin;
4311 SilcIDListData idata = (SilcIDListData)client;
4313 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4315 if (server->server_type == SILC_SERVER)
4318 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4321 /* Get the username */
4322 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4324 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4325 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4329 /* Get the admin configuration */
4330 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4331 username, client->nickname);
4333 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4334 username, client->nickname);
4336 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4337 SILC_STATUS_ERR_AUTH_FAILED);
4342 /* Get the authentication payload */
4343 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4345 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4346 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4350 /* Verify the authentication data */
4351 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4352 admin->auth_data, admin->auth_data_len,
4353 idata->hash, client->id, SILC_ID_CLIENT)) {
4354 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4355 SILC_STATUS_ERR_AUTH_FAILED);
4359 /* Client is now router operator */
4360 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4362 /* Send UMODE change to primary router */
4363 if (!server->standalone)
4364 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4365 client->id, client->mode);
4367 /* Send reply to the sender */
4368 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4372 silc_server_command_free(cmd);
4375 /* Server side command of CONNECT. Connects us to the specified remote
4376 server or router. */
4378 SILC_SERVER_CMD_FUNC(connect)
4380 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4381 SilcServer server = cmd->server;
4382 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4383 unsigned char *tmp, *host;
4385 uint32 port = SILC_PORT;
4387 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CONNECT, cmd, 1, 2);
4389 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4392 /* Check whether client has the permissions. */
4393 if (client->mode == SILC_UMODE_NONE) {
4394 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4395 SILC_STATUS_ERR_NO_SERVER_PRIV);
4399 if (server->server_type == SILC_ROUTER &&
4400 client->mode & SILC_UMODE_SERVER_OPERATOR) {
4401 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4402 SILC_STATUS_ERR_NO_ROUTER_PRIV);
4406 /* Get the remote server */
4407 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4409 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4410 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4415 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4417 SILC_GET32_MSB(port, tmp);
4419 /* Create the connection. It is done with timeout and is async. */
4420 silc_server_create_connection(server, host, port);
4422 /* Send reply to the sender */
4423 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4427 silc_server_command_free(cmd);
4430 /* Server side of command BAN. This is used to manage the ban list of the
4431 channel. To add clients and remove clients from the ban list. */
4433 SILC_SERVER_CMD_FUNC(ban)
4435 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4436 SilcServer server = cmd->server;
4437 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4439 SilcChannelEntry channel;
4440 SilcChannelClientEntry chl;
4441 SilcChannelID *channel_id = NULL;
4442 unsigned char *id, *add, *del;
4443 uint32 id_len, tmp_len;
4444 uint16 ident = silc_command_get_ident(cmd->payload);
4446 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4449 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4451 /* Get Channel ID */
4452 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4454 channel_id = silc_id_payload_parse_id(id, id_len);
4456 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4457 SILC_STATUS_ERR_NO_CHANNEL_ID);
4462 /* Get channel entry. The server must know about the channel since the
4463 client is expected to be on the channel. */
4464 channel = silc_idlist_find_channel_by_id(server->local_list,
4467 channel = silc_idlist_find_channel_by_id(server->global_list,
4470 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4471 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4476 /* Check whether this client is on the channel */
4477 if (!silc_server_client_on_channel(client, channel)) {
4478 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4479 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4483 /* Get entry to the channel user list */
4484 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4486 /* The client must be at least channel operator. */
4487 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4488 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4489 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4493 /* Get the new ban and add it to the ban list */
4494 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4496 if (!channel->ban_list)
4497 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4499 channel->ban_list = silc_realloc(channel->ban_list,
4500 sizeof(*channel->ban_list) *
4502 strlen(channel->ban_list) + 2));
4503 if (add[tmp_len - 1] == ',')
4504 add[tmp_len - 1] = '\0';
4506 strncat(channel->ban_list, add, tmp_len);
4507 strncat(channel->ban_list, ",", 1);
4510 /* Get the ban to be removed and remove it from the list */
4511 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4512 if (del && channel->ban_list) {
4513 char *start, *end, *n;
4515 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4516 silc_free(channel->ban_list);
4517 channel->ban_list = NULL;
4519 start = strstr(channel->ban_list, del);
4520 if (start && strlen(start) >= tmp_len) {
4521 end = start + tmp_len;
4522 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4523 strncat(n, channel->ban_list, start - channel->ban_list);
4524 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4526 silc_free(channel->ban_list);
4527 channel->ban_list = n;
4532 /* Send the BAN notify type to our primary router. */
4533 if (!server->standalone && (add || del))
4534 silc_server_send_notify_ban(server, server->router->connection,
4535 server->server_type == SILC_ROUTER ?
4536 TRUE : FALSE, channel, add, del);
4538 /* Send the reply back to the client */
4539 if (channel->ban_list)
4541 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4542 SILC_STATUS_OK, ident, 2,
4544 3, channel->ban_list,
4545 strlen(channel->ban_list) - 1);
4548 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4549 SILC_STATUS_OK, ident, 1,
4552 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4553 packet->data, packet->len, FALSE);
4555 silc_buffer_free(packet);
4559 silc_free(channel_id);
4560 silc_server_command_free(cmd);
4563 /* Server side command of CLOSE. Closes connection to a specified server. */
4565 SILC_SERVER_CMD_FUNC(close)
4567 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4568 SilcServer server = cmd->server;
4569 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4570 SilcServerEntry server_entry;
4571 SilcSocketConnection sock;
4574 unsigned char *name;
4575 uint32 port = SILC_PORT;
4577 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CLOSE, cmd, 1, 2);
4579 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4582 /* Check whether client has the permissions. */
4583 if (client->mode == SILC_UMODE_NONE) {
4584 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4585 SILC_STATUS_ERR_NO_SERVER_PRIV);
4589 /* Get the remote server */
4590 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4592 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4593 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4598 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4600 SILC_GET32_MSB(port, tmp);
4602 server_entry = silc_idlist_find_server_by_conn(server->local_list,
4604 if (!server_entry) {
4605 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4606 SILC_STATUS_ERR_NO_SERVER_ID);
4610 /* Send reply to the sender */
4611 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4614 /* Close the connection to the server */
4615 sock = (SilcSocketConnection)server_entry->connection;
4616 silc_server_free_sock_user_data(server, sock);
4617 silc_server_close_connection(server, sock);
4620 silc_server_command_free(cmd);
4623 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4624 active connections. */
4626 SILC_SERVER_CMD_FUNC(shutdown)
4628 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4629 SilcServer server = cmd->server;
4630 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4632 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4634 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4637 /* Check whether client has the permission. */
4638 if (client->mode == SILC_UMODE_NONE) {
4639 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4640 SILC_STATUS_ERR_NO_SERVER_PRIV);
4644 /* Send reply to the sender */
4645 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4648 /* Then, gracefully, or not, bring the server down. */
4649 silc_server_stop(server);
4653 silc_server_command_free(cmd);
4656 /* Server side command of LEAVE. Removes client from a channel. */
4658 SILC_SERVER_CMD_FUNC(leave)
4660 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4661 SilcServer server = cmd->server;
4662 SilcSocketConnection sock = cmd->sock;
4663 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4664 SilcChannelID *id = NULL;
4665 SilcChannelEntry channel;
4669 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4671 /* Get Channel ID */
4672 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4674 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4675 SILC_STATUS_ERR_NO_CHANNEL_ID);
4678 id = silc_id_payload_parse_id(tmp, len);
4680 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4681 SILC_STATUS_ERR_NO_CHANNEL_ID);
4685 /* Get channel entry */
4686 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4688 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4690 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4691 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4696 /* Check whether this client is on the channel */
4697 if (!silc_server_client_on_channel(id_entry, channel)) {
4698 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4699 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4703 /* Notify routers that they should remove this client from their list
4704 of clients on the channel. Send LEAVE notify type. */
4705 if (!server->standalone)
4706 silc_server_send_notify_leave(server, server->router->connection,
4707 server->server_type == SILC_ROUTER ?
4708 TRUE : FALSE, channel, id_entry->id);
4710 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4713 /* Remove client from channel */
4714 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4716 /* If the channel does not exist anymore we won't send anything */
4719 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4720 /* Re-generate channel key */
4721 silc_server_create_channel_key(server, channel, 0);
4723 /* Send the channel key */
4724 silc_server_send_channel_key(server, NULL, channel,
4725 server->server_type == SILC_ROUTER ?
4726 FALSE : !server->standalone);
4732 silc_server_command_free(cmd);
4735 /* Server side of command USERS. Resolves clients and their USERS currently
4736 joined on the requested channel. The list of Client ID's and their modes
4737 on the channel is sent back. */
4739 SILC_SERVER_CMD_FUNC(users)
4741 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4742 SilcServer server = cmd->server;
4743 SilcChannelEntry channel;
4746 unsigned char *channel_id;
4747 uint32 channel_id_len;
4748 SilcBuffer client_id_list;
4749 SilcBuffer client_mode_list;
4750 unsigned char lc[4];
4751 uint32 list_count = 0;
4752 uint16 ident = silc_command_get_ident(cmd->payload);
4754 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 1);
4756 /* Get Channel ID */
4757 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4759 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4760 SILC_STATUS_ERR_NO_CHANNEL_ID);
4763 id = silc_id_payload_parse_id(channel_id, channel_id_len);
4765 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4766 SILC_STATUS_ERR_NO_CHANNEL_ID);
4770 /* If we are server and we don't know about this channel we will send
4771 the command to our router. If we know about the channel then we also
4772 have the list of users already. */
4773 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4775 if (server->server_type == SILC_SERVER && !server->standalone &&
4779 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
4780 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4782 /* Send USERS command */
4783 silc_server_packet_send(server, server->router->connection,
4784 SILC_PACKET_COMMAND, cmd->packet->flags,
4785 tmpbuf->data, tmpbuf->len, TRUE);
4787 /* Reprocess this packet after received reply */
4788 silc_server_command_pending(server, SILC_COMMAND_USERS,
4789 silc_command_get_ident(cmd->payload),
4790 silc_server_command_destructor,
4791 silc_server_command_users,
4792 silc_server_command_dup(cmd));
4793 cmd->pending = TRUE;
4794 silc_command_set_ident(cmd->payload, ident);
4796 silc_buffer_free(tmpbuf);
4801 /* We are router and we will check the global list as well. */
4802 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4804 /* Channel really does not exist */
4805 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4806 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4811 /* Get the users list */
4812 silc_server_get_users_on_channel(server, channel, &client_id_list,
4813 &client_mode_list, &list_count);
4816 SILC_PUT32_MSB(list_count, lc);
4819 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
4820 SILC_STATUS_OK, ident, 4,
4821 2, channel_id, channel_id_len,
4823 4, client_id_list->data,
4824 client_id_list->len,
4825 5, client_mode_list->data,
4826 client_mode_list->len);
4827 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4828 packet->data, packet->len, FALSE);
4830 silc_buffer_free(packet);
4831 silc_buffer_free(client_id_list);
4832 silc_buffer_free(client_mode_list);
4836 silc_server_command_free(cmd);
4839 /* Server side of command GETKEY. This fetches the client's public key
4840 from the server where to the client is connected. */
4842 SILC_SERVER_CMD_FUNC(getkey)
4844 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4845 SilcServer server = cmd->server;
4847 SilcClientEntry client;
4848 SilcServerEntry server_entry;
4849 SilcClientID *client_id = NULL;
4850 SilcServerID *server_id = NULL;
4851 SilcIDPayload idp = NULL;
4852 uint16 ident = silc_command_get_ident(cmd->payload);
4858 SILC_LOG_DEBUG(("Start"));
4860 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4862 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4863 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4866 idp = silc_id_payload_parse_data(tmp, tmp_len);
4868 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4869 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4873 id_type = silc_id_payload_get_type(idp);
4874 if (id_type == SILC_ID_CLIENT) {
4875 client_id = silc_id_payload_get_id(idp);
4877 /* If the client is not found from local list there is no chance it
4878 would be locally connected client so send the command further. */
4879 client = silc_idlist_find_client_by_id(server->local_list,
4882 client = silc_idlist_find_client_by_id(server->global_list,
4885 if ((!client && !cmd->pending && !server->standalone) ||
4886 (client && !client->connection && !cmd->pending &&
4887 !server->standalone) ||
4888 (client && !client->data.public_key && !cmd->pending &&
4889 !server->standalone)) {
4892 SilcSocketConnection dest_sock;
4894 dest_sock = silc_server_get_client_route(server, NULL, 0,
4899 old_ident = silc_command_get_ident(cmd->payload);
4900 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
4901 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4903 silc_server_packet_send(server, dest_sock,
4904 SILC_PACKET_COMMAND, cmd->packet->flags,
4905 tmpbuf->data, tmpbuf->len, TRUE);
4907 /* Reprocess this packet after received reply from router */
4908 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
4909 silc_command_get_ident(cmd->payload),
4910 silc_server_command_destructor,
4911 silc_server_command_getkey,
4912 silc_server_command_dup(cmd));
4913 cmd->pending = TRUE;
4915 silc_command_set_ident(cmd->payload, old_ident);
4916 silc_buffer_free(tmpbuf);
4920 if (!client && cmd->pending) {
4921 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4922 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
4926 /* The client is locally connected, just get the public key and
4928 tmp = silc_pkcs_public_key_encode(client->data.public_key, &tmp_len);
4929 pk = silc_buffer_alloc(4 + tmp_len);
4930 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
4931 silc_buffer_format(pk,
4932 SILC_STR_UI_SHORT(tmp_len),
4933 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
4934 SILC_STR_UI_XNSTRING(tmp, tmp_len),
4938 } else if (id_type == SILC_ID_SERVER) {
4939 server_id = silc_id_payload_get_id(idp);
4941 /* If the server is not found from local list there is no chance it
4942 would be locally connected server so send the command further. */
4943 server_entry = silc_idlist_find_server_by_id(server->local_list,
4946 server_entry = silc_idlist_find_server_by_id(server->global_list,
4949 if ((!server_entry && !cmd->pending && !server->standalone) ||
4950 (server_entry && !server_entry->connection && !cmd->pending &&
4951 !server->standalone) ||
4952 (server_entry && !server_entry->data.public_key && !cmd->pending &&
4953 !server->standalone)) {
4957 old_ident = silc_command_get_ident(cmd->payload);
4958 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
4959 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4961 silc_server_packet_send(server, server->router->connection,
4962 SILC_PACKET_COMMAND, cmd->packet->flags,
4963 tmpbuf->data, tmpbuf->len, TRUE);
4965 /* Reprocess this packet after received reply from router */
4966 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
4967 silc_command_get_ident(cmd->payload),
4968 silc_server_command_destructor,
4969 silc_server_command_getkey,
4970 silc_server_command_dup(cmd));
4971 cmd->pending = TRUE;
4973 silc_command_set_ident(cmd->payload, old_ident);
4974 silc_buffer_free(tmpbuf);
4978 if (!server_entry && cmd->pending) {
4979 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4980 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
4984 /* The client is locally connected, just get the public key and
4986 tmp = silc_pkcs_public_key_encode(server_entry->data.public_key, &tmp_len);
4987 pk = silc_buffer_alloc(4 + tmp_len);
4988 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
4989 silc_buffer_format(pk,
4990 SILC_STR_UI_SHORT(tmp_len),
4991 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
4992 SILC_STR_UI_XNSTRING(tmp, tmp_len),
4999 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5000 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5001 SILC_STATUS_OK, ident, 2,
5003 3, pk->data, pk->len);
5004 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5005 packet->data, packet->len, FALSE);
5006 silc_buffer_free(packet);
5007 silc_buffer_free(pk);
5011 silc_id_payload_free(idp);
5012 silc_free(client_id);
5013 silc_free(server_id);
5014 silc_server_command_free(cmd);