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,
37 unsigned int arg_type,
39 unsigned int arg_len);
40 SILC_TASK_CALLBACK(silc_server_command_process_timeout);
42 /* Server command list. */
43 SilcServerCommand silc_command_list[] =
45 SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
46 SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
47 SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
48 SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
49 SILC_SERVER_CMD(list, LIST, SILC_CF_LAG_STRICT | SILC_CF_REG),
50 SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
51 SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
52 SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
53 SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG_STRICT | SILC_CF_REG | SILC_CF_OPER),
54 SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
55 SILC_SERVER_CMD(connect, CONNECT,
56 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
57 SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
58 SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
59 SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG_STRICT | SILC_CF_REG),
60 SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
61 SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
62 SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG_STRICT | SILC_CF_REG),
63 SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
64 SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
65 SILC_SERVER_CMD(restart, RESTART,
66 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
67 SILC_SERVER_CMD(close, CLOSE,
68 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
69 SILC_SERVER_CMD(shutdown, SHUTDOWN, SILC_CF_LAG | SILC_CF_REG |
71 SILC_SERVER_CMD(silcoper, SILCOPER,
72 SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
73 SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
74 SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
79 #define SILC_SERVER_COMMAND_CHECK_ARGC(command, context, min, max) \
81 unsigned int _argc = silc_argument_get_arg_num(cmd->args); \
83 SILC_LOG_DEBUG(("Start")); \
86 silc_server_command_send_status_reply(cmd, command, \
87 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
88 silc_server_command_free(cmd); \
92 silc_server_command_send_status_reply(cmd, command, \
93 SILC_STATUS_ERR_TOO_MANY_PARAMS); \
94 silc_server_command_free(cmd); \
99 /* Returns TRUE if the connection is registered. Unregistered connections
100 usually cannot send commands hence the check. */
102 static int silc_server_is_registered(SilcServer server,
103 SilcSocketConnection sock,
104 SilcServerCommandContext cmd,
107 SilcIDListData idata = (SilcIDListData)sock->user_data;
108 if (idata->registered)
111 silc_server_command_send_status_reply(cmd, command,
112 SILC_STATUS_ERR_NOT_REGISTERED);
113 silc_server_command_free(cmd);
117 /* Internal context to hold data when executed command with timeout. */
119 SilcServerCommandContext ctx;
120 SilcServerCommand *cmd;
121 } *SilcServerCommandTimeout;
123 /* Timeout callback to process commands with timeout for client. Client's
124 commands are always executed with timeout. */
126 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
128 SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
129 SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data;
131 /* Update access time */
132 client->last_command = time(NULL);
134 if (!(timeout->cmd->flags & SILC_CF_REG))
135 timeout->cmd->cb(timeout->ctx);
136 else if (silc_server_is_registered(timeout->ctx->server,
140 timeout->cmd->cb(timeout->ctx);
145 /* Processes received command packet. */
147 void silc_server_command_process(SilcServer server,
148 SilcSocketConnection sock,
149 SilcPacketContext *packet)
151 SilcServerCommandContext ctx;
152 SilcServerCommand *cmd;
155 /* Allocate command context. This must be free'd by the
156 command routine receiving it. */
157 ctx = silc_server_command_alloc();
158 ctx->server = server;
159 ctx->sock = silc_socket_dup(sock);
160 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
162 /* Parse the command payload in the packet */
163 ctx->payload = silc_command_payload_parse(packet->buffer);
165 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
166 silc_buffer_free(packet->buffer);
167 silc_packet_context_free(packet);
168 silc_socket_free(ctx->sock);
172 ctx->args = silc_command_get_args(ctx->payload);
174 /* Get the command */
175 command = silc_command_get(ctx->payload);
176 for (cmd = silc_command_list; cmd->cb; cmd++)
177 if (cmd->cmd == command)
181 silc_server_command_send_status_reply(ctx, command,
182 SILC_STATUS_ERR_UNKNOWN_COMMAND);
183 silc_server_command_free(ctx);
187 /* Execute client's commands always with timeout. Normally they are
188 executed with zero (0) timeout but if client is sending command more
189 frequently than once in 2 seconds, then the timeout may be 0 to 2
191 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
192 SilcClientEntry client = (SilcClientEntry)sock->user_data;
193 SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
199 if (client->last_command && (time(NULL) - client->last_command) < 2) {
200 client->fast_command++;
203 client->fast_command = ((client->fast_command - 1) <= 0 ? 0 :
204 client->fast_command--);
208 if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
209 (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
210 silc_task_register(server->timeout_queue, sock->sock,
211 silc_server_command_process_timeout,
213 2 - (time(NULL) - client->last_command), 0,
215 SILC_TASK_PRI_NORMAL);
217 silc_task_register(server->timeout_queue, sock->sock,
218 silc_server_command_process_timeout,
222 SILC_TASK_PRI_NORMAL);
226 /* Execute for server */
228 if (!(cmd->flags & SILC_CF_REG))
230 else if (silc_server_is_registered(server, sock, ctx, cmd->cmd))
234 /* Allocate Command Context */
236 SilcServerCommandContext silc_server_command_alloc()
238 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
243 /* Free's the command context allocated before executing the command */
245 void silc_server_command_free(SilcServerCommandContext ctx)
248 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
250 if (ctx->users < 1) {
252 silc_command_free_payload(ctx->payload);
254 silc_packet_context_free(ctx->packet);
256 silc_socket_free(ctx->sock); /* Decrease reference counter */
261 /* Duplicate Command Context by adding reference counter. The context won't
262 be free'd untill it hits zero. */
264 SilcServerCommandContext
265 silc_server_command_dup(SilcServerCommandContext ctx)
268 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
273 /* Add new pending command to be executed when reply to a command has been
274 received. The `reply_cmd' is the command that will call the `callback'
275 with `context' when reply has been received. If `ident' is non-zero
276 the `callback' will be executed when received reply with command
277 identifier `ident'. */
279 void silc_server_command_pending(SilcServer server,
280 SilcCommand reply_cmd,
281 unsigned short ident,
282 SilcServerPendingDestructor destructor,
283 SilcCommandCb callback,
286 SilcServerCommandPending *reply;
288 reply = silc_calloc(1, sizeof(*reply));
289 reply->reply_cmd = reply_cmd;
290 reply->ident = ident;
291 reply->context = context;
292 reply->callback = callback;
293 reply->destructor = destructor;
294 silc_dlist_add(server->pending_commands, reply);
297 /* Deletes pending command by reply command type. */
299 void silc_server_command_pending_del(SilcServer server,
300 SilcCommand reply_cmd,
301 unsigned short ident)
303 SilcServerCommandPending *r;
305 silc_dlist_start(server->pending_commands);
306 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
307 if (r->reply_cmd == reply_cmd && r->ident == ident) {
308 silc_dlist_del(server->pending_commands, r);
314 /* Checks for pending commands and marks callbacks to be called from
315 the command reply function. Returns TRUE if there were pending command. */
317 int silc_server_command_pending_check(SilcServer server,
318 SilcServerCommandReplyContext ctx,
320 unsigned short ident)
322 SilcServerCommandPending *r;
324 silc_dlist_start(server->pending_commands);
325 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
326 if (r->reply_cmd == command && r->ident == ident) {
327 ctx->context = r->context;
328 ctx->callback = r->callback;
329 ctx->destructor = r->destructor;
338 /* Destructor function for pending callbacks. This is called when using
339 pending commands to free the context given for the pending command. */
341 static void silc_server_command_destructor(void *context)
343 silc_server_command_free((SilcServerCommandContext)context);
346 /* Sends simple status message as command reply packet */
349 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
351 SilcCommandStatus status)
355 SILC_LOG_DEBUG(("Sending command status %d", status));
358 silc_command_reply_payload_encode_va(command, status,
359 silc_command_get_ident(cmd->payload),
361 silc_server_packet_send(cmd->server, cmd->sock,
362 SILC_PACKET_COMMAND_REPLY, 0,
363 buffer->data, buffer->len, FALSE);
364 silc_buffer_free(buffer);
367 /* Sends command status reply with one extra argument. The argument
368 type must be sent as argument. */
371 silc_server_command_send_status_data(SilcServerCommandContext cmd,
373 SilcCommandStatus status,
374 unsigned int arg_type,
376 unsigned int arg_len)
380 SILC_LOG_DEBUG(("Sending command status %d", status));
383 silc_command_reply_payload_encode_va(command, status,
384 silc_command_get_ident(cmd->payload),
385 1, arg_type, arg, arg_len);
386 silc_server_packet_send(cmd->server, cmd->sock,
387 SILC_PACKET_COMMAND_REPLY, 0,
388 buffer->data, buffer->len, FALSE);
389 silc_buffer_free(buffer);
392 /******************************************************************************
396 ******************************************************************************/
399 silc_server_command_whois_parse(SilcServerCommandContext cmd,
400 SilcClientID ***client_id,
401 unsigned int *client_id_count,
409 unsigned int argc = silc_argument_get_arg_num(cmd->args);
412 /* If client ID is in the command it must be used instead of nickname */
413 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
415 /* No ID, get the nickname@server string and parse it. */
416 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
418 if (strchr(tmp, '@')) {
419 len = strcspn(tmp, "@");
420 *nickname = silc_calloc(len + 1, sizeof(char));
421 memcpy(*nickname, tmp, len);
422 *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
423 memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
425 *nickname = strdup(tmp);
428 silc_server_command_send_status_reply(cmd, command,
429 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
433 /* Command includes ID, we must use that. Also check whether the command
434 has more than one ID set - take them all. */
436 *client_id = silc_calloc(1, sizeof(**client_id));
437 (*client_id)[0] = silc_id_payload_parse_id(tmp, len);
438 if ((*client_id)[0] == NULL) {
439 silc_free(*client_id);
442 *client_id_count = 1;
444 /* Take all ID's from the command packet */
446 for (k = 1, i = 1; i < argc; i++) {
447 tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
449 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
450 (*client_id_count + 1));
451 (*client_id)[k] = silc_id_payload_parse_id(tmp, len);
452 if ((*client_id)[k] == NULL) {
453 /* Cleanup all and fail */
454 for (i = 0; i < *client_id_count; i++)
455 silc_free((*client_id)[i]);
456 silc_free(*client_id);
459 (*client_id_count)++;
465 /* Command includes ID, use that */
468 /* Get the max count of reply messages allowed */
469 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
479 silc_server_command_whois_check(SilcServerCommandContext cmd,
480 SilcClientEntry *clients,
481 unsigned int clients_count)
483 SilcServer server = cmd->server;
485 SilcClientEntry entry;
487 for (i = 0; i < clients_count; i++) {
490 if (entry->data.registered == FALSE)
493 if (!entry->nickname || !entry->username || !entry->userinfo) {
495 unsigned short old_ident;
500 old_ident = silc_command_get_ident(cmd->payload);
501 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
502 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
504 /* Send WHOIS command */
505 silc_server_packet_send(server, entry->router->connection,
506 SILC_PACKET_COMMAND, cmd->packet->flags,
507 tmpbuf->data, tmpbuf->len, TRUE);
509 /* Reprocess this packet after received reply */
510 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
511 silc_command_get_ident(cmd->payload),
512 silc_server_command_destructor,
513 silc_server_command_whois,
514 silc_server_command_dup(cmd));
517 silc_command_set_ident(cmd->payload, old_ident);
519 silc_buffer_free(tmpbuf);
528 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
529 SilcClientEntry *clients,
530 unsigned int clients_count)
532 SilcServer server = cmd->server;
534 int i, count = 0, len;
535 SilcBuffer packet, idp, channels;
536 SilcClientEntry entry;
537 SilcCommandStatus status;
538 unsigned short ident = silc_command_get_ident(cmd->payload);
539 char nh[128], uh[128];
540 unsigned char idle[4], mode[4];
541 SilcSocketConnection hsock;
543 status = SILC_STATUS_OK;
544 if (clients_count > 1)
545 status = SILC_STATUS_LIST_START;
547 for (i = 0; i < clients_count; i++) {
550 if (entry->data.registered == FALSE) {
551 if (clients_count == 1) {
552 SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
553 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
554 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
555 2, idp->data, idp->len);
556 silc_buffer_free(idp);
561 if (count && i - 1 == count)
565 status = SILC_STATUS_LIST_ITEM;
567 if (clients_count > 1 && i == clients_count - 1)
568 status = SILC_STATUS_LIST_END;
570 /* Sanity check, however these should never fail. However, as
571 this sanity check has been added here they have failed. */
572 if (!entry->nickname || !entry->username || !entry->userinfo)
575 /* Send WHOIS reply */
576 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
577 tmp = silc_argument_get_first_arg(cmd->args, NULL);
579 memset(uh, 0, sizeof(uh));
580 memset(nh, 0, sizeof(nh));
581 memset(idle, 0, sizeof(idle));
583 strncat(nh, entry->nickname, strlen(entry->nickname));
584 if (!strchr(entry->nickname, '@')) {
586 len = entry->router ? strlen(entry->router->server_name) :
587 strlen(server->server_name);
588 strncat(nh, entry->router ? entry->router->server_name :
589 server->server_name, len);
592 strncat(uh, entry->username, strlen(entry->username));
593 if (!strchr(entry->username, '@')) {
595 hsock = (SilcSocketConnection)entry->connection;
596 len = strlen(hsock->hostname);
597 strncat(uh, hsock->hostname, len);
600 channels = silc_server_get_client_channel_list(server, entry);
602 SILC_PUT32_MSB(entry->mode, mode);
604 if (entry->connection) {
605 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
609 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
611 2, idp->data, idp->len,
615 strlen(entry->userinfo),
621 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
623 2, idp->data, idp->len,
627 strlen(entry->userinfo),
631 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
632 0, packet->data, packet->len, FALSE);
634 silc_buffer_free(packet);
635 silc_buffer_free(idp);
637 silc_buffer_free(channels);
642 silc_server_command_whois_from_client(SilcServerCommandContext cmd)
644 SilcServer server = cmd->server;
645 char *nick = NULL, *server_name = NULL;
646 int count = 0, clients_count = 0;
647 SilcClientEntry *clients = NULL, entry;
648 SilcClientID **client_id = NULL;
649 unsigned int client_id_count = 0;
652 /* Protocol dictates that we must always send the received WHOIS request
653 to our router if we are normal server, so let's do it now unless we
654 are standalone. We will not send any replies to the client until we
655 have received reply from the router. */
656 if (server->server_type == SILC_SERVER && !cmd->pending &&
657 !server->standalone) {
659 unsigned short old_ident;
661 old_ident = silc_command_get_ident(cmd->payload);
662 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
663 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
665 /* Send WHOIS command to our router */
666 silc_server_packet_send(server, (SilcSocketConnection)
667 server->router->connection,
668 SILC_PACKET_COMMAND, cmd->packet->flags,
669 tmpbuf->data, tmpbuf->len, TRUE);
671 /* Reprocess this packet after received reply from router */
672 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
673 silc_command_get_ident(cmd->payload),
674 silc_server_command_destructor,
675 silc_server_command_whois,
676 silc_server_command_dup(cmd));
679 silc_command_set_ident(cmd->payload, old_ident);
681 silc_buffer_free(tmpbuf);
686 /* We are ready to process the command request. Let's search for the
687 requested client and send reply to the requesting client. */
689 /* Parse the whois request */
690 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
691 &nick, &server_name, &count,
695 /* Get all clients matching that ID or nickname from local list */
696 if (client_id_count) {
697 /* Check all Client ID's received in the command packet */
698 for (i = 0; i < client_id_count; i++) {
699 entry = silc_idlist_find_client_by_id(server->local_list,
702 clients = silc_realloc(clients, sizeof(*clients) *
703 (clients_count + 1));
704 clients[clients_count++] = entry;
708 clients = silc_idlist_get_clients_by_hash(server->local_list,
709 nick, server->md5hash,
712 clients = silc_idlist_get_clients_by_nickname(server->local_list,
717 /* Check global list as well */
719 if (client_id_count) {
720 /* Check all Client ID's received in the command packet */
721 for (i = 0; i < client_id_count; i++) {
722 entry = silc_idlist_find_client_by_id(server->global_list,
725 clients = silc_realloc(clients, sizeof(*clients) *
726 (clients_count + 1));
727 clients[clients_count++] = entry;
731 clients = silc_idlist_get_clients_by_hash(server->global_list,
732 nick, server->md5hash,
735 clients = silc_idlist_get_clients_by_nickname(server->global_list,
742 /* Such client(s) really does not exist in the SILC network. */
743 if (!client_id_count) {
744 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
745 SILC_STATUS_ERR_NO_SUCH_NICK,
746 3, nick, strlen(nick));
748 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
749 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
750 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
751 2, idp->data, idp->len);
752 silc_buffer_free(idp);
757 /* Router always finds the client entry if it exists in the SILC network.
758 However, it might be incomplete entry and does not include all the
759 mandatory fields that WHOIS command reply requires. Check for these and
760 make query from the server who owns the client if some fields are
762 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
767 /* Send the command reply to the client */
768 silc_server_command_whois_send_reply(cmd, clients, clients_count);
771 if (client_id_count) {
772 for (i = 0; i < client_id_count; i++)
773 silc_free(client_id[i]);
774 silc_free(client_id);
781 silc_free(server_name);
787 silc_server_command_whois_from_server(SilcServerCommandContext cmd)
789 SilcServer server = cmd->server;
790 char *nick = NULL, *server_name = NULL;
791 int count = 0, clients_count = 0;
792 SilcClientEntry *clients = NULL, entry;
793 SilcClientID **client_id = NULL;
794 unsigned int client_id_count = 0;
797 /* Parse the whois request */
798 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
799 &nick, &server_name, &count,
803 /* Process the command request. Let's search for the requested client and
804 send reply to the requesting server. */
806 if (client_id_count) {
807 /* Check all Client ID's received in the command packet */
808 for (i = 0; i < client_id_count; i++) {
809 entry = silc_idlist_find_client_by_id(server->local_list,
812 clients = silc_realloc(clients, sizeof(*clients) *
813 (clients_count + 1));
814 clients[clients_count++] = entry;
818 clients = silc_idlist_get_clients_by_hash(server->local_list,
819 nick, server->md5hash,
822 clients = silc_idlist_get_clients_by_nickname(server->local_list,
827 /* If we are router we will check our global list as well. */
828 if (!clients && server->server_type == SILC_ROUTER) {
829 if (client_id_count) {
830 /* Check all Client ID's received in the command packet */
831 for (i = 0; i < client_id_count; i++) {
832 entry = silc_idlist_find_client_by_id(server->global_list,
835 clients = silc_realloc(clients, sizeof(*clients) *
836 (clients_count + 1));
837 clients[clients_count++] = entry;
841 clients = silc_idlist_get_clients_by_hash(server->global_list,
842 nick, server->md5hash,
845 clients = silc_idlist_get_clients_by_nickname(server->global_list,
852 /* Such a client really does not exist in the SILC network. */
853 if (!client_id_count) {
854 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
855 SILC_STATUS_ERR_NO_SUCH_NICK,
856 3, nick, strlen(nick));
858 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
859 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
860 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
861 2, idp->data, idp->len);
862 silc_buffer_free(idp);
867 /* Router always finds the client entry if it exists in the SILC network.
868 However, it might be incomplete entry and does not include all the
869 mandatory fields that WHOIS command reply requires. Check for these and
870 make query from the server who owns the client if some fields are
872 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
877 /* Send the command reply to the client */
878 silc_server_command_whois_send_reply(cmd, clients, clients_count);
881 if (client_id_count) {
882 for (i = 0; i < client_id_count; i++)
883 silc_free(client_id[i]);
884 silc_free(client_id);
891 silc_free(server_name);
896 /* Server side of command WHOIS. Processes user's query and sends found
897 results as command replies back to the client. */
899 SILC_SERVER_CMD_FUNC(whois)
901 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
904 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOIS, cmd, 1, 3328);
906 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
907 ret = silc_server_command_whois_from_client(cmd);
908 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
909 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
910 ret = silc_server_command_whois_from_server(cmd);
913 silc_server_command_free(cmd);
916 /******************************************************************************
920 ******************************************************************************/
923 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
931 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
933 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
934 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
938 /* Get the nickname@server string and parse it. */
939 if (strchr(tmp, '@')) {
940 len = strcspn(tmp, "@");
941 *nickname = silc_calloc(len + 1, sizeof(char));
942 memcpy(*nickname, tmp, len);
943 *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
944 memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
946 *nickname = strdup(tmp);
948 /* Get the max count of reply messages allowed */
949 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
959 silc_server_command_whowas_check(SilcServerCommandContext cmd,
960 SilcClientEntry *clients,
961 unsigned int clients_count)
963 SilcServer server = cmd->server;
965 SilcClientEntry entry;
967 for (i = 0; i < clients_count; i++) {
970 if (!entry->nickname || !entry->username) {
972 unsigned short old_ident;
977 old_ident = silc_command_get_ident(cmd->payload);
978 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
979 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
981 /* Send WHOWAS command */
982 silc_server_packet_send(server, entry->router->connection,
983 SILC_PACKET_COMMAND, cmd->packet->flags,
984 tmpbuf->data, tmpbuf->len, TRUE);
986 /* Reprocess this packet after received reply */
987 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
988 silc_command_get_ident(cmd->payload),
989 silc_server_command_destructor,
990 silc_server_command_whowas,
991 silc_server_command_dup(cmd));
994 silc_command_set_ident(cmd->payload, old_ident);
996 silc_buffer_free(tmpbuf);
1005 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1006 SilcClientEntry *clients,
1007 unsigned int clients_count)
1009 SilcServer server = cmd->server;
1011 int i, count = 0, len;
1012 SilcBuffer packet, idp;
1013 SilcClientEntry entry = NULL;
1014 SilcCommandStatus status;
1015 unsigned short ident = silc_command_get_ident(cmd->payload);
1017 char nh[256], uh[256];
1019 status = SILC_STATUS_OK;
1020 if (clients_count > 1)
1021 status = SILC_STATUS_LIST_START;
1023 for (i = 0; i < clients_count; i++) {
1026 /* We will take only clients that are not valid anymore. They are the
1027 ones that are not registered anymore but still have a ID. They
1028 have disconnected us, and thus valid for WHOWAS. */
1029 if (entry->data.registered == TRUE)
1031 if (entry->id == NULL)
1034 if (count && i - 1 == count)
1039 if (clients_count > 2)
1040 status = SILC_STATUS_LIST_ITEM;
1042 if (clients_count > 1 && i == clients_count - 1)
1043 status = SILC_STATUS_LIST_END;
1045 /* Sanity check, however these should never fail. However, as
1046 this sanity check has been added here they have failed. */
1047 if (!entry->nickname || !entry->username)
1050 /* Send WHOWAS reply */
1051 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1052 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1054 memset(uh, 0, sizeof(uh));
1055 memset(nh, 0, sizeof(nh));
1057 strncat(nh, entry->nickname, strlen(entry->nickname));
1058 if (!strchr(entry->nickname, '@')) {
1059 strncat(nh, "@", 1);
1060 len = entry->router ? strlen(entry->router->server_name) :
1061 strlen(server->server_name);
1062 strncat(nh, entry->router ? entry->router->server_name :
1063 server->server_name, len);
1066 strncat(uh, entry->username, strlen(entry->username));
1067 if (!strchr(entry->username, '@')) {
1068 strncat(uh, "@", 1);
1069 strcat(uh, "*private*");
1072 if (entry->userinfo)
1074 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1076 2, idp->data, idp->len,
1080 strlen(entry->userinfo));
1083 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1085 2, idp->data, idp->len,
1089 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1090 0, packet->data, packet->len, FALSE);
1092 silc_buffer_free(packet);
1093 silc_buffer_free(idp);
1096 if (found == FALSE && entry)
1097 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1098 SILC_STATUS_ERR_NO_SUCH_NICK,
1100 strlen(entry->nickname));
1104 silc_server_command_whowas_from_client(SilcServerCommandContext cmd)
1106 SilcServer server = cmd->server;
1107 char *nick = NULL, *server_name = NULL;
1108 int count = 0, clients_count = 0;
1109 SilcClientEntry *clients = NULL;
1112 /* Protocol dictates that we must always send the received WHOWAS request
1113 to our router if we are normal server, so let's do it now unless we
1114 are standalone. We will not send any replies to the client until we
1115 have received reply from the router. */
1116 if (server->server_type == SILC_SERVER &&
1117 !cmd->pending && !server->standalone) {
1119 unsigned short old_ident;
1121 old_ident = silc_command_get_ident(cmd->payload);
1122 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1123 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1125 /* Send WHOWAS command to our router */
1126 silc_server_packet_send(server, (SilcSocketConnection)
1127 server->router->connection,
1128 SILC_PACKET_COMMAND, cmd->packet->flags,
1129 tmpbuf->data, tmpbuf->len, TRUE);
1131 /* Reprocess this packet after received reply from router */
1132 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1133 silc_command_get_ident(cmd->payload),
1134 silc_server_command_destructor,
1135 silc_server_command_whowas,
1136 silc_server_command_dup(cmd));
1137 cmd->pending = TRUE;
1139 silc_command_set_ident(cmd->payload, old_ident);
1141 silc_buffer_free(tmpbuf);
1146 /* We are ready to process the command request. Let's search for the
1147 requested client and send reply to the requesting client. */
1149 /* Parse the whowas request */
1150 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1153 /* Get all clients matching that nickname from local list */
1154 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1158 clients = silc_idlist_get_clients_by_hash(server->local_list,
1159 nick, server->md5hash,
1162 /* Check global list as well */
1164 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1168 clients = silc_idlist_get_clients_by_hash(server->global_list,
1169 nick, server->md5hash,
1173 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1178 /* Send the command reply to the client */
1179 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1187 silc_free(server_name);
1193 silc_server_command_whowas_from_server(SilcServerCommandContext cmd)
1195 SilcServer server = cmd->server;
1196 char *nick = NULL, *server_name = NULL;
1197 int count = 0, clients_count = 0;
1198 SilcClientEntry *clients = NULL;
1201 /* Parse the whowas request */
1202 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1205 /* Process the command request. Let's search for the requested client and
1206 send reply to the requesting server. */
1208 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1212 clients = silc_idlist_get_clients_by_hash(server->local_list,
1213 nick, server->md5hash,
1216 /* If we are router we will check our global list as well. */
1217 if (!clients && server->server_type == SILC_ROUTER) {
1218 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1222 clients = silc_idlist_get_clients_by_hash(server->global_list,
1223 nick, server->md5hash,
1228 /* Such a client really does not exist in the SILC network. */
1229 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1230 SILC_STATUS_ERR_NO_SUCH_NICK,
1231 3, nick, strlen(nick));
1235 /* Send the command reply to the client */
1236 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1244 silc_free(server_name);
1249 /* Server side of command WHOWAS. */
1251 SILC_SERVER_CMD_FUNC(whowas)
1253 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1256 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1258 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1259 ret = silc_server_command_whowas_from_client(cmd);
1260 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
1261 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1262 ret = silc_server_command_whowas_from_server(cmd);
1265 silc_server_command_free(cmd);
1268 /******************************************************************************
1272 ******************************************************************************/
1274 /* Checks that all mandatory fields are present. If not then send WHOIS
1275 request to the server who owns the client. We use WHOIS because we want
1276 to get as much information as possible at once. */
1279 silc_server_command_identify_check(SilcServerCommandContext cmd,
1280 SilcClientEntry *clients,
1281 unsigned int clients_count)
1283 SilcServer server = cmd->server;
1285 SilcClientEntry entry;
1287 for (i = 0; i < clients_count; i++) {
1290 if (entry->data.registered == FALSE)
1293 if (!entry->nickname) {
1295 unsigned short old_ident;
1300 old_ident = silc_command_get_ident(cmd->payload);
1301 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1302 silc_command_set_command(cmd->payload, SILC_COMMAND_WHOIS);
1303 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1305 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1306 now anyway so make it a good one. */
1307 silc_server_packet_send(server, entry->router->connection,
1308 SILC_PACKET_COMMAND, cmd->packet->flags,
1309 tmpbuf->data, tmpbuf->len, TRUE);
1311 /* Reprocess this packet after received reply */
1312 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1313 silc_command_get_ident(cmd->payload),
1314 silc_server_command_destructor,
1315 silc_server_command_identify,
1316 silc_server_command_dup(cmd));
1318 cmd->pending = TRUE;
1320 /* Put old data back to the Command Payload we just changed */
1321 silc_command_set_ident(cmd->payload, old_ident);
1322 silc_command_set_command(cmd->payload, SILC_COMMAND_IDENTIFY);
1324 silc_buffer_free(tmpbuf);
1333 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1334 SilcClientEntry *clients,
1335 unsigned int clients_count)
1337 SilcServer server = cmd->server;
1339 int i, count = 0, len;
1340 SilcBuffer packet, idp;
1341 SilcClientEntry entry;
1342 SilcCommandStatus status;
1343 unsigned short ident = silc_command_get_ident(cmd->payload);
1345 status = SILC_STATUS_OK;
1346 if (clients_count > 1)
1347 status = SILC_STATUS_LIST_START;
1349 for (i = 0; i < clients_count; i++) {
1352 if (entry->data.registered == FALSE) {
1353 if (clients_count == 1) {
1354 SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1355 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1356 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1357 2, idp->data, idp->len);
1358 silc_buffer_free(idp);
1363 if (count && i - 1 == count)
1367 status = SILC_STATUS_LIST_ITEM;
1369 if (clients_count > 1 && i == clients_count - 1)
1370 status = SILC_STATUS_LIST_END;
1372 /* Send IDENTIFY reply */
1373 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1374 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1378 char nh[256], uh[256];
1379 SilcSocketConnection hsock;
1381 memset(uh, 0, sizeof(uh));
1382 memset(nh, 0, sizeof(nh));
1384 strncat(nh, entry->nickname, strlen(entry->nickname));
1385 if (!strchr(entry->nickname, '@')) {
1386 strncat(nh, "@", 1);
1387 len = entry->router ? strlen(entry->router->server_name) :
1388 strlen(server->server_name);
1389 strncat(nh, entry->router ? entry->router->server_name :
1390 server->server_name, len);
1393 if (!entry->username) {
1394 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1396 2, idp->data, idp->len,
1399 strncat(uh, entry->username, strlen(entry->username));
1400 if (!strchr(entry->username, '@')) {
1401 strncat(uh, "@", 1);
1402 hsock = (SilcSocketConnection)entry->connection;
1403 len = strlen(hsock->hostname);
1404 strncat(uh, hsock->hostname, len);
1407 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1409 2, idp->data, idp->len,
1414 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1415 0, packet->data, packet->len, FALSE);
1417 silc_buffer_free(packet);
1418 silc_buffer_free(idp);
1424 silc_server_command_identify_from_client(SilcServerCommandContext cmd)
1426 SilcServer server = cmd->server;
1427 char *nick = NULL, *server_name = NULL;
1428 int count = 0, clients_count = 0;
1429 SilcClientEntry *clients = NULL, entry;
1430 SilcClientID **client_id = NULL;
1431 unsigned int client_id_count = 0;
1434 /* Protocol dictates that we must always send the received IDENTIFY request
1435 to our router if we are normal server, so let's do it now unless we
1436 are standalone. We will not send any replies to the client until we
1437 have received reply from the router. */
1438 if (server->server_type == SILC_SERVER &&
1439 !cmd->pending && !server->standalone) {
1441 unsigned short old_ident;
1443 old_ident = silc_command_get_ident(cmd->payload);
1444 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1445 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1447 /* Send IDENTIFY command to our router */
1448 silc_server_packet_send(server, (SilcSocketConnection)
1449 server->router->connection,
1450 SILC_PACKET_COMMAND, cmd->packet->flags,
1451 tmpbuf->data, tmpbuf->len, TRUE);
1453 /* Reprocess this packet after received reply from router */
1454 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1455 silc_command_get_ident(cmd->payload),
1456 silc_server_command_destructor,
1457 silc_server_command_identify,
1458 silc_server_command_dup(cmd));
1459 cmd->pending = TRUE;
1461 silc_command_set_ident(cmd->payload, old_ident);
1463 silc_buffer_free(tmpbuf);
1468 /* We are ready to process the command request. Let's search for the
1469 requested client and send reply to the requesting client. */
1471 /* Parse the IDENTIFY request */
1472 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1473 &nick, &server_name, &count,
1474 SILC_COMMAND_IDENTIFY))
1477 /* Get all clients matching that ID or nickname from local list */
1478 if (client_id_count) {
1479 /* Check all Client ID's received in the command packet */
1480 for (i = 0; i < client_id_count; i++) {
1481 entry = silc_idlist_find_client_by_id(server->local_list,
1482 client_id[i], NULL);
1484 clients = silc_realloc(clients, sizeof(*clients) *
1485 (clients_count + 1));
1486 clients[clients_count++] = entry;
1490 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1494 clients = silc_idlist_get_clients_by_hash(server->local_list,
1495 nick, server->md5hash,
1499 /* Check global list as well */
1501 if (client_id_count) {
1502 /* Check all Client ID's received in the command packet */
1503 for (i = 0; i < client_id_count; i++) {
1504 entry = silc_idlist_find_client_by_id(server->global_list,
1505 client_id[i], NULL);
1507 clients = silc_realloc(clients, sizeof(*clients) *
1508 (clients_count + 1));
1509 clients[clients_count++] = entry;
1513 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1517 clients = silc_idlist_get_clients_by_hash(server->global_list,
1518 nick, server->md5hash,
1524 /* Such a client really does not exist in the SILC network. */
1525 if (!client_id_count) {
1526 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1527 SILC_STATUS_ERR_NO_SUCH_NICK,
1528 3, nick, strlen(nick));
1530 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1531 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1532 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1533 2, idp->data, idp->len);
1534 silc_buffer_free(idp);
1539 /* Check that all mandatory fields are present and request those data
1540 from the server who owns the client if necessary. */
1541 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1546 /* Send the command reply to the client */
1547 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1550 if (client_id_count) {
1551 for (i = 0; i < client_id_count; i++)
1552 silc_free(client_id[i]);
1553 silc_free(client_id);
1560 silc_free(server_name);
1566 silc_server_command_identify_from_server(SilcServerCommandContext cmd)
1568 SilcServer server = cmd->server;
1569 char *nick = NULL, *server_name = NULL;
1570 int count = 0, clients_count = 0;
1571 SilcClientEntry *clients = NULL, entry;
1572 SilcClientID **client_id = NULL;
1573 unsigned int client_id_count = 0;
1576 /* Parse the IDENTIFY request */
1577 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1578 &nick, &server_name, &count,
1579 SILC_COMMAND_IDENTIFY))
1582 /* Process the command request. Let's search for the requested client and
1583 send reply to the requesting server. */
1585 if (client_id_count) {
1586 /* Check all Client ID's received in the command packet */
1587 for (i = 0; i < client_id_count; i++) {
1588 entry = silc_idlist_find_client_by_id(server->local_list,
1589 client_id[i], NULL);
1591 clients = silc_realloc(clients, sizeof(*clients) *
1592 (clients_count + 1));
1593 clients[clients_count++] = entry;
1597 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1601 clients = silc_idlist_get_clients_by_hash(server->local_list,
1602 nick, server->md5hash,
1606 /* If we are router we will check our global list as well. */
1607 if (!clients && server->server_type == SILC_ROUTER) {
1608 if (client_id_count) {
1609 /* Check all Client ID's received in the command packet */
1610 for (i = 0; i < client_id_count; i++) {
1611 entry = silc_idlist_find_client_by_id(server->global_list,
1612 client_id[i], NULL);
1614 clients = silc_realloc(clients, sizeof(*clients) *
1615 (clients_count + 1));
1616 clients[clients_count++] = entry;
1620 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1624 clients = silc_idlist_get_clients_by_hash(server->global_list,
1625 nick, server->md5hash,
1631 /* Such a client really does not exist in the SILC network. */
1632 if (!client_id_count) {
1633 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1634 SILC_STATUS_ERR_NO_SUCH_NICK,
1635 3, nick, strlen(nick));
1637 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1638 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1639 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1640 2, idp->data, idp->len);
1641 silc_buffer_free(idp);
1646 /* Check that all mandatory fields are present and request those data
1647 from the server who owns the client if necessary. */
1648 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1653 /* Send the command reply */
1654 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1657 if (client_id_count) {
1658 for (i = 0; i < client_id_count; i++)
1659 silc_free(client_id[i]);
1660 silc_free(client_id);
1667 silc_free(server_name);
1672 SILC_SERVER_CMD_FUNC(identify)
1674 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1677 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1679 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1680 ret = silc_server_command_identify_from_client(cmd);
1681 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) |
1682 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1683 ret = silc_server_command_identify_from_server(cmd);
1686 silc_server_command_free(cmd);
1689 /* Checks string for bad characters and returns TRUE if they are found. */
1691 static int silc_server_command_bad_chars(char *nick)
1693 if (strchr(nick, '\\')) return TRUE;
1694 if (strchr(nick, '\"')) return TRUE;
1695 if (strchr(nick, '´')) return TRUE;
1696 if (strchr(nick, '`')) return TRUE;
1697 if (strchr(nick, '\'')) return TRUE;
1698 if (strchr(nick, '*')) return TRUE;
1699 if (strchr(nick, '/')) return TRUE;
1700 if (strchr(nick, '@')) return TRUE;
1705 /* Server side of command NICK. Sets nickname for user. Setting
1706 nickname causes generation of a new client ID for the client. The
1707 new client ID is sent to the client after changing the nickname. */
1709 SILC_SERVER_CMD_FUNC(nick)
1711 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1712 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1713 SilcServer server = cmd->server;
1714 SilcBuffer packet, nidp, oidp;
1715 SilcClientID *new_id;
1717 unsigned short ident = silc_command_get_ident(cmd->payload);
1719 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1722 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NICK, cmd, 1, 1);
1724 /* Check nickname */
1725 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1726 if (silc_server_command_bad_chars(nick) == TRUE) {
1727 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1728 SILC_STATUS_ERR_BAD_NICKNAME);
1732 if (strlen(nick) > 128)
1735 /* Create new Client ID */
1736 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
1737 cmd->server->md5hash, nick,
1740 /* Send notify about nickname change to our router. We send the new
1741 ID and ask to replace it with the old one. If we are router the
1742 packet is broadcasted. Send NICK_CHANGE notify. */
1743 if (!server->standalone)
1744 silc_server_send_notify_nick_change(server, server->router->connection,
1745 server->server_type == SILC_SERVER ?
1746 FALSE : TRUE, client->id,
1747 new_id, SILC_ID_CLIENT_LEN);
1749 /* Remove old cache entry */
1750 silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
1753 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1757 memset(client->id, 0, SILC_ID_CLIENT_LEN);
1758 silc_free(client->id);
1761 /* Save the nickname as this client is our local client */
1762 if (client->nickname)
1763 silc_free(client->nickname);
1765 client->nickname = strdup(nick);
1766 client->id = new_id;
1768 /* Update client cache */
1769 silc_idcache_add(server->local_list->clients, client->nickname,
1770 strlen(client->nickname), SILC_ID_CLIENT, client->id,
1771 (void *)client, TRUE, FALSE);
1773 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1775 /* Send NICK_CHANGE notify to the client's channels */
1776 silc_server_send_notify_on_channels(server, NULL, client,
1777 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1778 oidp->data, oidp->len,
1779 nidp->data, nidp->len);
1781 /* Send the new Client ID as reply command back to client */
1782 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
1783 SILC_STATUS_OK, ident, 1,
1784 2, nidp->data, nidp->len);
1785 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1786 0, packet->data, packet->len, FALSE);
1788 silc_buffer_free(packet);
1789 silc_buffer_free(nidp);
1790 silc_buffer_free(oidp);
1793 silc_server_command_free(cmd);
1796 /* Sends the LIST command reply */
1799 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
1800 SilcChannelEntry *lch,
1801 unsigned int lch_count,
1802 SilcChannelEntry *gch,
1803 unsigned int gch_count)
1806 SilcBuffer packet, idp;
1807 SilcChannelEntry entry;
1808 SilcCommandStatus status;
1809 unsigned short ident = silc_command_get_ident(cmd->payload);
1811 unsigned char usercount[4];
1814 for (i = 0; i < lch_count; i++)
1815 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
1817 for (i = 0; i < gch_count; i++)
1818 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
1821 status = SILC_STATUS_OK;
1822 if ((lch_count + gch_count) > 1)
1823 status = SILC_STATUS_LIST_START;
1826 for (i = 0; i < lch_count; i++) {
1833 status = SILC_STATUS_LIST_ITEM;
1835 if (i == lch_count - 1 && gch_count)
1837 if (lch_count > 1 && i == lch_count - 1)
1838 status = SILC_STATUS_LIST_END;
1840 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1842 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
1843 topic = "*private*";
1844 memset(usercount, 0, sizeof(usercount));
1846 topic = entry->topic;
1847 users = silc_list_count(entry->user_list);
1848 SILC_PUT32_MSB(users, usercount);
1851 /* Send the reply */
1854 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1856 2, idp->data, idp->len,
1857 3, entry->channel_name,
1858 strlen(entry->channel_name),
1859 4, topic, strlen(topic),
1863 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1865 2, idp->data, idp->len,
1866 3, entry->channel_name,
1867 strlen(entry->channel_name),
1869 silc_server_packet_send(cmd->server, cmd->sock,
1870 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
1871 packet->len, FALSE);
1872 silc_buffer_free(packet);
1873 silc_buffer_free(idp);
1876 status = i ? SILC_STATUS_LIST_ITEM : SILC_STATUS_OK;
1879 for (i = 0; i < gch_count; i++) {
1886 status = SILC_STATUS_LIST_ITEM;
1888 if (gch_count > 1 && i == lch_count - 1)
1889 status = SILC_STATUS_LIST_END;
1891 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1893 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
1894 topic = "*private*";
1895 memset(usercount, 0, sizeof(usercount));
1897 topic = entry->topic;
1898 users = silc_list_count(entry->user_list);
1899 SILC_PUT32_MSB(users, usercount);
1902 /* Send the reply */
1905 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1907 2, idp->data, idp->len,
1908 3, entry->channel_name,
1909 strlen(entry->channel_name),
1910 4, topic, strlen(topic),
1914 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
1916 2, idp->data, idp->len,
1917 3, entry->channel_name,
1918 strlen(entry->channel_name),
1920 silc_server_packet_send(cmd->server, cmd->sock,
1921 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
1922 packet->len, FALSE);
1923 silc_buffer_free(packet);
1924 silc_buffer_free(idp);
1928 /* Server side of LIST command. This lists the channel of the requested
1929 server. Secret channels are not listed. */
1931 SILC_SERVER_CMD_FUNC(list)
1933 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1934 SilcServer server = cmd->server;
1935 SilcChannelID *channel_id = NULL;
1937 unsigned int tmp_len;
1938 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
1939 unsigned int lch_count = 0, gch_count = 0;
1941 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LIST, cmd, 0, 2);
1943 /* Get Channel ID */
1944 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1946 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1948 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
1949 SILC_STATUS_ERR_NO_CHANNEL_ID);
1954 /* Get the channels from local list */
1955 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
1958 /* Get the channels from global list if we are router */
1959 if (server->server_type == SILC_ROUTER)
1960 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
1963 /* Send the reply */
1964 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
1965 gchannels, gch_count);
1968 silc_server_command_free(cmd);
1971 /* Server side of TOPIC command. Sets topic for channel and/or returns
1972 current topic to client. */
1974 SILC_SERVER_CMD_FUNC(topic)
1976 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1977 SilcServer server = cmd->server;
1978 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1979 SilcChannelID *channel_id;
1980 SilcChannelEntry channel;
1981 SilcChannelClientEntry chl;
1982 SilcBuffer packet, idp;
1984 unsigned int argc, tmp_len;
1985 unsigned short ident = silc_command_get_ident(cmd->payload);
1987 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
1989 argc = silc_argument_get_arg_num(cmd->args);
1991 /* Get Channel ID */
1992 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1994 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1995 SILC_STATUS_ERR_NO_CHANNEL_ID);
1998 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2000 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2001 SILC_STATUS_ERR_NO_CHANNEL_ID);
2005 /* Check whether the channel exists */
2006 channel = silc_idlist_find_channel_by_id(server->local_list,
2009 channel = silc_idlist_find_channel_by_id(server->global_list,
2012 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2013 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2020 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2022 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2023 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2027 if (strlen(tmp) > 256) {
2028 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2029 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2033 /* See whether has rights to change topic */
2034 silc_list_start(channel->user_list);
2035 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2036 if (chl->client == client)
2039 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2040 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2041 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2042 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2047 /* Set the topic for channel */
2049 silc_free(channel->topic);
2050 channel->topic = strdup(tmp);
2052 /* Send TOPIC_SET notify type to the network */
2053 if (!server->standalone)
2054 silc_server_send_notify_topic_set(server, server->router->connection,
2055 server->server_type == SILC_ROUTER ?
2056 TRUE : FALSE, channel, client->id,
2057 SILC_ID_CLIENT_LEN, channel->topic);
2059 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2061 /* Send notify about topic change to all clients on the channel */
2062 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2063 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2064 idp->data, idp->len,
2065 channel->topic, strlen(channel->topic));
2066 silc_buffer_free(idp);
2069 /* Send the topic to client as reply packet */
2070 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2072 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2073 SILC_STATUS_OK, ident, 2,
2074 2, idp->data, idp->len,
2076 strlen(channel->topic));
2078 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2079 SILC_STATUS_OK, ident, 1,
2080 2, idp->data, idp->len);
2081 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2082 0, packet->data, packet->len, FALSE);
2084 silc_buffer_free(packet);
2085 silc_buffer_free(idp);
2086 silc_free(channel_id);
2089 silc_server_command_free(cmd);
2092 /* Server side of INVITE command. Invites some client to join some channel. */
2094 SILC_SERVER_CMD_FUNC(invite)
2096 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2097 SilcServer server = cmd->server;
2098 SilcSocketConnection sock = cmd->sock, dest_sock;
2099 SilcClientEntry sender, dest;
2100 SilcClientID *dest_id;
2101 SilcChannelEntry channel;
2102 SilcChannelID *channel_id;
2107 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 2);
2109 /* Get destination ID */
2110 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2112 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2113 SILC_STATUS_ERR_NO_CLIENT_ID);
2116 dest_id = silc_id_payload_parse_id(tmp, len);
2118 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2119 SILC_STATUS_ERR_NO_CLIENT_ID);
2123 /* Get Channel ID */
2124 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2126 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2127 SILC_STATUS_ERR_NO_CHANNEL_ID);
2130 channel_id = silc_id_payload_parse_id(tmp, len);
2132 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2133 SILC_STATUS_ERR_NO_CHANNEL_ID);
2137 /* Check whether the channel exists */
2138 channel = silc_idlist_find_channel_by_id(server->local_list,
2141 channel = silc_idlist_find_channel_by_id(server->global_list,
2144 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2145 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2150 /* Check whether the sender of this command is on the channel. */
2151 sender = (SilcClientEntry)sock->user_data;
2152 if (!silc_server_client_on_channel(sender, channel)) {
2153 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2154 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2158 /* Check whether the channel is invite-only channel. If yes then the
2159 sender of this command must be at least channel operator. */
2160 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2161 SilcChannelClientEntry chl;
2163 silc_list_start(channel->user_list);
2164 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2165 if (chl->client == sender) {
2166 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2167 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2168 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2175 /* Find the connection data for the destination. If it is local we will
2176 send it directly otherwise we will send it to router for routing. */
2177 dest = silc_idlist_find_client_by_id(server->local_list, dest_id, NULL);
2179 dest_sock = (SilcSocketConnection)dest->connection;
2181 dest_sock = silc_server_route_get(server, dest_id, SILC_ID_CLIENT);
2183 /* Check whether the requested client is already on the channel. */
2184 /* XXX if we are normal server we don't know about global clients on
2185 the channel thus we must request it (USERS command), check from
2186 local cache as well. */
2187 if (silc_server_client_on_channel(dest, channel)) {
2188 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2189 SILC_STATUS_ERR_USER_ON_CHANNEL);
2193 sidp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2195 /* Send notify to the client that is invited to the channel */
2196 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2198 SILC_NOTIFY_TYPE_INVITE, 2,
2199 sidp->data, sidp->len, tmp, len);
2201 /* Send command reply */
2202 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2205 silc_buffer_free(sidp);
2208 silc_server_command_free(cmd);
2213 SilcSocketConnection sock;
2217 /* Quits connection to client. This gets called if client won't
2218 close the connection even when it has issued QUIT command. */
2220 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2222 QuitInternal q = (QuitInternal)context;
2224 /* Free all client specific data, such as client entry and entires
2225 on channels this client may be on. */
2226 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2228 q->sock->user_data = NULL;
2230 /* Close the connection on our side */
2231 silc_server_close_connection(q->server, q->sock);
2233 silc_free(q->signoff);
2237 /* Quits SILC session. This is the normal way to disconnect client. */
2239 SILC_SERVER_CMD_FUNC(quit)
2241 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2242 SilcServer server = cmd->server;
2243 SilcSocketConnection sock = cmd->sock;
2245 unsigned char *tmp = NULL;
2246 unsigned int len = 0;
2248 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_QUIT, cmd, 0, 1);
2250 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2253 /* Get destination ID */
2254 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2258 q = silc_calloc(1, sizeof(*q));
2261 q->signoff = tmp ? strdup(tmp) : NULL;
2263 /* We quit the connection with little timeout */
2264 silc_task_register(server->timeout_queue, sock->sock,
2265 silc_server_command_quit_cb, (void *)q,
2266 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2269 silc_server_command_free(cmd);
2272 /* Server side of command KILL. This command is used by router operator
2273 to remove an client from the SILC Network temporarily. */
2275 SILC_SERVER_CMD_FUNC(kill)
2277 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2278 SilcServer server = cmd->server;
2279 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2280 SilcClientEntry remote_client;
2281 SilcClientID *client_id;
2282 unsigned char *tmp, *comment;
2283 unsigned int tmp_len, tmp_len2;
2285 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_KILL, cmd, 1, 2);
2287 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2290 /* KILL command works only on router */
2291 if (server->server_type != SILC_ROUTER) {
2292 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2293 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2297 /* Check whether client has the permissions. */
2298 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2299 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2300 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2304 /* Get the client ID */
2305 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2307 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2308 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2311 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2313 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2314 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2318 /* Get the client entry */
2319 remote_client = silc_idlist_find_client_by_id(server->local_list,
2321 if (!remote_client) {
2322 remote_client = silc_idlist_find_client_by_id(server->global_list,
2324 if (!remote_client) {
2325 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2326 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2332 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2336 /* Send reply to the sender */
2337 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2340 /* Send the KILL notify packets. First send it to the channel, then
2341 to our primary router and then directly to the client who is being
2342 killed right now. */
2344 /* Send KILLED notify to the channels. It is not sent to the client
2345 as it will be sent differently destined directly to the client and not
2347 silc_server_send_notify_on_channels(server, remote_client,
2348 remote_client, SILC_NOTIFY_TYPE_KILLED,
2351 comment, comment ? tmp_len2 : 0);
2353 /* Send KILLED notify to primary route */
2354 if (!server->standalone)
2355 silc_server_send_notify_killed(server, server->router->connection, TRUE,
2356 remote_client->id, SILC_ID_CLIENT_LEN,
2359 /* Send KILLED notify to the client directly */
2360 silc_server_send_notify_killed(server, remote_client->connection ?
2361 remote_client->connection :
2362 remote_client->router->connection, FALSE,
2363 remote_client->id, SILC_ID_CLIENT_LEN,
2366 /* Remove the client from all channels. This generates new keys to the
2367 channels as well. */
2368 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2371 /* Remove the client entry, If it is locally connected then we will also
2372 disconnect the client here */
2373 if (remote_client->data.registered && remote_client->connection) {
2374 /* Remove locally conneted client */
2375 SilcSocketConnection sock = remote_client->connection;
2376 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2377 silc_server_close_connection(server, sock);
2379 /* Remove remote client */
2380 if (!silc_idlist_del_client(server->global_list, remote_client))
2381 silc_idlist_del_client(server->local_list, remote_client);
2385 silc_server_command_free(cmd);
2388 /* Server side of command INFO. This sends information about us to
2389 the client. If client requested specific server we will send the
2390 command to that server. */
2392 SILC_SERVER_CMD_FUNC(info)
2394 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2395 SilcServer server = cmd->server;
2396 SilcBuffer packet, idp;
2397 char *dest_server, *server_info = NULL, *server_name;
2398 unsigned short ident = silc_command_get_ident(cmd->payload);
2399 SilcServerEntry entry = NULL;
2401 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 1);
2403 /* Get server name */
2404 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2406 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2407 SILC_STATUS_ERR_NO_SUCH_SERVER);
2411 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
2412 /* Send our reply */
2413 char info_string[256];
2415 memset(info_string, 0, sizeof(info_string));
2416 snprintf(info_string, sizeof(info_string),
2417 "location: %s server: %s admin: %s <%s>",
2418 server->config->admin_info->location,
2419 server->config->admin_info->server_type,
2420 server->config->admin_info->admin_name,
2421 server->config->admin_info->admin_email);
2423 server_info = info_string;
2424 entry = server->id_entry;
2426 /* Check whether we have this server cached */
2427 entry = silc_idlist_find_server_by_name(server->global_list,
2430 entry = silc_idlist_find_server_by_name(server->local_list,
2434 if (server->server_type == SILC_ROUTER && entry && !entry->server_info) {
2435 /* Send to the server */
2437 unsigned short old_ident;
2439 old_ident = silc_command_get_ident(cmd->payload);
2440 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2441 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2443 silc_server_packet_send(server, entry->connection,
2444 SILC_PACKET_COMMAND, cmd->packet->flags,
2445 tmpbuf->data, tmpbuf->len, TRUE);
2447 /* Reprocess this packet after received reply from router */
2448 silc_server_command_pending(server, SILC_COMMAND_INFO,
2449 silc_command_get_ident(cmd->payload),
2450 silc_server_command_destructor,
2451 silc_server_command_info,
2452 silc_server_command_dup(cmd));
2453 cmd->pending = TRUE;
2454 silc_command_set_ident(cmd->payload, old_ident);
2455 silc_buffer_free(tmpbuf);
2459 if (!entry && !cmd->pending && !server->standalone) {
2460 /* Send to the primary router */
2462 unsigned short old_ident;
2464 old_ident = silc_command_get_ident(cmd->payload);
2465 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2466 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2468 silc_server_packet_send(server, server->router->connection,
2469 SILC_PACKET_COMMAND, cmd->packet->flags,
2470 tmpbuf->data, tmpbuf->len, TRUE);
2472 /* Reprocess this packet after received reply from router */
2473 silc_server_command_pending(server, SILC_COMMAND_INFO,
2474 silc_command_get_ident(cmd->payload),
2475 silc_server_command_destructor,
2476 silc_server_command_info,
2477 silc_server_command_dup(cmd));
2478 cmd->pending = TRUE;
2479 silc_command_set_ident(cmd->payload, old_ident);
2480 silc_buffer_free(tmpbuf);
2486 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2487 SILC_STATUS_ERR_NO_SUCH_SERVER);
2491 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2493 server_info = entry->server_info;
2494 server_name = dest_server;
2496 /* Send the reply */
2497 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2498 SILC_STATUS_OK, ident, 3,
2499 2, idp->data, idp->len,
2501 strlen(server_name),
2503 strlen(server_info));
2504 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2505 packet->data, packet->len, FALSE);
2507 silc_buffer_free(packet);
2508 silc_buffer_free(idp);
2511 silc_server_command_free(cmd);
2514 /* Server side of command PING. This just replies to the ping. */
2516 SILC_SERVER_CMD_FUNC(ping)
2518 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2519 SilcServer server = cmd->server;
2524 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
2527 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2529 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2530 SILC_STATUS_ERR_NO_SERVER_ID);
2533 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2537 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
2538 /* Send our reply */
2539 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2542 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2543 SILC_STATUS_ERR_NO_SUCH_SERVER);
2550 silc_server_command_free(cmd);
2553 /* Internal routine to join channel. The channel sent to this function
2554 has been either created or resolved from ID lists. This joins the sent
2555 client to the channel. */
2557 static void silc_server_command_join_channel(SilcServer server,
2558 SilcServerCommandContext cmd,
2559 SilcChannelEntry channel,
2560 SilcClientID *client_id,
2564 SilcSocketConnection sock = cmd->sock;
2566 unsigned int tmp_len, user_count;
2567 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
2568 SilcClientEntry client;
2569 SilcChannelClientEntry chl;
2570 SilcBuffer reply, chidp, clidp, keyp, user_list, mode_list;
2571 unsigned short ident = silc_command_get_ident(cmd->payload);
2573 SILC_LOG_DEBUG(("Start"));
2578 /* Get passphrase */
2579 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2581 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
2582 memcpy(passphrase, tmp, tmp_len);
2586 * Check channel modes
2589 /* Check invite list if channel is invite-only channel */
2590 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2591 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
2592 /* Invite list is specified. Check whether client is invited in the
2593 list. If not, then check whether it has been invited otherwise. */
2596 /* XXX client must be invited to be able to join the channel */
2600 /* Check ban list if set */
2601 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2605 /* Check the channel passphrase if set. */
2606 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2607 if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
2608 strlen(channel->mode_data.passphrase))) {
2609 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2610 SILC_STATUS_ERR_BAD_PASSWORD);
2615 /* Check user count limit if set. */
2616 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
2617 if (silc_list_count(channel->user_list) + 1 >
2618 channel->mode_data.user_limit) {
2619 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2620 SILC_STATUS_ERR_CHANNEL_IS_FULL);
2626 * Client is allowed to join to the channel. Make it happen.
2629 /* Get the client entry */
2630 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2631 client = (SilcClientEntry)sock->user_data;
2633 client = silc_idlist_find_client_by_id(server->local_list, client_id,
2636 /* XXX actually this is useless since router finds always cell's
2637 local clients from its local lists. */
2638 client = silc_idlist_find_client_by_id(server->global_list, client_id,
2645 /* Check whether the client already is on the channel */
2646 if (silc_server_client_on_channel(client, channel)) {
2647 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2648 SILC_STATUS_ERR_USER_ON_CHANNEL);
2652 /* Generate new channel key as protocol dictates */
2653 if ((!created && silc_list_count(channel->user_list) > 0) ||
2654 !channel->channel_key)
2655 silc_server_create_channel_key(server, channel, 0);
2657 /* Send the channel key. This is broadcasted to the channel but is not
2658 sent to the client who is joining to the channel. */
2659 silc_server_send_channel_key(server, NULL, channel,
2660 server->server_type == SILC_ROUTER ?
2661 FALSE : !server->standalone);
2663 /* Join the client to the channel by adding it to channel's user list.
2664 Add also the channel to client entry's channels list for fast cross-
2666 chl = silc_calloc(1, sizeof(*chl));
2668 chl->client = client;
2669 chl->channel = channel;
2670 silc_list_add(channel->user_list, chl);
2671 silc_list_add(client->channels, chl);
2673 /* Get users on the channel */
2674 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
2677 /* Encode Client ID Payload of the original client who wants to join */
2678 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2680 /* Encode command reply packet */
2681 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2682 SILC_PUT32_MSB(channel->mode, mode);
2683 SILC_PUT32_MSB(created, tmp2);
2684 SILC_PUT32_MSB(user_count, tmp3);
2685 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
2686 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
2687 strlen(channel->channel_key->
2689 channel->channel_key->cipher->name,
2690 channel->key_len / 8, channel->key);
2692 if (!channel->topic) {
2694 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2695 SILC_STATUS_OK, ident, 9,
2696 2, channel->channel_name,
2697 strlen(channel->channel_name),
2698 3, chidp->data, chidp->len,
2699 4, clidp->data, clidp->len,
2702 7, keyp->data, keyp->len,
2704 13, user_list->data, user_list->len,
2705 14, mode_list->data,
2709 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2710 SILC_STATUS_OK, ident, 10,
2711 2, channel->channel_name,
2712 strlen(channel->channel_name),
2713 3, chidp->data, chidp->len,
2714 4, clidp->data, clidp->len,
2717 7, keyp->data, keyp->len,
2719 strlen(channel->topic),
2721 13, user_list->data, user_list->len,
2722 14, mode_list->data,
2726 /* Send command reply */
2727 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
2728 reply->data, reply->len, FALSE);
2730 if (!cmd->pending) {
2731 /* Send JOIN notify to locally connected clients on the channel */
2732 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2733 SILC_NOTIFY_TYPE_JOIN, 2,
2734 clidp->data, clidp->len,
2735 chidp->data, chidp->len);
2737 /* Send JOIN notify packet to our primary router */
2738 if (!server->standalone)
2739 silc_server_send_notify_join(server, server->router->connection,
2740 server->server_type == SILC_ROUTER ?
2741 TRUE : FALSE, channel, client->id,
2742 SILC_ID_CLIENT_LEN);
2745 silc_buffer_free(reply);
2746 silc_buffer_free(clidp);
2747 silc_buffer_free(chidp);
2748 silc_buffer_free(keyp);
2749 silc_buffer_free(user_list);
2750 silc_buffer_free(mode_list);
2754 silc_free(passphrase);
2757 /* Server side of command JOIN. Joins client into requested channel. If
2758 the channel does not exist it will be created. */
2760 SILC_SERVER_CMD_FUNC(join)
2762 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2763 SilcServer server = cmd->server;
2765 char *tmp, *channel_name = NULL, *cipher, *hmac;
2766 SilcChannelEntry channel;
2767 unsigned int umode = 0;
2768 int created = FALSE;
2769 SilcClientID *client_id;
2771 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
2773 /* Get channel name */
2774 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2776 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2777 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2782 if (strlen(channel_name) > 256)
2783 channel_name[255] = '\0';
2785 if (silc_server_command_bad_chars(channel_name) == TRUE) {
2786 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2787 SILC_STATUS_ERR_BAD_CHANNEL);
2788 silc_free(channel_name);
2792 /* Get Client ID of the client who is joining to the channel */
2793 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2795 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2796 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2799 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2801 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2802 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2806 /* Get cipher and hmac name */
2807 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2808 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2810 /* See if the channel exists */
2811 channel = silc_idlist_find_channel_by_name(server->local_list,
2812 channel_name, NULL);
2814 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2815 /* If this is coming from client the Client ID in the command packet must
2816 be same as the client's ID. */
2817 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2818 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2819 if (SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
2820 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2821 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2827 /* Channel not found */
2829 /* If we are standalone server we don't have a router, we just create
2830 the channel by ourselves. */
2831 if (server->standalone) {
2832 channel = silc_server_create_new_channel(server, server->id, cipher,
2833 hmac, channel_name, TRUE);
2834 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2839 /* The channel does not exist on our server. If we are normal server
2840 we will send JOIN command to our router which will handle the
2841 joining procedure (either creates the channel if it doesn't exist
2842 or joins the client to it). */
2843 if (server->server_type == SILC_SERVER) {
2845 unsigned short old_ident;
2847 old_ident = silc_command_get_ident(cmd->payload);
2848 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2849 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2851 /* Send JOIN command to our router */
2852 silc_server_packet_send(server, (SilcSocketConnection)
2853 server->router->connection,
2854 SILC_PACKET_COMMAND, cmd->packet->flags,
2855 tmpbuf->data, tmpbuf->len, TRUE);
2857 /* Reprocess this packet after received reply from router */
2858 silc_server_command_pending(server, SILC_COMMAND_JOIN,
2859 silc_command_get_ident(cmd->payload),
2860 silc_server_command_destructor,
2861 silc_server_command_join,
2862 silc_server_command_dup(cmd));
2863 cmd->pending = TRUE;
2867 /* We are router and the channel does not seem exist so we will check
2868 our global list as well for the channel. */
2869 channel = silc_idlist_find_channel_by_name(server->global_list,
2870 channel_name, NULL);
2872 /* Channel really does not exist, create it */
2873 channel = silc_server_create_new_channel(server, server->id, cipher,
2874 hmac, channel_name, TRUE);
2875 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2882 /* Channel not found */
2884 /* If the command came from router and/or we are normal server then
2885 something went wrong with the joining as the channel was not found.
2886 We can't do anything else but ignore this. */
2887 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
2888 server->server_type == SILC_SERVER)
2891 /* We are router and the channel does not seem exist so we will check
2892 our global list as well for the channel. */
2893 channel = silc_idlist_find_channel_by_name(server->global_list,
2894 channel_name, NULL);
2896 /* Channel really does not exist, create it */
2897 channel = silc_server_create_new_channel(server, server->id, cipher,
2898 hmac, channel_name, TRUE);
2899 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2905 /* If the channel does not have global users and is also empty it means the
2906 channel was created globally (by our router) and the client will be the
2907 channel founder and operator. */
2908 if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
2909 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2910 created = TRUE; /* Created globally by our router */
2913 /* Join to the channel */
2914 silc_server_command_join_channel(server, cmd, channel, client_id,
2917 silc_free(client_id);
2920 silc_server_command_free(cmd);
2923 /* Server side of command MOTD. Sends server's current "message of the
2924 day" to the client. */
2926 SILC_SERVER_CMD_FUNC(motd)
2928 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2929 SilcServer server = cmd->server;
2930 SilcBuffer packet, idp;
2931 char *motd, *dest_server;
2933 unsigned short ident = silc_command_get_ident(cmd->payload);
2935 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 1);
2937 /* Get server name */
2938 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2940 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2941 SILC_STATUS_ERR_NO_SUCH_SERVER);
2945 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
2948 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
2950 if (server->config && server->config->motd &&
2951 server->config->motd->motd_file) {
2953 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
2958 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
2959 SILC_STATUS_OK, ident, 2,
2965 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
2966 SILC_STATUS_OK, ident, 1,
2970 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2971 packet->data, packet->len, FALSE);
2972 silc_buffer_free(packet);
2973 silc_buffer_free(idp);
2975 SilcServerEntry entry;
2977 /* Check whether we have this server cached */
2978 entry = silc_idlist_find_server_by_name(server->global_list,
2981 entry = silc_idlist_find_server_by_name(server->local_list,
2985 if (server->server_type == SILC_ROUTER && !cmd->pending &&
2986 entry && !entry->motd) {
2987 /* Send to the server */
2989 unsigned short old_ident;
2991 old_ident = silc_command_get_ident(cmd->payload);
2992 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2993 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2995 silc_server_packet_send(server, entry->connection,
2996 SILC_PACKET_COMMAND, cmd->packet->flags,
2997 tmpbuf->data, tmpbuf->len, TRUE);
2999 /* Reprocess this packet after received reply from router */
3000 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3001 silc_command_get_ident(cmd->payload),
3002 silc_server_command_destructor,
3003 silc_server_command_motd,
3004 silc_server_command_dup(cmd));
3005 cmd->pending = TRUE;
3006 silc_command_set_ident(cmd->payload, old_ident);
3007 silc_buffer_free(tmpbuf);
3011 if (!entry && !cmd->pending && !server->standalone) {
3012 /* Send to the primary router */
3014 unsigned short old_ident;
3016 old_ident = silc_command_get_ident(cmd->payload);
3017 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3018 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3020 silc_server_packet_send(server, server->router->connection,
3021 SILC_PACKET_COMMAND, cmd->packet->flags,
3022 tmpbuf->data, tmpbuf->len, TRUE);
3024 /* Reprocess this packet after received reply from router */
3025 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3026 silc_command_get_ident(cmd->payload),
3027 silc_server_command_destructor,
3028 silc_server_command_motd,
3029 silc_server_command_dup(cmd));
3030 cmd->pending = TRUE;
3031 silc_command_set_ident(cmd->payload, old_ident);
3032 silc_buffer_free(tmpbuf);
3037 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3038 SILC_STATUS_ERR_NO_SUCH_SERVER);
3042 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3045 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3046 SILC_STATUS_OK, ident, 2,
3049 strlen(entry->motd));
3051 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3052 SILC_STATUS_OK, ident, 1,
3055 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3056 packet->data, packet->len, FALSE);
3057 silc_buffer_free(packet);
3058 silc_buffer_free(idp);
3062 silc_server_command_free(cmd);
3065 /* Server side of command UMODE. Client can use this command to set/unset
3066 user mode. Client actually cannot set itself to be as server/router
3067 operator so this can be used only to unset the modes. */
3069 SILC_SERVER_CMD_FUNC(umode)
3071 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3072 SilcServer server = cmd->server;
3073 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3075 unsigned char *tmp_mask;
3077 unsigned short ident = silc_command_get_ident(cmd->payload);
3079 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3082 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_UMODE, cmd, 2, 2);
3084 /* Get the client's mode mask */
3085 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3087 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3088 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3091 SILC_GET32_MSB(mask, tmp_mask);
3097 if (mask & SILC_UMODE_SERVER_OPERATOR) {
3098 /* Cannot operator mode */
3099 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3100 SILC_STATUS_ERR_PERM_DENIED);
3103 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
3104 /* Remove the server operator rights */
3105 client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3108 if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3109 /* Cannot operator mode */
3110 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3111 SILC_STATUS_ERR_PERM_DENIED);
3114 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
3115 /* Remove the router operator rights */
3116 client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3119 /* Send UMODE change to primary router */
3120 if (!server->standalone)
3121 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3122 client->id, SILC_ID_CLIENT_LEN,
3125 /* Send command reply to sender */
3126 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3127 SILC_STATUS_OK, ident, 1,
3129 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3130 packet->data, packet->len, FALSE);
3131 silc_buffer_free(packet);
3134 silc_server_command_free(cmd);
3137 /* Checks that client has rights to add or remove channel modes. If any
3138 of the checks fails FALSE is returned. */
3140 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3141 SilcChannelClientEntry client,
3144 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3145 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3147 /* Check whether has rights to change anything */
3148 if (!is_op && !is_fo)
3151 /* Check whether has rights to change everything */
3155 /* We know that client is channel operator, check that they are not
3156 changing anything that requires channel founder rights. Rest of the
3157 modes are available automatically for channel operator. */
3159 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3160 if (is_op && !is_fo)
3163 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3164 if (is_op && !is_fo)
3169 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3170 if (is_op && !is_fo)
3173 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3174 if (is_op && !is_fo)
3179 if (mode & SILC_CHANNEL_MODE_CIPHER) {
3180 if (is_op && !is_fo)
3183 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3184 if (is_op && !is_fo)
3192 /* Server side command of CMODE. Changes channel mode */
3194 SILC_SERVER_CMD_FUNC(cmode)
3196 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3197 SilcServer server = cmd->server;
3198 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3199 SilcChannelID *channel_id;
3200 SilcChannelEntry channel;
3201 SilcChannelClientEntry chl;
3202 SilcBuffer packet, cidp;
3203 unsigned char *tmp, *tmp_id, *tmp_mask;
3204 unsigned int argc, mode_mask, tmp_len, tmp_len2;
3205 unsigned short ident = silc_command_get_ident(cmd->payload);
3207 SILC_LOG_DEBUG(("Start"));
3209 argc = silc_argument_get_arg_num(cmd->args);
3211 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3212 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3216 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3217 SILC_STATUS_ERR_TOO_MANY_PARAMS);
3221 /* Get Channel ID */
3222 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3224 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3225 SILC_STATUS_ERR_NO_CHANNEL_ID);
3228 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3230 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3231 SILC_STATUS_ERR_NO_CHANNEL_ID);
3235 /* Get the channel mode mask */
3236 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3238 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3239 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3242 SILC_GET32_MSB(mode_mask, tmp_mask);
3244 /* Get channel entry */
3245 channel = silc_idlist_find_channel_by_id(server->local_list,
3248 channel = silc_idlist_find_channel_by_id(server->global_list,
3251 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3252 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3257 /* Check whether this client is on the channel */
3258 if (!silc_server_client_on_channel(client, channel)) {
3259 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3260 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3264 /* Get entry to the channel user list */
3265 silc_list_start(channel->user_list);
3266 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
3267 if (chl->client == client)
3270 /* Check that client has rights to change any requested channel modes */
3271 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3272 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3273 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3278 * Check the modes. Modes that requires nothing special operation are
3282 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3283 /* Channel uses private keys to protect traffic. Client(s) has set the
3284 key locally they want to use, server does not know that key. */
3285 /* Nothing interesting to do here now */
3287 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3288 /* The mode is removed and we need to generate and distribute
3289 new channel key. Clients are not using private channel keys
3290 anymore after this. */
3292 /* XXX Duplicated code, make own function for this!! LEAVE uses this
3295 /* Re-generate channel key */
3296 silc_server_create_channel_key(server, channel, 0);
3298 /* Encode channel key payload to be distributed on the channel */
3300 silc_channel_key_payload_encode(tmp_len2, tmp_id,
3301 strlen(channel->channel_key->
3303 channel->channel_key->cipher->name,
3304 channel->key_len / 8, channel->key);
3306 /* If we are normal server then we will send it to our router. If we
3307 are router we will send it to all local servers that has clients on
3309 if (server->server_type == SILC_SERVER) {
3310 if (!server->standalone)
3311 silc_server_packet_send(server,
3312 cmd->server->router->connection,
3313 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
3319 /* Send to locally connected clients on the channel */
3320 silc_server_packet_send_local_channel(server, channel,
3321 SILC_PACKET_CHANNEL_KEY, 0,
3322 packet->data, packet->len, FALSE);
3323 silc_buffer_free(packet);
3327 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3328 /* User limit is set on channel */
3329 unsigned int user_limit;
3331 /* Get user limit */
3332 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3334 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3335 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3336 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3340 SILC_GET32_MSB(user_limit, tmp);
3341 channel->mode_data.user_limit = user_limit;
3344 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3345 /* User limit mode is unset. Remove user limit */
3346 channel->mode_data.user_limit = 0;
3349 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3350 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3351 /* Passphrase has been set to channel */
3353 /* Get the passphrase */
3354 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3356 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3357 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3361 /* Save the passphrase */
3362 channel->mode_data.passphrase = strdup(tmp);
3365 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3366 /* Passphrase mode is unset. remove the passphrase */
3367 if (channel->mode_data.passphrase) {
3368 silc_free(channel->mode_data.passphrase);
3369 channel->mode_data.passphrase = NULL;
3374 if (mode_mask & SILC_CHANNEL_MODE_BAN) {
3375 if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
3376 /* Ban list is specified for channel */
3379 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
3381 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3382 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3386 /* XXX check that channel founder is not banned */
3388 /* Save the ban list */
3389 channel->mode_data.ban_list = strdup(tmp);
3392 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
3393 /* Ban mode is unset. Remove the entire ban list */
3394 if (channel->mode_data.ban_list) {
3395 silc_free(channel->mode_data.ban_list);
3396 channel->mode_data.ban_list = NULL;
3401 if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
3402 if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
3403 /* Invite list is specified for channel */
3405 /* Get invite list */
3406 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
3408 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3409 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3413 /* Save the invite linst */
3414 channel->mode_data.invite_list = strdup(tmp);
3417 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
3418 /* Invite list mode is unset. Remove the entire invite list */
3419 if (channel->mode_data.invite_list) {
3420 silc_free(channel->mode_data.invite_list);
3421 channel->mode_data.invite_list = NULL;
3426 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3427 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3428 /* Cipher to use protect the traffic */
3429 unsigned int key_len;
3432 tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
3434 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3435 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3439 /* XXX Duplicated code, make own function for this!! */
3441 /* Delete old cipher and allocate the new one */
3442 silc_cipher_free(channel->channel_key);
3443 if (!silc_cipher_alloc(tmp, &channel->channel_key)) {
3444 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3445 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3448 key_len = silc_cipher_get_key_len(channel->channel_key) / 8;
3450 /* Re-generate channel key */
3451 silc_server_create_channel_key(server, channel, key_len);
3453 /* Encode channel key payload to be distributed on the channel */
3455 silc_channel_key_payload_encode(tmp_len2, tmp_id,
3456 strlen(channel->channel_key->
3458 channel->channel_key->cipher->name,
3459 channel->key_len / 8, channel->key);
3461 /* If we are normal server then we will send it to our router. If we
3462 are router we will send it to all local servers that has clients on
3464 if (server->server_type == SILC_SERVER) {
3465 if (!server->standalone)
3466 silc_server_packet_send(server,
3467 cmd->server->router->connection,
3468 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
3474 /* Send to locally connected clients on the channel */
3475 silc_server_packet_send_local_channel(server, channel,
3476 SILC_PACKET_CHANNEL_KEY, 0,
3477 packet->data, packet->len, FALSE);
3478 silc_buffer_free(packet);
3481 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3482 /* Cipher mode is unset. Remove the cipher and revert back to
3485 if (channel->mode_data.cipher) {
3486 silc_free(channel->mode_data.cipher);
3487 channel->mode_data.cipher = NULL;
3488 channel->mode_data.key_len = 0;
3491 /* Generate new cipher and key for the channel */
3493 /* XXX Duplicated code, make own function for this!! */
3495 /* Delete old cipher and allocate default one */
3496 silc_cipher_free(channel->channel_key);
3497 if (!channel->cipher)
3498 silc_cipher_alloc("aes-256-cbc", &channel->channel_key);
3500 if (!silc_cipher_alloc(channel->cipher, &channel->channel_key)) {
3501 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3502 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3507 /* Re-generate channel key */
3508 silc_server_create_channel_key(server, channel, 0);
3510 /* Encode channel key payload to be distributed on the channel */
3512 silc_channel_key_payload_encode(tmp_len2, tmp_id,
3513 strlen(channel->channel_key->
3515 channel->channel_key->cipher->name,
3516 channel->key_len / 8, channel->key);
3518 /* If we are normal server then we will send it to our router. If we
3519 are router we will send it to all local servers that has clients on
3521 if (server->server_type == SILC_SERVER) {
3522 if (!server->standalone)
3523 silc_server_packet_send(server,
3524 cmd->server->router->connection,
3525 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
3531 /* Send to locally connected clients on the channel */
3532 silc_server_packet_send_local_channel(server, channel,
3533 SILC_PACKET_CHANNEL_KEY, 0,
3534 packet->data, packet->len, FALSE);
3535 silc_buffer_free(packet);
3539 /* Finally, set the mode */
3540 channel->mode = mode_mask;
3542 /* Send CMODE_CHANGE notify */
3543 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3544 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3545 SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
3546 cidp->data, cidp->len,
3549 /* Set CMODE notify type to network */
3550 if (!server->standalone)
3551 silc_server_send_notify_cmode(server, server->router->connection,
3552 server->server_type == SILC_ROUTER ?
3553 TRUE : FALSE, channel,
3554 mode_mask, client->id, SILC_ID_CLIENT_LEN);
3556 /* Send command reply to sender */
3557 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3558 SILC_STATUS_OK, ident, 1,
3560 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3561 packet->data, packet->len, FALSE);
3563 silc_buffer_free(packet);
3564 silc_free(channel_id);
3568 silc_server_command_free(cmd);
3571 /* Server side of CUMODE command. Changes client's mode on a channel. */
3573 SILC_SERVER_CMD_FUNC(cumode)
3575 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3576 SilcServer server = cmd->server;
3577 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3578 SilcChannelID *channel_id;
3579 SilcClientID *client_id;
3580 SilcChannelEntry channel;
3581 SilcClientEntry target_client;
3582 SilcChannelClientEntry chl;
3583 SilcBuffer packet, idp;
3584 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
3585 unsigned int target_mask, sender_mask, tmp_len, tmp_ch_len;
3587 unsigned short ident = silc_command_get_ident(cmd->payload);
3589 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 3);
3591 /* Get Channel ID */
3592 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3594 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3595 SILC_STATUS_ERR_NO_CHANNEL_ID);
3598 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
3600 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3601 SILC_STATUS_ERR_NO_CHANNEL_ID);
3605 /* Get channel entry */
3606 channel = silc_idlist_find_channel_by_id(server->local_list,
3609 channel = silc_idlist_find_channel_by_id(server->global_list,
3612 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3613 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3618 /* Check whether sender is on the channel */
3619 if (!silc_server_client_on_channel(client, channel)) {
3620 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3621 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3625 /* Check that client has rights to change other's rights */
3626 silc_list_start(channel->user_list);
3627 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3628 if (chl->client == client) {
3629 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
3630 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3631 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3632 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3636 sender_mask = chl->mode;
3641 /* Get the target client's channel mode mask */
3642 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3644 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3645 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3648 SILC_GET32_MSB(target_mask, tmp_mask);
3650 /* Get target Client ID */
3651 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3653 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3654 SILC_STATUS_ERR_NO_CLIENT_ID);
3657 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
3659 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3660 SILC_STATUS_ERR_NO_CLIENT_ID);
3664 /* Get target client's entry */
3665 target_client = silc_idlist_find_client_by_id(server->local_list,
3667 if (!target_client) {
3668 target_client = silc_idlist_find_client_by_id(server->global_list,
3672 /* Check whether target client is on the channel */
3673 if (!silc_server_client_on_channel(target_client, channel)) {
3674 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3675 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
3679 /* Get entry to the channel user list */
3680 silc_list_start(channel->user_list);
3681 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
3682 if (chl->client == target_client)
3689 /* If the target client is founder, no one else can change their mode
3691 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
3692 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3693 SILC_STATUS_ERR_NOT_YOU);
3697 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
3698 /* Cannot promote anyone to channel founder */
3699 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3700 SILC_STATUS_ERR_NOT_YOU);
3703 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3704 if (target_client == client) {
3705 /* Remove channel founder rights from itself */
3706 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3709 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3710 SILC_STATUS_ERR_NOT_YOU);
3716 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
3717 /* Promote to operator */
3718 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3719 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
3723 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
3724 /* Demote to normal user */
3725 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
3730 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3732 /* Send notify to channel, notify only if mode was actually changed. */
3734 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3735 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3736 idp->data, idp->len,
3740 /* Set CUMODE notify type to network */
3741 if (!server->standalone)
3742 silc_server_send_notify_cumode(server, server->router->connection,
3743 server->server_type == SILC_ROUTER ?
3744 TRUE : FALSE, channel,
3745 target_mask, client->id,
3748 SILC_ID_CLIENT_LEN);
3751 /* Send command reply to sender */
3752 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
3753 SILC_STATUS_OK, ident, 2,
3755 3, tmp_id, tmp_len);
3756 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3757 packet->data, packet->len, FALSE);
3759 silc_buffer_free(packet);
3760 silc_free(channel_id);
3761 silc_free(client_id);
3762 silc_buffer_free(idp);
3765 silc_server_command_free(cmd);
3768 /* Server side of KICK command. Kicks client out of channel. */
3770 SILC_SERVER_CMD_FUNC(kick)
3772 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3773 SilcServer server = cmd->server;
3774 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3775 SilcClientEntry target_client;
3776 SilcChannelID *channel_id;
3777 SilcClientID *client_id;
3778 SilcChannelEntry channel;
3779 SilcChannelClientEntry chl;
3781 unsigned int tmp_len;
3782 unsigned char *tmp, *comment;
3784 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 3);
3786 /* Get Channel ID */
3787 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3789 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3790 SILC_STATUS_ERR_NO_CHANNEL_ID);
3793 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
3795 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3796 SILC_STATUS_ERR_NO_CHANNEL_ID);
3800 /* Get channel entry */
3801 channel = silc_idlist_find_channel_by_id(server->local_list,
3804 channel = silc_idlist_find_channel_by_id(server->local_list,
3807 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3808 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3813 /* Check whether sender is on the channel */
3814 if (!silc_server_client_on_channel(client, channel)) {
3815 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3816 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3820 /* Check that the kicker is channel operator or channel founder */
3821 silc_list_start(channel->user_list);
3822 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3823 if (chl->client == client) {
3824 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
3825 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3826 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3833 /* Get target Client ID */
3834 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3836 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3837 SILC_STATUS_ERR_NO_CLIENT_ID);
3840 client_id = silc_id_payload_parse_id(tmp, tmp_len);
3842 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3843 SILC_STATUS_ERR_NO_CLIENT_ID);
3847 /* Get target client's entry */
3848 target_client = silc_idlist_find_client_by_id(server->local_list,
3850 if (!target_client) {
3851 target_client = silc_idlist_find_client_by_id(server->global_list,
3855 /* Check that the target client is not channel founder. Channel founder
3856 cannot be kicked from the channel. */
3857 silc_list_start(channel->user_list);
3858 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3859 if (chl->client == target_client) {
3860 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3861 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3862 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
3869 /* Check whether target client is on the channel */
3870 if (!silc_server_client_on_channel(target_client, channel)) {
3871 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3872 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
3878 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3882 /* Send command reply to sender */
3883 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3886 /* Send KICKED notify to local clients on the channel */
3887 idp = silc_id_payload_encode(target_client->id, SILC_ID_CLIENT);
3888 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3889 SILC_NOTIFY_TYPE_KICKED,
3891 idp->data, idp->len,
3892 comment, comment ? strlen(comment) : 0);
3893 silc_buffer_free(idp);
3895 /* Remove the client from the channel. If the channel does not exist
3896 after removing the client then the client kicked itself off the channel
3897 and we don't have to send anything after that. */
3898 if (!silc_server_remove_from_one_channel(server, NULL, channel,
3899 target_client, FALSE))
3902 /* Send KICKED notify to primary route */
3903 if (!server->standalone)
3904 silc_server_send_notify_kicked(server, server->router->connection,
3905 server->server_type == SILC_ROUTER ?
3906 TRUE : FALSE, channel,
3907 target_client->id, SILC_ID_CLIENT_LEN,
3910 /* Re-generate channel key */
3911 silc_server_create_channel_key(server, channel, 0);
3913 /* Send the channel key to the channel. The key of course is not sent
3914 to the client who was kicked off the channel. */
3915 silc_server_send_channel_key(server, target_client->connection, channel,
3916 server->server_type == SILC_ROUTER ?
3917 FALSE : !server->standalone);
3920 silc_server_command_free(cmd);
3923 /* Server side of OPER command. Client uses this comand to obtain server
3924 operator privileges to this server/router. */
3926 SILC_SERVER_CMD_FUNC(oper)
3928 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3929 SilcServer server = cmd->server;
3930 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3931 unsigned char *username, *auth;
3932 unsigned int tmp_len;
3933 SilcServerConfigSectionAdminConnection *admin;
3934 SilcIDListData idata = (SilcIDListData)client;
3936 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_OPER, cmd, 1, 2);
3938 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3941 /* Get the username */
3942 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3944 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3945 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3949 /* Get the admin configuration */
3950 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
3951 username, client->nickname);
3953 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
3954 username, client->nickname);
3956 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3957 SILC_STATUS_ERR_AUTH_FAILED);
3962 /* Get the authentication payload */
3963 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3965 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3966 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3970 /* Verify the authentication data */
3971 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
3972 admin->auth_data, admin->auth_data_len,
3973 idata->hash, client->id, SILC_ID_CLIENT)) {
3974 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3975 SILC_STATUS_ERR_AUTH_FAILED);
3979 /* Client is now server operator */
3980 client->mode |= SILC_UMODE_SERVER_OPERATOR;
3982 /* Send UMODE change to primary router */
3983 if (!server->standalone)
3984 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3985 client->id, SILC_ID_CLIENT_LEN,
3988 /* Send reply to the sender */
3989 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3993 silc_server_command_free(cmd);
3996 /* Server side of SILCOPER command. Client uses this comand to obtain router
3997 operator privileges to this router. */
3999 SILC_SERVER_CMD_FUNC(silcoper)
4001 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4002 SilcServer server = cmd->server;
4003 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4004 unsigned char *username, *auth;
4005 unsigned int tmp_len;
4006 SilcServerConfigSectionAdminConnection *admin;
4007 SilcIDListData idata = (SilcIDListData)client;
4009 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4011 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4014 /* Get the username */
4015 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4017 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4018 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4022 /* Get the admin configuration */
4023 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4024 username, client->nickname);
4026 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4027 username, client->nickname);
4029 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4030 SILC_STATUS_ERR_AUTH_FAILED);
4035 /* Get the authentication payload */
4036 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4038 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4039 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4043 /* Verify the authentication data */
4044 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4045 admin->auth_data, admin->auth_data_len,
4046 idata->hash, client->id, SILC_ID_CLIENT)) {
4047 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4048 SILC_STATUS_ERR_AUTH_FAILED);
4052 /* Client is now router operator */
4053 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4055 /* Send UMODE change to primary router */
4056 if (!server->standalone)
4057 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4058 client->id, SILC_ID_CLIENT_LEN,
4061 /* Send reply to the sender */
4062 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4066 silc_server_command_free(cmd);
4069 /* Server side command of CONNECT. Connects us to the specified remote
4070 server or router. */
4072 SILC_SERVER_CMD_FUNC(connect)
4074 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4075 SilcServer server = cmd->server;
4076 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4077 unsigned char *tmp, *host;
4078 unsigned int tmp_len;
4079 unsigned int port = SILC_PORT;
4081 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CONNECT, cmd, 1, 2);
4083 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4086 /* Check whether client has the permissions. */
4087 if (client->mode == SILC_UMODE_NONE) {
4088 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4089 SILC_STATUS_ERR_NO_SERVER_PRIV);
4093 if (server->server_type == SILC_ROUTER &&
4094 client->mode & SILC_UMODE_SERVER_OPERATOR) {
4095 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4096 SILC_STATUS_ERR_NO_ROUTER_PRIV);
4100 /* Get the remote server */
4101 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4103 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4104 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4109 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4111 SILC_GET32_MSB(port, tmp);
4113 /* Create the connection. It is done with timeout and is async. */
4114 silc_server_create_connection(server, host, port);
4116 /* Send reply to the sender */
4117 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4121 silc_server_command_free(cmd);
4124 SILC_SERVER_CMD_FUNC(restart)
4128 /* Server side command of CLOSE. Closes connection to a specified server. */
4130 SILC_SERVER_CMD_FUNC(close)
4132 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4133 SilcServer server = cmd->server;
4134 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4135 SilcServerEntry server_entry;
4136 SilcSocketConnection sock;
4138 unsigned int tmp_len;
4139 unsigned char *name;
4140 unsigned int port = SILC_PORT;
4142 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CLOSE, cmd, 1, 2);
4144 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4147 /* Check whether client has the permissions. */
4148 if (client->mode == SILC_UMODE_NONE) {
4149 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4150 SILC_STATUS_ERR_NO_SERVER_PRIV);
4154 /* Get the remote server */
4155 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4157 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4158 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4163 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4165 SILC_GET32_MSB(port, tmp);
4167 server_entry = silc_idlist_find_server_by_conn(server->local_list,
4169 if (!server_entry) {
4170 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4171 SILC_STATUS_ERR_NO_SERVER_ID);
4175 /* Send reply to the sender */
4176 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4179 /* Close the connection to the server */
4180 sock = (SilcSocketConnection)server_entry->connection;
4181 silc_server_free_sock_user_data(server, sock);
4182 silc_server_close_connection(server, sock);
4185 silc_server_command_free(cmd);
4188 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4189 active connections. */
4191 SILC_SERVER_CMD_FUNC(shutdown)
4193 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4194 SilcServer server = cmd->server;
4195 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4197 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4199 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4202 /* Check whether client has the permission. */
4203 if (client->mode == SILC_UMODE_NONE) {
4204 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4205 SILC_STATUS_ERR_NO_SERVER_PRIV);
4209 /* Send reply to the sender */
4210 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4213 /* Then, gracefully, or not, bring the server down. */
4214 silc_server_stop(server);
4218 silc_server_command_free(cmd);
4221 /* Server side command of LEAVE. Removes client from a channel. */
4223 SILC_SERVER_CMD_FUNC(leave)
4225 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4226 SilcServer server = cmd->server;
4227 SilcSocketConnection sock = cmd->sock;
4228 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4230 SilcChannelEntry channel;
4232 unsigned int i, len;
4235 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
4237 /* Get Channel ID */
4238 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4240 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4241 SILC_STATUS_ERR_NO_CHANNEL_ID);
4244 id = silc_id_payload_parse_id(tmp, len);
4246 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4247 SILC_STATUS_ERR_NO_CHANNEL_ID);
4251 /* Get channel entry */
4252 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4254 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4256 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4257 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4262 /* Check whether this client is on the channel */
4263 if (!silc_server_client_on_channel(id_entry, channel)) {
4264 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4265 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4269 /* Notify routers that they should remove this client from their list
4270 of clients on the channel. Send LEAVE notify type. */
4271 if (!server->standalone)
4272 silc_server_send_notify_leave(server, server->router->connection,
4273 server->server_type == SILC_ROUTER ?
4274 TRUE : FALSE, channel, id_entry->id,
4275 SILC_ID_CLIENT_LEN);
4277 /* Remove client from channel */
4278 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4280 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4283 /* If the channel does not exist anymore we won't send anything */
4287 /* Re-generate channel key */
4288 silc_server_create_channel_key(server, channel, 0);
4290 /* Encode channel key payload to be distributed on the channel */
4292 silc_channel_key_payload_encode(len, tmp,
4293 strlen(channel->channel_key->cipher->name),
4294 channel->channel_key->cipher->name,
4295 channel->key_len / 8, channel->key);
4297 /* If we are normal server then we will send it to our router. If we
4298 are router we will send it to all local servers that has clients on
4300 if (server->server_type == SILC_SERVER) {
4301 if (!server->standalone)
4302 silc_server_packet_send(server,
4303 cmd->server->router->connection,
4304 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
4305 packet->len, FALSE);
4310 /* Send to locally connected clients on the channel */
4311 silc_server_packet_send_local_channel(server, channel,
4312 SILC_PACKET_CHANNEL_KEY, 0,
4313 packet->data, packet->len, FALSE);
4315 silc_buffer_free(packet);
4319 silc_server_command_free(cmd);
4322 /* Server side of command USERS. Resolves clients and their USERS currently
4323 joined on the requested channel. The list of Client ID's and their modes
4324 on the channel is sent back. */
4326 SILC_SERVER_CMD_FUNC(users)
4328 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4329 SilcServer server = cmd->server;
4330 SilcChannelEntry channel;
4333 unsigned char *channel_id;
4334 unsigned int channel_id_len;
4335 SilcBuffer client_id_list;
4336 SilcBuffer client_mode_list;
4337 unsigned char lc[4];
4338 unsigned int list_count = 0;
4339 unsigned short ident = silc_command_get_ident(cmd->payload);
4341 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
4343 /* Get Channel ID */
4344 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4346 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4347 SILC_STATUS_ERR_NO_CHANNEL_ID);
4350 id = silc_id_payload_parse_id(channel_id, channel_id_len);
4352 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4353 SILC_STATUS_ERR_NO_CHANNEL_ID);
4357 /* If we are server and we don't know about this channel we will send
4358 the command to our router. If we know about the channel then we also
4359 have the list of users already. */
4360 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4362 if (server->server_type == SILC_SERVER && !server->standalone &&
4366 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
4367 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4369 /* Send USERS command */
4370 silc_server_packet_send(server, server->router->connection,
4371 SILC_PACKET_COMMAND, cmd->packet->flags,
4372 tmpbuf->data, tmpbuf->len, TRUE);
4374 /* Reprocess this packet after received reply */
4375 silc_server_command_pending(server, SILC_COMMAND_USERS,
4376 silc_command_get_ident(cmd->payload),
4377 silc_server_command_destructor,
4378 silc_server_command_users,
4379 silc_server_command_dup(cmd));
4380 cmd->pending = TRUE;
4381 silc_command_set_ident(cmd->payload, ident);
4383 silc_buffer_free(tmpbuf);
4388 /* We are router and we will check the global list as well. */
4389 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4391 /* Channel really does not exist */
4392 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4393 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4398 /* Get the users list */
4399 silc_server_get_users_on_channel(server, channel, &client_id_list,
4400 &client_mode_list, &list_count);
4403 SILC_PUT32_MSB(list_count, lc);
4406 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
4407 SILC_STATUS_OK, ident, 4,
4408 2, channel_id, channel_id_len,
4410 4, client_id_list->data,
4411 client_id_list->len,
4412 5, client_mode_list->data,
4413 client_mode_list->len);
4414 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4415 packet->data, packet->len, FALSE);
4417 silc_buffer_free(packet);
4418 silc_buffer_free(client_id_list);
4419 silc_buffer_free(client_mode_list);
4423 silc_server_command_free(cmd);