5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2000 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 static void silc_server_command_free(SilcServerCommandContext cmd);
41 void silc_server_command_send_users(SilcServer server,
42 SilcSocketConnection sock,
43 SilcChannelEntry channel,
46 /* Server command list. */
47 SilcServerCommand silc_command_list[] =
49 SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
50 SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
51 SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
52 SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG | SILC_CF_REG),
53 SILC_SERVER_CMD(list, LIST, SILC_CF_LAG | SILC_CF_REG),
54 SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
55 SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
56 SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
57 SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
58 SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
59 SILC_SERVER_CMD(connect, CONNECT,
60 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
61 SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
62 SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
63 SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG | SILC_CF_REG),
64 SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
65 SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
66 SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG | SILC_CF_REG),
67 SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
68 SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG | SILC_CF_REG),
69 SILC_SERVER_CMD(restart, RESTART,
70 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
71 SILC_SERVER_CMD(close, CLOSE,
72 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
73 SILC_SERVER_CMD(die, DIE, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
74 SILC_SERVER_CMD(silcoper, SILCOPER,
75 SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
76 SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG | SILC_CF_REG),
77 SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
82 #define SILC_SERVER_COMMAND_CHECK_ARGC(command, context, min, max) \
84 unsigned int _argc = silc_argument_get_arg_num(cmd->args); \
86 SILC_LOG_DEBUG(("Start")); \
89 silc_server_command_send_status_reply(cmd, command, \
90 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
91 silc_server_command_free(cmd); \
95 silc_server_command_send_status_reply(cmd, command, \
96 SILC_STATUS_ERR_TOO_MANY_PARAMS); \
97 silc_server_command_free(cmd); \
102 /* Returns TRUE if the connection is registered. Unregistered connections
103 usually cannot send commands hence the check. */
105 static int silc_server_is_registered(SilcServer server,
106 SilcSocketConnection sock,
107 SilcServerCommandContext cmd,
110 SilcIDListData idata = (SilcIDListData)sock->user_data;
111 if (idata->registered)
114 silc_server_command_send_status_reply(cmd, command,
115 SILC_STATUS_ERR_NOT_REGISTERED);
116 silc_server_command_free(cmd);
120 /* Processes received command packet. */
122 void silc_server_command_process(SilcServer server,
123 SilcSocketConnection sock,
124 SilcPacketContext *packet)
126 SilcServerCommandContext ctx;
127 SilcServerCommand *cmd;
130 /* XXX allow commands in but do not execute them more than once per
133 /* Check whether it is allowed for this connection to execute any
135 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
137 SilcClientEntry client = (SilcClientEntry)sock->user_data;
142 /* Allow only one command executed in 2 seconds. */
143 curtime = time(NULL);
144 if (client->last_command && (curtime - client->last_command) < 2)
147 /* Update access time */
148 client->last_command = curtime;
152 /* Allocate command context. This must be free'd by the
153 command routine receiving it. */
154 ctx = silc_calloc(1, sizeof(*ctx));
155 ctx->server = server;
157 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
159 /* Parse the command payload in the packet */
160 ctx->payload = silc_command_payload_parse(packet->buffer);
162 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
163 silc_buffer_free(packet->buffer);
164 silc_packet_context_free(packet);
168 ctx->args = silc_command_get_args(ctx->payload);
170 /* Execute command. If this fails the packet is dropped. */
171 for (cmd = silc_command_list; cmd->cb; cmd++)
172 if (cmd->cmd == silc_command_get(ctx->payload)) {
174 if (!(cmd->flags & SILC_CF_REG)) {
179 if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) {
186 SILC_LOG_ERROR(("Unknown command, packet dropped"));
187 silc_server_command_free(ctx);
192 /* Add new pending command to be executed when reply to a command has been
193 received. The `reply_cmd' is the command that will call the `callback'
194 with `context' when reply has been received. If `ident' is non-zero
195 the `callback' will be executed when received reply with command
196 identifier `ident'. */
198 void silc_server_command_pending(SilcServer server,
199 SilcCommand reply_cmd,
200 unsigned short ident,
201 SilcCommandCb callback,
204 SilcServerCommandPending *reply;
206 reply = silc_calloc(1, sizeof(*reply));
207 reply->reply_cmd = reply_cmd;
208 reply->ident = ident;
209 reply->context = context;
210 reply->callback = callback;
211 silc_dlist_add(server->pending_commands, reply);
214 /* Deletes pending command by reply command type. */
216 void silc_server_command_pending_del(SilcServer server,
217 SilcCommand reply_cmd,
218 unsigned short ident)
220 SilcServerCommandPending *r;
222 silc_dlist_start(server->pending_commands);
223 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
224 if (r->reply_cmd == reply_cmd && r->ident == ident) {
225 silc_dlist_del(server->pending_commands, r);
231 /* Checks for pending commands and marks callbacks to be called from
232 the command reply function. Returns TRUE if there were pending command. */
234 int silc_server_command_pending_check(SilcServer server,
235 SilcServerCommandReplyContext ctx,
237 unsigned short ident)
239 SilcServerCommandPending *r;
241 silc_dlist_start(server->pending_commands);
242 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
243 if (r->reply_cmd == command && r->ident == ident) {
244 ctx->context = r->context;
245 ctx->callback = r->callback;
254 /* Free's the command context allocated before executing the command */
256 static void silc_server_command_free(SilcServerCommandContext cmd)
260 silc_command_free_payload(cmd->payload);
262 silc_packet_context_free(cmd->packet);
267 /* Sends simple status message as command reply packet */
270 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
272 SilcCommandStatus status)
276 SILC_LOG_DEBUG(("Sending command status %d", status));
278 buffer = silc_command_reply_payload_encode_va(command, status, 0, 0);
279 silc_server_packet_send(cmd->server, cmd->sock,
280 SILC_PACKET_COMMAND_REPLY, 0,
281 buffer->data, buffer->len, FALSE);
282 silc_buffer_free(buffer);
285 /* Sends command status reply with one extra argument. The argument
286 type must be sent as argument. */
289 silc_server_command_send_status_data(SilcServerCommandContext cmd,
291 SilcCommandStatus status,
292 unsigned int arg_type,
294 unsigned int arg_len)
298 SILC_LOG_DEBUG(("Sending command status %d", status));
300 buffer = silc_command_reply_payload_encode_va(command, status, 0, 1,
301 arg_type, arg, arg_len);
302 silc_server_packet_send(cmd->server, cmd->sock,
303 SILC_PACKET_COMMAND_REPLY, 0,
304 buffer->data, buffer->len, FALSE);
305 silc_buffer_free(buffer);
308 /******************************************************************************
312 ******************************************************************************/
315 silc_server_command_whois_parse(SilcServerCommandContext cmd,
316 SilcClientID ***client_id,
317 unsigned int *client_id_count,
325 unsigned int argc = silc_argument_get_arg_num(cmd->args);
328 /* If client ID is in the command it must be used instead of nickname */
329 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
331 /* No ID, get the nickname@server string and parse it. */
332 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
334 if (strchr(tmp, '@')) {
335 len = strcspn(tmp, "@");
336 *nickname = silc_calloc(len + 1, sizeof(char));
337 memcpy(*nickname, tmp, len);
338 *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
339 memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
341 *nickname = strdup(tmp);
344 silc_server_command_send_status_reply(cmd, command,
345 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
349 /* Command includes ID, we must use that. Also check whether the command
350 has more than one ID set - take them all. */
352 *client_id = silc_calloc(1, sizeof(**client_id));
353 (*client_id)[0] = silc_id_payload_parse_id(tmp, len);
354 *client_id_count = 1;
356 /* Take all ID's from the command packet */
358 for (k = 1, i = 4; i < argc; i++) {
359 tmp = silc_argument_get_arg_type(cmd->args, i, &len);
361 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
362 (*client_id_count + 1));
363 (*client_id)[k++] = silc_id_payload_parse_id(tmp, len);
364 (*client_id_count)++;
369 /* Command includes ID, use that */
372 /* Get the max count of reply messages allowed */
373 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
383 silc_server_command_whois_check(SilcServerCommandContext cmd,
384 SilcClientEntry *clients,
385 unsigned int clients_count)
387 SilcServer server = cmd->server;
389 SilcClientEntry entry;
391 for (i = 0; i < clients_count; i++) {
394 if (!entry->nickname || !entry->username || !entry->userinfo) {
396 unsigned short old_ident;
401 old_ident = silc_command_get_ident(cmd->payload);
402 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
403 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
405 /* Send WHOIS command */
406 silc_server_packet_send(server, entry->router->connection,
407 SILC_PACKET_COMMAND, cmd->packet->flags,
408 tmpbuf->data, tmpbuf->len, TRUE);
410 /* Reprocess this packet after received reply */
411 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
412 silc_command_get_ident(cmd->payload),
413 silc_server_command_whois, (void *)cmd);
416 silc_command_set_ident(cmd->payload, old_ident);
418 silc_buffer_free(tmpbuf);
427 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
428 SilcClientEntry *clients,
429 unsigned int clients_count)
431 SilcServer server = cmd->server;
433 int i, count = 0, len;
434 SilcBuffer packet, idp;
435 SilcClientEntry entry;
436 SilcCommandStatus status;
437 unsigned short ident = silc_command_get_ident(cmd->payload);
439 status = SILC_STATUS_OK;
440 if (clients_count > 1)
441 status = SILC_STATUS_LIST_START;
443 for (i = 0; i < clients_count; i++) {
446 if (count && i - 1 == count)
449 if (clients_count > 2)
450 status = SILC_STATUS_LIST_ITEM;
452 if (clients_count > 1 && i == clients_count - 1)
453 status = SILC_STATUS_LIST_END;
455 /* Send WHOIS reply */
456 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
457 tmp = silc_argument_get_first_arg(cmd->args, NULL);
461 char nh[256], uh[256];
462 unsigned char idle[4];
463 SilcSocketConnection hsock;
465 memset(uh, 0, sizeof(uh));
466 memset(nh, 0, sizeof(nh));
468 strncat(nh, entry->nickname, strlen(entry->nickname));
469 if (!strchr(entry->nickname, '@')) {
471 len = entry->router ? strlen(entry->router->server_name) :
472 strlen(server->server_name);
473 strncat(nh, entry->router ? entry->router->server_name :
474 server->server_name, len);
477 strncat(uh, entry->username, strlen(entry->username));
478 if (!strchr(entry->username, '@')) {
480 hsock = (SilcSocketConnection)entry->connection;
481 len = strlen(hsock->hostname);
482 strncat(uh, hsock->hostname, len);
485 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
490 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
492 2, idp->data, idp->len,
496 strlen(entry->userinfo),
500 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
502 2, idp->data, idp->len,
508 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
509 0, packet->data, packet->len, FALSE);
511 silc_buffer_free(packet);
512 silc_buffer_free(idp);
517 silc_server_command_whois_from_client(SilcServerCommandContext cmd)
519 SilcServer server = cmd->server;
520 char *nick = NULL, *server_name = NULL;
521 int count = 0, clients_count = 0;
522 SilcClientEntry *clients = NULL, entry;
523 SilcClientID **client_id = NULL;
524 unsigned int client_id_count = 0;
527 /* Protocol dictates that we must always send the received WHOIS request
528 to our router if we are normal server, so let's do it now unless we
529 are standalone. We will not send any replies to the client until we
530 have received reply from the router. */
531 if (server->server_type == SILC_SERVER &&
532 !cmd->pending && !server->standalone) {
534 unsigned short old_ident;
536 old_ident = silc_command_get_ident(cmd->payload);
537 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
538 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
540 /* Send WHOIS command to our router */
541 silc_server_packet_send(server, (SilcSocketConnection)
542 server->router->connection,
543 SILC_PACKET_COMMAND, cmd->packet->flags,
544 tmpbuf->data, tmpbuf->len, TRUE);
546 /* Reprocess this packet after received reply from router */
547 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
548 silc_command_get_ident(cmd->payload),
549 silc_server_command_whois, (void *)cmd);
552 silc_command_set_ident(cmd->payload, old_ident);
554 silc_buffer_free(tmpbuf);
559 /* We are ready to process the command request. Let's search for the
560 requested client and send reply to the requesting client. */
562 /* Parse the whois request */
563 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
564 &nick, &server_name, &count,
568 /* Get all clients matching that ID or nickname from local list */
569 if (client_id_count) {
570 /* Check all Client ID's received in the command packet */
571 for (i = 0; i < client_id_count; i++) {
572 entry = silc_idlist_find_client_by_id(server->local_list,
575 clients = silc_realloc(clients, sizeof(*clients) *
576 (clients_count + 1));
577 clients[clients_count++] = entry;
581 clients = silc_idlist_get_clients_by_nickname(server->local_list,
586 /* Check global list as well */
588 if (client_id_count) {
589 /* Check all Client ID's received in the command packet */
590 for (i = 0; i < client_id_count; i++) {
591 entry = silc_idlist_find_client_by_id(server->global_list,
594 clients = silc_realloc(clients, sizeof(*clients) *
595 (clients_count + 1));
596 clients[clients_count++] = entry;
600 clients = silc_idlist_get_clients_by_nickname(server->global_list,
607 /* Such client(s) really does not exist in the SILC network. */
608 if (!client_id_count) {
609 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
610 SILC_STATUS_ERR_NO_SUCH_NICK,
611 3, nick, strlen(nick));
613 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
614 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
615 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
616 2, idp->data, idp->len);
617 silc_buffer_free(idp);
622 /* Router always finds the client entry if it exists in the SILC network.
623 However, it might be incomplete entry and does not include all the
624 mandatory fields that WHOIS command reply requires. Check for these and
625 make query from the server who owns the client if some fields are
627 if (server->server_type == SILC_ROUTER &&
628 !silc_server_command_whois_check(cmd, clients, clients_count)) {
633 /* Send the command reply to the client */
634 silc_server_command_whois_send_reply(cmd, clients, clients_count);
637 if (client_id_count) {
638 for (i = 0; i < client_id_count; i++)
639 silc_free(client_id[i]);
640 silc_free(client_id);
647 silc_free(server_name);
653 silc_server_command_whois_from_server(SilcServerCommandContext cmd)
655 SilcServer server = cmd->server;
656 char *nick = NULL, *server_name = NULL;
657 int count = 0, clients_count = 0;
658 SilcClientEntry *clients = NULL, entry;
659 SilcClientID **client_id = NULL;
660 unsigned int client_id_count = 0;
663 /* Parse the whois request */
664 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
665 &nick, &server_name, &count,
669 /* Process the command request. Let's search for the requested client and
670 send reply to the requesting server. */
672 if (client_id_count) {
673 /* Check all Client ID's received in the command packet */
674 for (i = 0; i < client_id_count; i++) {
675 entry = silc_idlist_find_client_by_id(server->local_list,
678 clients = silc_realloc(clients, sizeof(*clients) *
679 (clients_count + 1));
680 clients[clients_count++] = entry;
684 clients = silc_idlist_get_clients_by_nickname(server->local_list,
688 clients = silc_idlist_get_clients_by_hash(server->local_list,
689 nick, server->md5hash,
693 /* If we are router we will check our global list as well. */
694 if (!clients && server->server_type == SILC_ROUTER) {
695 if (client_id_count) {
696 /* Check all Client ID's received in the command packet */
697 for (i = 0; i < client_id_count; i++) {
698 entry = silc_idlist_find_client_by_id(server->global_list,
701 clients = silc_realloc(clients, sizeof(*clients) *
702 (clients_count + 1));
703 clients[clients_count++] = entry;
707 clients = silc_idlist_get_clients_by_nickname(server->global_list,
711 clients = silc_idlist_get_clients_by_hash(server->global_list,
712 nick, server->md5hash,
718 /* Such a client really does not exist in the SILC network. */
719 if (!client_id_count) {
720 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
721 SILC_STATUS_ERR_NO_SUCH_NICK,
722 3, nick, strlen(nick));
724 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
725 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
726 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
727 2, idp->data, idp->len);
728 silc_buffer_free(idp);
733 /* Router always finds the client entry if it exists in the SILC network.
734 However, it might be incomplete entry and does not include all the
735 mandatory fields that WHOIS command reply requires. Check for these and
736 make query from the server who owns the client if some fields are
738 if (server->server_type == SILC_ROUTER &&
739 !silc_server_command_whois_check(cmd, clients, clients_count)) {
744 /* Send the command reply to the client */
745 silc_server_command_whois_send_reply(cmd, clients, clients_count);
748 if (client_id_count) {
749 for (i = 0; i < client_id_count; i++)
750 silc_free(client_id[i]);
751 silc_free(client_id);
758 silc_free(server_name);
763 /* Server side of command WHOIS. Processes user's query and sends found
764 results as command replies back to the client. */
766 SILC_SERVER_CMD_FUNC(whois)
768 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
771 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOIS, cmd, 1, 3328);
773 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
774 ret = silc_server_command_whois_from_client(cmd);
776 ret = silc_server_command_whois_from_server(cmd);
779 silc_server_command_free(cmd);
782 SILC_SERVER_CMD_FUNC(whowas)
786 /******************************************************************************
790 ******************************************************************************/
792 /* Checks that all mandatory fields are present. If not then send WHOIS
793 request to the server who owns the client. We use WHOIS because we want
794 to get as much information as possible at once. */
797 silc_server_command_identify_check(SilcServerCommandContext cmd,
798 SilcClientEntry *clients,
799 unsigned int clients_count)
801 SilcServer server = cmd->server;
803 SilcClientEntry entry;
805 for (i = 0; i < clients_count; i++) {
808 if (!entry->nickname) {
810 unsigned short old_ident;
815 old_ident = silc_command_get_ident(cmd->payload);
816 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
817 silc_command_set_command(cmd->payload, SILC_COMMAND_WHOIS);
818 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
820 /* Send WHOIS request. We send WHOIS since we're doing the requesting
821 now anyway so make it a good one. */
822 silc_server_packet_send(server, entry->router->connection,
823 SILC_PACKET_COMMAND, cmd->packet->flags,
824 tmpbuf->data, tmpbuf->len, TRUE);
826 /* Reprocess this packet after received reply */
827 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
828 silc_command_get_ident(cmd->payload),
829 silc_server_command_identify, (void *)cmd);
832 /* Put old data back to the Command Payload we just changed */
833 silc_command_set_ident(cmd->payload, old_ident);
834 silc_command_set_command(cmd->payload, SILC_COMMAND_IDENTIFY);
836 silc_buffer_free(tmpbuf);
845 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
846 SilcClientEntry *clients,
847 unsigned int clients_count)
849 SilcServer server = cmd->server;
851 int i, count = 0, len;
852 SilcBuffer packet, idp;
853 SilcClientEntry entry;
854 SilcCommandStatus status;
855 unsigned short ident = silc_command_get_ident(cmd->payload);
857 status = SILC_STATUS_OK;
858 if (clients_count > 1)
859 status = SILC_STATUS_LIST_START;
861 for (i = 0; i < clients_count; i++) {
864 if (count && i - 1 == count)
867 if (clients_count > 2)
868 status = SILC_STATUS_LIST_ITEM;
870 if (clients_count > 1 && i == clients_count - 1)
871 status = SILC_STATUS_LIST_END;
873 /* Send IDENTIFY reply */
874 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
875 tmp = silc_argument_get_first_arg(cmd->args, NULL);
879 char nh[256], uh[256];
880 SilcSocketConnection hsock;
882 memset(uh, 0, sizeof(uh));
883 memset(nh, 0, sizeof(nh));
885 strncat(nh, entry->nickname, strlen(entry->nickname));
886 if (!strchr(entry->nickname, '@')) {
888 len = entry->router ? strlen(entry->router->server_name) :
889 strlen(server->server_name);
890 strncat(nh, entry->router ? entry->router->server_name :
891 server->server_name, len);
894 if (!entry->username) {
895 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
896 SILC_STATUS_OK, ident, 2,
897 2, idp->data, idp->len,
900 strncat(uh, entry->username, strlen(entry->username));
901 if (!strchr(entry->username, '@')) {
903 hsock = (SilcSocketConnection)entry->connection;
904 len = strlen(hsock->hostname);
905 strncat(uh, hsock->hostname, len);
908 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
909 SILC_STATUS_OK, ident, 3,
910 2, idp->data, idp->len,
915 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
916 0, packet->data, packet->len, FALSE);
918 silc_buffer_free(packet);
919 silc_buffer_free(idp);
925 silc_server_command_identify_from_client(SilcServerCommandContext cmd)
927 SilcServer server = cmd->server;
928 char *nick = NULL, *server_name = NULL;
929 int count = 0, clients_count = 0;
930 SilcClientEntry *clients = NULL, entry;
931 SilcClientID **client_id = NULL;
932 unsigned int client_id_count = 0;
935 /* Protocol dictates that we must always send the received IDENTIFY request
936 to our router if we are normal server, so let's do it now unless we
937 are standalone. We will not send any replies to the client until we
938 have received reply from the router. */
939 if (server->server_type == SILC_SERVER &&
940 !cmd->pending && !server->standalone) {
942 unsigned short old_ident;
944 old_ident = silc_command_get_ident(cmd->payload);
945 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
946 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
948 /* Send IDENTIFY command to our router */
949 silc_server_packet_send(server, (SilcSocketConnection)
950 server->router->connection,
951 SILC_PACKET_COMMAND, cmd->packet->flags,
952 tmpbuf->data, tmpbuf->len, TRUE);
954 /* Reprocess this packet after received reply from router */
955 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
956 silc_command_get_ident(cmd->payload),
957 silc_server_command_identify, (void *)cmd);
960 silc_command_set_ident(cmd->payload, old_ident);
962 silc_buffer_free(tmpbuf);
967 /* We are ready to process the command request. Let's search for the
968 requested client and send reply to the requesting client. */
970 /* Parse the IDENTIFY request */
971 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
972 &nick, &server_name, &count,
973 SILC_COMMAND_IDENTIFY))
976 /* Get all clients matching that ID or nickname from local list */
977 if (client_id_count) {
978 /* Check all Client ID's received in the command packet */
979 for (i = 0; i < client_id_count; i++) {
980 entry = silc_idlist_find_client_by_id(server->local_list,
983 clients = silc_realloc(clients, sizeof(*clients) *
984 (clients_count + 1));
985 clients[clients_count++] = entry;
989 clients = silc_idlist_get_clients_by_nickname(server->local_list,
994 /* Check global list as well */
996 if (client_id_count) {
997 /* Check all Client ID's received in the command packet */
998 for (i = 0; i < client_id_count; i++) {
999 entry = silc_idlist_find_client_by_id(server->global_list,
1000 client_id[i], NULL);
1002 clients = silc_realloc(clients, sizeof(*clients) *
1003 (clients_count + 1));
1004 clients[clients_count++] = entry;
1008 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1015 /* Such a client really does not exist in the SILC network. */
1016 if (!client_id_count) {
1017 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1018 SILC_STATUS_ERR_NO_SUCH_NICK,
1019 3, nick, strlen(nick));
1021 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1022 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1023 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1024 2, idp->data, idp->len);
1025 silc_buffer_free(idp);
1030 /* Check that all mandatory fields are present and request those data
1031 from the server who owns the client if necessary. */
1032 if (!cmd->pending && server->server_type == SILC_ROUTER &&
1033 !silc_server_command_identify_check(cmd, clients, clients_count)) {
1038 /* Send the command reply to the client */
1039 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1042 if (client_id_count) {
1043 for (i = 0; i < client_id_count; i++)
1044 silc_free(client_id[i]);
1045 silc_free(client_id);
1052 silc_free(server_name);
1058 silc_server_command_identify_from_server(SilcServerCommandContext cmd)
1060 SilcServer server = cmd->server;
1061 char *nick = NULL, *server_name = NULL;
1062 int count = 0, clients_count = 0;
1063 SilcClientEntry *clients = NULL, entry;
1064 SilcClientID **client_id = NULL;
1065 unsigned int client_id_count = 0;
1068 /* Parse the IDENTIFY request */
1069 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1070 &nick, &server_name, &count,
1071 SILC_COMMAND_IDENTIFY))
1074 /* Process the command request. Let's search for the requested client and
1075 send reply to the requesting server. */
1077 if (client_id_count) {
1078 /* Check all Client ID's received in the command packet */
1079 for (i = 0; i < client_id_count; i++) {
1080 entry = silc_idlist_find_client_by_id(server->local_list,
1081 client_id[i], NULL);
1083 clients = silc_realloc(clients, sizeof(*clients) *
1084 (clients_count + 1));
1085 clients[clients_count++] = entry;
1089 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1093 clients = silc_idlist_get_clients_by_hash(server->local_list,
1094 nick, server->md5hash,
1098 /* If we are router we will check our global list as well. */
1099 if (!clients && server->server_type == SILC_ROUTER) {
1100 if (client_id_count) {
1101 /* Check all Client ID's received in the command packet */
1102 for (i = 0; i < client_id_count; i++) {
1103 entry = silc_idlist_find_client_by_id(server->global_list,
1104 client_id[i], NULL);
1106 clients = silc_realloc(clients, sizeof(*clients) *
1107 (clients_count + 1));
1108 clients[clients_count++] = entry;
1112 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1116 clients = silc_idlist_get_clients_by_hash(server->global_list,
1117 nick, server->md5hash,
1123 /* Such a client really does not exist in the SILC network. */
1124 if (!client_id_count) {
1125 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1126 SILC_STATUS_ERR_NO_SUCH_NICK,
1127 3, nick, strlen(nick));
1129 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1130 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1131 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1132 2, idp->data, idp->len);
1133 silc_buffer_free(idp);
1138 /* Check that all mandatory fields are present and request those data
1139 from the server who owns the client if necessary. */
1140 if (!cmd->pending && server->server_type == SILC_ROUTER &&
1141 !silc_server_command_identify_check(cmd, clients, clients_count)) {
1146 /* Send the command reply */
1147 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1150 if (client_id_count) {
1151 for (i = 0; i < client_id_count; i++)
1152 silc_free(client_id[i]);
1153 silc_free(client_id);
1160 silc_free(server_name);
1165 SILC_SERVER_CMD_FUNC(identify)
1167 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1170 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1172 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1173 ret = silc_server_command_identify_from_client(cmd);
1175 ret = silc_server_command_identify_from_server(cmd);
1178 silc_server_command_free(cmd);
1181 /* Checks string for bad characters and returns TRUE if they are found. */
1183 static int silc_server_command_bad_chars(char *nick)
1185 if (strchr(nick, '\\')) return TRUE;
1186 if (strchr(nick, '\"')) return TRUE;
1187 if (strchr(nick, '´')) return TRUE;
1188 if (strchr(nick, '`')) return TRUE;
1189 if (strchr(nick, '\'')) return TRUE;
1190 if (strchr(nick, '*')) return TRUE;
1191 if (strchr(nick, '/')) return TRUE;
1192 if (strchr(nick, '@')) return TRUE;
1197 /* Server side of command NICK. Sets nickname for user. Setting
1198 nickname causes generation of a new client ID for the client. The
1199 new client ID is sent to the client after changing the nickname. */
1201 SILC_SERVER_CMD_FUNC(nick)
1203 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1204 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1205 SilcServer server = cmd->server;
1206 SilcBuffer packet, nidp, oidp;
1207 SilcClientID *new_id;
1210 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NICK, cmd, 1, 1);
1212 /* Check nickname */
1213 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1214 if (silc_server_command_bad_chars(nick) == TRUE) {
1215 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1216 SILC_STATUS_ERR_BAD_NICKNAME);
1220 /* Create new Client ID */
1221 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
1222 cmd->server->md5hash, nick,
1225 /* Send notify about nickname change to our router. We send the new
1226 ID and ask to replace it with the old one. If we are router the
1227 packet is broadcasted. */
1228 if (!server->standalone)
1229 silc_server_send_replace_id(server, server->router->connection,
1230 server->server_type == SILC_SERVER ?
1231 FALSE : TRUE, client->id,
1232 SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
1233 new_id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
1235 /* Remove old cache entry */
1236 silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
1239 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1243 memset(client->id, 0, SILC_ID_CLIENT_LEN);
1244 silc_free(client->id);
1247 /* Save the nickname as this client is our local client */
1248 if (client->nickname)
1249 silc_free(client->nickname);
1251 client->nickname = strdup(nick);
1252 client->id = new_id;
1254 /* Update client cache */
1255 silc_idcache_add(server->local_list->clients, client->nickname,
1256 SILC_ID_CLIENT, client->id, (void *)client, TRUE);
1258 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1260 /* Send NICK_CHANGE notify */
1261 silc_server_send_notify_on_channels(server, client,
1262 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1263 oidp->data, oidp->len,
1264 nidp->data, nidp->len);
1266 /* Send the new Client ID as reply command back to client */
1267 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
1268 SILC_STATUS_OK, 0, 1,
1269 2, nidp->data, nidp->len);
1270 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1271 0, packet->data, packet->len, FALSE);
1273 silc_buffer_free(packet);
1274 silc_buffer_free(nidp);
1275 silc_buffer_free(oidp);
1278 silc_server_command_free(cmd);
1281 SILC_SERVER_CMD_FUNC(list)
1285 /* Server side of TOPIC command. Sets topic for channel and/or returns
1286 current topic to client. */
1288 SILC_SERVER_CMD_FUNC(topic)
1290 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1291 SilcServer server = cmd->server;
1292 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1293 SilcChannelID *channel_id;
1294 SilcChannelEntry channel;
1295 SilcChannelClientEntry chl;
1296 SilcBuffer packet, idp;
1298 unsigned int argc, tmp_len;
1300 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
1302 argc = silc_argument_get_arg_num(cmd->args);
1304 /* Get Channel ID */
1305 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1307 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1308 SILC_STATUS_ERR_NO_CHANNEL_ID);
1311 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1313 /* Check whether the channel exists */
1314 channel = silc_idlist_find_channel_by_id(server->local_list,
1317 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1318 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1324 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1326 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1327 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1331 if (strlen(tmp) > 256) {
1332 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1333 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1337 /* See whether has rights to change topic */
1338 silc_list_start(channel->user_list);
1339 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
1340 if (chl->client == client) {
1341 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1342 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1343 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1351 /* Set the topic for channel */
1353 silc_free(channel->topic);
1354 channel->topic = strdup(tmp);
1356 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1358 /* Send notify about topic change to all clients on the channel */
1359 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
1360 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
1361 idp->data, idp->len,
1362 channel->topic, strlen(channel->topic));
1363 silc_buffer_free(idp);
1366 /* Send the topic to client as reply packet */
1367 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1369 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1370 SILC_STATUS_OK, 0, 2,
1371 2, idp->data, idp->len,
1373 strlen(channel->topic));
1375 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1376 SILC_STATUS_OK, 0, 1,
1377 2, idp->data, idp->len);
1378 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1379 0, packet->data, packet->len, FALSE);
1381 silc_buffer_free(packet);
1382 silc_buffer_free(idp);
1383 silc_free(channel_id);
1386 silc_server_command_free(cmd);
1389 /* Server side of INVITE command. Invites some client to join some channel. */
1391 SILC_SERVER_CMD_FUNC(invite)
1393 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1394 SilcServer server = cmd->server;
1395 SilcSocketConnection sock = cmd->sock, dest_sock;
1396 SilcClientEntry sender, dest;
1397 SilcClientID *dest_id;
1398 SilcChannelEntry channel;
1399 SilcChannelID *channel_id;
1404 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 2);
1406 /* Get destination ID */
1407 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1409 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1410 SILC_STATUS_ERR_NO_CLIENT_ID);
1413 dest_id = silc_id_payload_parse_id(tmp, len);
1415 /* Get Channel ID */
1416 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1418 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1419 SILC_STATUS_ERR_NO_CHANNEL_ID);
1422 channel_id = silc_id_payload_parse_id(tmp, len);
1424 /* Check whether the channel exists */
1425 channel = silc_idlist_find_channel_by_id(server->local_list,
1428 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1429 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1433 /* Check whether the sender of this command is on the channel. */
1434 sender = (SilcClientEntry)sock->user_data;
1435 if (!silc_server_client_on_channel(sender, channel)) {
1436 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1437 SILC_STATUS_ERR_NOT_ON_CHANNEL);
1441 /* Check whether the channel is invite-only channel. If yes then the
1442 sender of this command must be at least channel operator. */
1443 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1444 SilcChannelClientEntry chl;
1446 silc_list_start(channel->user_list);
1447 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1448 if (chl->client == sender) {
1449 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1450 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1451 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1458 /* Find the connection data for the destination. If it is local we will
1459 send it directly otherwise we will send it to router for routing. */
1460 dest = silc_idlist_find_client_by_id(server->local_list, dest_id, NULL);
1462 dest_sock = (SilcSocketConnection)dest->connection;
1464 dest_sock = silc_server_route_get(server, dest_id, SILC_ID_CLIENT);
1466 /* Check whether the requested client is already on the channel. */
1467 /* XXX if we are normal server we don't know about global clients on
1468 the channel thus we must request it (USERS command), check from
1469 local cache as well. */
1470 if (silc_server_client_on_channel(dest, channel)) {
1471 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1472 SILC_STATUS_ERR_USER_ON_CHANNEL);
1476 sidp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1478 /* Send notify to the client that is invited to the channel */
1479 silc_server_send_notify_dest(server, dest_sock, dest_id, SILC_ID_CLIENT,
1480 SILC_NOTIFY_TYPE_INVITE, 2,
1481 sidp->data, sidp->len, tmp, len);
1483 /* Send command reply */
1484 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1487 silc_buffer_free(sidp);
1490 silc_server_command_free(cmd);
1493 /* Quits connection to client. This gets called if client won't
1494 close the connection even when it has issued QUIT command. */
1496 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
1498 SilcServer server = (SilcServer)context;
1499 SilcSocketConnection sock = server->sockets[fd];
1501 /* Free all client specific data, such as client entry and entires
1502 on channels this client may be on. */
1503 silc_server_free_sock_user_data(server, sock);
1505 /* Close the connection on our side */
1506 silc_server_close_connection(server, sock);
1509 /* Quits SILC session. This is the normal way to disconnect client. */
1511 SILC_SERVER_CMD_FUNC(quit)
1513 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1514 SilcServer server = cmd->server;
1515 SilcSocketConnection sock = cmd->sock;
1517 SILC_LOG_DEBUG(("Start"));
1519 /* We quit the connection with little timeout */
1520 silc_task_register(server->timeout_queue, sock->sock,
1521 silc_server_command_quit_cb, server,
1522 0, 300000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1524 silc_server_command_free(cmd);
1527 SILC_SERVER_CMD_FUNC(kill)
1531 /* Server side of command INFO. This sends information about us to
1532 the client. If client requested specific server we will send the
1533 command to that server. */
1535 SILC_SERVER_CMD_FUNC(info)
1537 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1538 SilcServer server = cmd->server;
1539 SilcBuffer packet, idp;
1540 char info_string[256], *dest_server;
1542 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 1);
1544 /* Get server name */
1545 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1547 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1548 SILC_STATUS_ERR_NO_SUCH_SERVER);
1552 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
1553 /* Send our reply */
1554 memset(info_string, 0, sizeof(info_string));
1555 snprintf(info_string, sizeof(info_string),
1556 "location: %s server: %s admin: %s <%s>",
1557 server->config->admin_info->location,
1558 server->config->admin_info->server_type,
1559 server->config->admin_info->admin_name,
1560 server->config->admin_info->admin_email);
1562 idp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1564 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
1565 SILC_STATUS_OK, 0, 2,
1566 2, idp->data, idp->len,
1568 strlen(info_string));
1569 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1570 packet->data, packet->len, FALSE);
1572 silc_buffer_free(packet);
1573 silc_buffer_free(idp);
1575 /* Send this command to the requested server */
1577 if (server->server_type == SILC_SERVER && !server->standalone) {
1581 if (server->server_type == SILC_ROUTER) {
1587 silc_server_command_free(cmd);
1590 SILC_SERVER_CMD_FUNC(connect)
1594 /* Server side of command PING. This just replies to the ping. */
1596 SILC_SERVER_CMD_FUNC(ping)
1598 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1599 SilcServer server = cmd->server;
1604 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
1607 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1609 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1610 SILC_STATUS_ERR_NO_SERVER_ID);
1613 id = silc_id_str2id(tmp, SILC_ID_SERVER);
1617 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
1618 /* Send our reply */
1619 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1622 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1623 SILC_STATUS_ERR_NO_SUCH_SERVER);
1630 silc_server_command_free(cmd);
1633 SILC_SERVER_CMD_FUNC(oper)
1637 /* Assembles USERS command and executes it. This is called when client
1638 joins to a channel and we wan't to send USERS command reply to the
1641 void silc_server_command_send_users(SilcServer server,
1642 SilcSocketConnection sock,
1643 SilcChannelEntry channel,
1646 SilcServerCommandContext cmd;
1647 SilcBuffer buffer, idp;
1648 SilcPacketContext *packet = silc_packet_context_alloc();
1650 SILC_LOG_DEBUG(("Start"));
1652 /* Create USERS command packet and process it. */
1653 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1654 buffer = silc_command_payload_encode_va(SILC_COMMAND_USERS, 0, 1,
1655 1, idp->data, idp->len);
1657 packet->buffer = silc_buffer_copy(buffer);
1658 packet->sock = sock;
1659 packet->type = SILC_PACKET_COMMAND;
1661 cmd = silc_calloc(1, sizeof(*cmd));
1662 cmd->payload = silc_command_payload_parse(buffer);
1663 cmd->args = silc_command_get_args(cmd->payload);
1664 cmd->server = server;
1666 cmd->packet = silc_packet_context_dup(packet);
1667 cmd->pending = FALSE;
1670 /* If this function was called from pending command then instead of
1671 processing the command now, register a pending command callback which
1672 will process it after we've received the automatic USERS command
1674 silc_server_command_pending(server, SILC_COMMAND_USERS, 0,
1675 silc_server_command_users, (void *)cmd);
1676 cmd->pending = TRUE;
1682 /* Process USERS command. */
1683 silc_server_command_users((void *)cmd);
1687 silc_packet_context_free(packet);
1690 /* Internal routine to join channel. The channel sent to this function
1691 has been either created or resolved from ID lists. This joins the sent
1692 client to the channel. */
1694 static void silc_server_command_join_channel(SilcServer server,
1695 SilcServerCommandContext cmd,
1696 SilcChannelEntry channel,
1697 SilcClientID *client_id,
1701 SilcSocketConnection sock = cmd->sock;
1703 unsigned int tmp_len;
1704 unsigned char *passphrase = NULL, mode[4], tmp2[4];
1705 SilcClientEntry client;
1706 SilcChannelClientEntry chl;
1707 SilcBuffer reply, chidp, clidp, keyp;
1708 unsigned short ident = silc_command_get_ident(cmd->payload);
1710 SILC_LOG_DEBUG(("Start"));
1715 /* Get passphrase */
1716 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1718 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
1719 memcpy(passphrase, tmp, tmp_len);
1723 * Check channel modes
1726 /* Check invite list if channel is invite-only channel */
1727 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1728 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1729 /* Invite list is specified. Check whether client is invited in the
1730 list. If not, then check whether it has been invited otherwise. */
1733 /* XXX client must be invited to be able to join the channel */
1737 /* Check ban list if set */
1738 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1742 /* Check the channel passphrase if set. */
1743 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1744 if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
1745 strlen(channel->mode_data.passphrase))) {
1746 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1747 SILC_STATUS_ERR_BAD_PASSWORD);
1752 /* Check user count limit if set. */
1753 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
1754 if (silc_list_count(channel->user_list) + 1 >
1755 channel->mode_data.user_limit) {
1756 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1757 SILC_STATUS_ERR_CHANNEL_IS_FULL);
1763 * Client is allowed to join to the channel. Make it happen.
1766 /* Get the client entry */
1767 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1768 client = (SilcClientEntry)sock->user_data;
1770 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1773 /* XXX actually this is useless since router finds always cell's
1774 local clients from its local lists. */
1775 client = silc_idlist_find_client_by_id(server->global_list, client_id,
1782 /* Check whether the client already is on the channel */
1783 if (silc_server_client_on_channel(client, channel)) {
1784 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1785 SILC_STATUS_ERR_USER_ON_CHANNEL);
1789 /* Generate new channel key as protocol dictates */
1790 if (!created || !channel->channel_key)
1791 silc_server_create_channel_key(server, channel, 0);
1793 /* Send the channel key. This is broadcasted to the channel but is not
1794 sent to the client who is joining to the channel. */
1795 silc_server_send_channel_key(server, NULL, channel,
1796 server->server_type == SILC_ROUTER ?
1797 FALSE : server->standalone);
1799 /* Join the client to the channel by adding it to channel's user list.
1800 Add also the channel to client entry's channels list for fast cross-
1802 chl = silc_calloc(1, sizeof(*chl));
1804 chl->client = client;
1805 chl->channel = channel;
1806 silc_list_add(channel->user_list, chl);
1807 silc_list_add(client->channels, chl);
1809 /* Encode Client ID Payload of the original client who wants to join */
1810 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1812 /* Encode command reply packet */
1813 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1814 SILC_PUT32_MSB(channel->mode, mode);
1815 SILC_PUT32_MSB(created, tmp2);
1816 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1817 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
1818 SILC_ID_CHANNEL_LEN,
1819 channel->channel_key->cipher->name,
1820 channel->key_len / 8, channel->key);
1822 if (!channel->topic) {
1824 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1825 SILC_STATUS_OK, ident, 5,
1826 2, channel->channel_name,
1827 strlen(channel->channel_name),
1828 3, chidp->data, chidp->len,
1831 6, keyp->data, keyp->len);
1834 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1835 SILC_STATUS_OK, ident, 6,
1836 2, channel->channel_name,
1837 strlen(channel->channel_name),
1838 3, chidp->data, chidp->len,
1841 6, keyp->data, keyp->len,
1843 strlen(channel->topic));
1846 /* Send command reply */
1847 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
1848 reply->data, reply->len, FALSE);
1850 if (!cmd->pending) {
1851 /* Send JOIN notify to locally connected clients on the channel */
1852 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
1853 SILC_NOTIFY_TYPE_JOIN, 1,
1854 clidp->data, clidp->len);
1856 /* Send NEW_CHANNEL_USER packet to our primary router */
1857 if (!server->standalone)
1858 silc_server_send_new_channel_user(server, server->router->connection,
1859 server->server_type == SILC_SERVER ?
1861 channel->id, SILC_ID_CHANNEL_LEN,
1862 client->id, SILC_ID_CLIENT_LEN);
1865 /* Send USERS command reply to the joined channel so the user sees who
1866 is currently on the channel. */
1867 silc_server_command_send_users(server, sock, channel, cmd->pending);
1869 silc_buffer_free(reply);
1870 silc_buffer_free(clidp);
1871 silc_buffer_free(chidp);
1872 silc_buffer_free(keyp);
1876 silc_free(passphrase);
1879 /* Server side of command JOIN. Joins client into requested channel. If
1880 the channel does not exist it will be created. */
1882 SILC_SERVER_CMD_FUNC(join)
1884 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1885 SilcServer server = cmd->server;
1887 char *tmp, *channel_name = NULL, *cipher = NULL;
1888 SilcChannelEntry channel;
1889 unsigned int umode = 0;
1890 int created = FALSE;
1891 SilcClientID *client_id;
1893 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
1895 /* Get channel name */
1896 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1898 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1899 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1904 if (silc_server_command_bad_chars(channel_name) == TRUE) {
1905 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1906 SILC_STATUS_ERR_BAD_CHANNEL);
1907 silc_free(channel_name);
1911 /* Get Client ID of the client who is joining to the channel */
1912 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1914 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1915 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1918 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1922 /* Get cipher name */
1923 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
1925 /* See if the channel exists */
1926 channel = silc_idlist_find_channel_by_name(server->local_list,
1927 channel_name, NULL);
1929 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1930 /* If this is coming from client the Client ID in the command packet must
1931 be same as the client's ID. */
1932 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1933 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
1934 if (SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
1935 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1936 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1942 /* Channel not found */
1944 /* If we are standalone server we don't have a router, we just create
1945 the channel by ourselves. */
1946 if (server->standalone) {
1947 channel = silc_server_create_new_channel(server, server->id, cipher,
1949 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
1954 /* The channel does not exist on our server. If we are normal server
1955 we will send JOIN command to our router which will handle the
1956 joining procedure (either creates the channel if it doesn't exist
1957 or joins the client to it). */
1958 if (server->server_type == SILC_SERVER) {
1960 unsigned short old_ident;
1962 old_ident = silc_command_get_ident(cmd->payload);
1963 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1964 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1966 /* Send JOIN command to our router */
1967 silc_server_packet_send(server, (SilcSocketConnection)
1968 server->router->connection,
1969 SILC_PACKET_COMMAND, cmd->packet->flags,
1970 tmpbuf->data, tmpbuf->len, TRUE);
1972 /* Reprocess this packet after received reply from router */
1973 silc_server_command_pending(server, SILC_COMMAND_JOIN,
1974 silc_command_get_ident(cmd->payload),
1975 silc_server_command_join, context);
1976 cmd->pending = TRUE;
1980 /* We are router and the channel does not seem exist so we will check
1981 our global list as well for the channel. */
1982 channel = silc_idlist_find_channel_by_name(server->global_list,
1983 channel_name, NULL);
1985 /* Channel really does not exist, create it */
1986 channel = silc_server_create_new_channel(server, server->id, cipher,
1988 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
1995 /* Channel not found */
1997 /* If the command came from router and/or we are normal server then
1998 something went wrong with the joining as the channel was not found.
1999 We can't do anything else but ignore this. */
2000 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
2001 server->server_type == SILC_SERVER)
2004 /* We are router and the channel does not seem exist so we will check
2005 our global list as well for the channel. */
2006 channel = silc_idlist_find_channel_by_name(server->global_list,
2007 channel_name, NULL);
2009 /* Channel really does not exist, create it */
2010 channel = silc_server_create_new_channel(server, server->id, cipher,
2012 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2018 /* If the channel does not have global users and is also empty it means the
2019 channel was created globally (by our router) and the client will be the
2020 channel founder and operator. */
2021 if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
2022 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2023 created = TRUE; /* Created globally by our router */
2026 /* Join to the channel */
2027 silc_server_command_join_channel(server, cmd, channel, client_id,
2030 silc_free(client_id);
2033 silc_server_command_free(cmd);
2036 /* Server side of command MOTD. Sends server's current "message of the
2037 day" to the client. */
2039 SILC_SERVER_CMD_FUNC(motd)
2041 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2042 SilcServer server = cmd->server;
2046 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 2);
2048 /* XXX show currently only our motd */
2050 if (server->config && server->config->motd &&
2051 server->config->motd->motd_file) {
2054 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
2059 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2065 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2070 silc_server_command_free(cmd);
2073 SILC_SERVER_CMD_FUNC(umode)
2077 /* Checks that client has rights to add or remove channel modes. If any
2078 of the checks fails FALSE is returned. */
2080 int silc_server_check_cmode_rights(SilcChannelEntry channel,
2081 SilcChannelClientEntry client,
2084 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
2085 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
2087 /* Check whether has rights to change anything */
2088 if (!is_op && !is_fo)
2091 /* Check whether has rights to change everything */
2095 /* We know that client is channel operator, check that they are not
2096 changing anything that requires channel founder rights. Rest of the
2097 modes are available automatically for channel operator. */
2099 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
2100 if (is_op && !is_fo)
2103 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2104 if (is_op && !is_fo)
2109 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2110 if (is_op && !is_fo)
2113 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2114 if (is_op && !is_fo)
2119 if (mode & SILC_CHANNEL_MODE_CIPHER) {
2120 if (is_op && !is_fo)
2123 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2124 if (is_op && !is_fo)
2132 /* Server side command of CMODE. Changes channel mode */
2134 SILC_SERVER_CMD_FUNC(cmode)
2136 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2137 SilcServer server = cmd->server;
2138 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2139 SilcChannelID *channel_id;
2140 SilcChannelEntry channel;
2141 SilcChannelClientEntry chl;
2142 SilcBuffer packet, cidp;
2143 unsigned char *tmp, *tmp_id, *tmp_mask;
2144 unsigned int argc, mode_mask, tmp_len, tmp_len2;
2146 SILC_LOG_DEBUG(("Start"));
2148 argc = silc_argument_get_arg_num(cmd->args);
2150 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2151 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2155 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2156 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2160 /* Get Channel ID */
2161 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2163 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2164 SILC_STATUS_ERR_NO_CHANNEL_ID);
2167 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
2169 /* Get the channel mode mask */
2170 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2172 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2173 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2176 SILC_GET32_MSB(mode_mask, tmp_mask);
2178 /* Get channel entry */
2179 channel = silc_idlist_find_channel_by_id(server->local_list,
2182 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2183 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2187 /* Check whether this client is on the channel */
2188 if (!silc_server_client_on_channel(client, channel)) {
2189 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2190 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2194 /* Get entry to the channel user list */
2195 silc_list_start(channel->user_list);
2196 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2197 if (chl->client == client)
2200 /* Check that client has rights to change any requested channel modes */
2201 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
2202 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2203 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2208 * Check the modes. Modes that requires nothing special operation are
2212 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2213 /* Channel uses private keys to protect traffic. Client(s) has set the
2214 key locally they want to use, server does not know that key. */
2215 /* Nothing interesting to do here now */
2217 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2218 /* The mode is removed and we need to generate and distribute
2219 new channel key. Clients are not using private channel keys
2220 anymore after this. */
2222 /* XXX Duplicated code, make own function for this!! LEAVE uses this
2225 /* Re-generate channel key */
2226 silc_server_create_channel_key(server, channel, 0);
2228 /* Encode channel key payload to be distributed on the channel */
2230 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2231 strlen(channel->channel_key->
2233 channel->channel_key->cipher->name,
2234 channel->key_len / 8, channel->key);
2236 /* If we are normal server then we will send it to our router. If we
2237 are router we will send it to all local servers that has clients on
2239 if (server->server_type == SILC_SERVER) {
2240 if (!server->standalone)
2241 silc_server_packet_send(server,
2242 cmd->server->router->connection,
2243 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2249 /* Send to locally connected clients on the channel */
2250 silc_server_packet_send_local_channel(server, channel,
2251 SILC_PACKET_CHANNEL_KEY, 0,
2252 packet->data, packet->len, FALSE);
2253 silc_buffer_free(packet);
2257 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2258 /* User limit is set on channel */
2259 unsigned int user_limit;
2261 /* Get user limit */
2262 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2264 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2265 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2266 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2270 SILC_GET32_MSB(user_limit, tmp);
2271 channel->mode_data.user_limit = user_limit;
2274 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2275 /* User limit mode is unset. Remove user limit */
2276 channel->mode_data.user_limit = 0;
2279 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
2280 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
2281 /* Passphrase has been set to channel */
2283 /* Get the passphrase */
2284 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
2286 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2287 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2291 /* Save the passphrase */
2292 channel->mode_data.passphrase = strdup(tmp);
2295 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2296 /* Passphrase mode is unset. remove the passphrase */
2297 if (channel->mode_data.passphrase) {
2298 silc_free(channel->mode_data.passphrase);
2299 channel->mode_data.passphrase = NULL;
2304 if (mode_mask & SILC_CHANNEL_MODE_BAN) {
2305 if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
2306 /* Ban list is specified for channel */
2309 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
2311 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2312 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2316 /* XXX check that channel founder is not banned */
2318 /* Save the ban list */
2319 channel->mode_data.ban_list = strdup(tmp);
2322 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2323 /* Ban mode is unset. Remove the entire ban list */
2324 if (channel->mode_data.ban_list) {
2325 silc_free(channel->mode_data.ban_list);
2326 channel->mode_data.ban_list = NULL;
2331 if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
2332 if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
2333 /* Invite list is specified for channel */
2335 /* Get invite list */
2336 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
2338 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2339 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2343 /* Save the invite linst */
2344 channel->mode_data.invite_list = strdup(tmp);
2347 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
2348 /* Invite list mode is unset. Remove the entire invite list */
2349 if (channel->mode_data.invite_list) {
2350 silc_free(channel->mode_data.invite_list);
2351 channel->mode_data.invite_list = NULL;
2356 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
2357 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
2358 /* Cipher to use protect the traffic */
2359 unsigned int key_len = 128;
2363 tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
2365 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2366 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2370 cp = strchr(tmp, ':');
2376 /* XXX Duplicated code, make own function for this!! */
2378 /* Delete old cipher and allocate the new one */
2379 silc_cipher_free(channel->channel_key);
2380 silc_cipher_alloc(tmp, &channel->channel_key);
2386 /* Re-generate channel key */
2387 silc_server_create_channel_key(server, channel, key_len);
2389 /* Encode channel key payload to be distributed on the channel */
2391 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2392 strlen(channel->channel_key->
2394 channel->channel_key->cipher->name,
2395 channel->key_len / 8, channel->key);
2397 /* If we are normal server then we will send it to our router. If we
2398 are router we will send it to all local servers that has clients on
2400 if (server->server_type == SILC_SERVER) {
2401 if (!server->standalone)
2402 silc_server_packet_send(server,
2403 cmd->server->router->connection,
2404 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2410 /* Send to locally connected clients on the channel */
2411 silc_server_packet_send_local_channel(server, channel,
2412 SILC_PACKET_CHANNEL_KEY, 0,
2413 packet->data, packet->len, FALSE);
2414 silc_buffer_free(packet);
2417 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2418 /* Cipher mode is unset. Remove the cipher and revert back to
2421 if (channel->mode_data.cipher) {
2422 silc_free(channel->mode_data.cipher);
2423 channel->mode_data.cipher = NULL;
2424 channel->mode_data.key_len = 0;
2427 /* Generate new cipher and key for the channel */
2429 /* XXX Duplicated code, make own function for this!! */
2431 /* Delete old cipher and allocate default one */
2432 silc_cipher_free(channel->channel_key);
2433 if (!channel->cipher)
2434 silc_cipher_alloc("twofish", &channel->channel_key);
2436 silc_cipher_alloc(channel->cipher, &channel->channel_key);
2438 /* Re-generate channel key */
2439 silc_server_create_channel_key(server, channel, 0);
2441 /* Encode channel key payload to be distributed on the channel */
2443 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2444 strlen(channel->channel_key->
2446 channel->channel_key->cipher->name,
2447 channel->key_len / 8, channel->key);
2449 /* If we are normal server then we will send it to our router. If we
2450 are router we will send it to all local servers that has clients on
2452 if (server->server_type == SILC_SERVER) {
2453 if (!server->standalone)
2454 silc_server_packet_send(server,
2455 cmd->server->router->connection,
2456 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2462 /* Send to locally connected clients on the channel */
2463 silc_server_packet_send_local_channel(server, channel,
2464 SILC_PACKET_CHANNEL_KEY, 0,
2465 packet->data, packet->len, FALSE);
2466 silc_buffer_free(packet);
2470 /* Finally, set the mode */
2471 channel->mode = mode_mask;
2473 /* Send CMODE_CHANGE notify */
2474 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2475 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2476 SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
2477 cidp->data, cidp->len,
2481 /* Send command reply to sender */
2482 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2483 SILC_STATUS_OK, 0, 1,
2485 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2486 packet->data, packet->len, FALSE);
2488 silc_buffer_free(packet);
2489 silc_free(channel_id);
2492 silc_server_command_free(cmd);
2495 /* Server side of CUMODE command. Changes client's mode on a channel. */
2497 SILC_SERVER_CMD_FUNC(cumode)
2499 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2500 SilcServer server = cmd->server;
2501 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2502 SilcChannelID *channel_id;
2503 SilcClientID *client_id;
2504 SilcChannelEntry channel;
2505 SilcClientEntry target_client;
2506 SilcChannelClientEntry chl;
2507 SilcBuffer packet, idp;
2508 unsigned char *tmp_id, *tmp_mask;
2509 unsigned int target_mask, sender_mask, tmp_len;
2512 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 3);
2514 /* Get Channel ID */
2515 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2517 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2518 SILC_STATUS_ERR_NO_CHANNEL_ID);
2521 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2523 /* Get channel entry */
2524 channel = silc_idlist_find_channel_by_id(server->local_list,
2527 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2528 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2532 /* Check whether sender is on the channel */
2533 if (!silc_server_client_on_channel(client, channel)) {
2534 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2535 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2539 /* Check that client has rights to change other's rights */
2540 silc_list_start(channel->user_list);
2541 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2542 if (chl->client == client) {
2543 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
2544 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2545 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2546 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2550 sender_mask = chl->mode;
2555 /* Get the target client's channel mode mask */
2556 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2558 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2559 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2562 SILC_GET32_MSB(target_mask, tmp_mask);
2564 /* Get target Client ID */
2565 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2567 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2568 SILC_STATUS_ERR_NO_CHANNEL_ID);
2571 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2573 /* Get target client's entry */
2574 target_client = silc_idlist_find_client_by_id(server->local_list,
2576 if (!target_client) {
2577 /* XXX If target client is not one of mine send to primary route */
2580 /* Check whether target client is on the channel */
2581 if (!silc_server_client_on_channel(target_client, channel)) {
2582 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2583 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2587 /* Get entry to the channel user list */
2588 silc_list_start(channel->user_list);
2589 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2590 if (chl->client == target_client)
2597 /* If the target client is founder, no one else can change their mode
2599 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
2600 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2601 SILC_STATUS_ERR_NOT_YOU);
2605 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
2606 /* Cannot promote anyone to channel founder */
2607 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2608 SILC_STATUS_ERR_NOT_YOU);
2611 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2612 if (target_client == client) {
2613 /* Remove channel founder rights from itself */
2614 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
2617 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2618 SILC_STATUS_ERR_NOT_YOU);
2624 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
2625 /* Promote to operator */
2626 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2627 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
2631 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
2632 /* Demote to normal user */
2633 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
2638 /* Send notify to channel, notify only if mode was actually changed. */
2640 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2641 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2642 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
2643 idp->data, idp->len,
2644 tmp_mask, 4, tmp_id, tmp_len);
2645 silc_buffer_free(idp);
2648 /* Send command reply to sender */
2649 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
2650 SILC_STATUS_OK, 0, 2,
2652 3, tmp_id, tmp_len);
2653 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2654 packet->data, packet->len, FALSE);
2656 silc_buffer_free(packet);
2657 silc_free(channel_id);
2658 silc_free(client_id);
2661 silc_server_command_free(cmd);
2664 /* Server side of KICK command. Kicks client out of channel. */
2666 SILC_SERVER_CMD_FUNC(kick)
2670 SILC_SERVER_CMD_FUNC(restart)
2674 SILC_SERVER_CMD_FUNC(close)
2678 SILC_SERVER_CMD_FUNC(die)
2682 SILC_SERVER_CMD_FUNC(silcoper)
2686 /* Server side command of LEAVE. Removes client from a channel. */
2688 SILC_SERVER_CMD_FUNC(leave)
2690 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2691 SilcServer server = cmd->server;
2692 SilcSocketConnection sock = cmd->sock;
2693 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
2695 SilcChannelEntry channel;
2697 unsigned int i, len;
2700 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
2702 /* Get Channel ID */
2703 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2705 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2706 SILC_STATUS_ERR_NO_CHANNEL_ID);
2709 id = silc_id_payload_parse_id(tmp, len);
2711 /* Get channel entry */
2712 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
2714 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2715 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2719 /* Check whether this client is on the channel */
2720 if (!silc_server_client_on_channel(id_entry, channel)) {
2721 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2722 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2726 /* Notify routers that they should remove this client from their list
2727 of clients on the channel. */
2728 if (!server->standalone)
2729 silc_server_send_remove_channel_user(server,
2730 server->router->connection,
2731 server->server_type == SILC_ROUTER ?
2732 TRUE : FALSE, id_entry->id, id);
2734 /* Remove client from channel */
2735 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
2737 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2740 /* If the channel does not exist anymore we won't send anything */
2744 /* Re-generate channel key */
2745 silc_server_create_channel_key(server, channel, 0);
2747 /* Encode channel key payload to be distributed on the channel */
2749 silc_channel_key_payload_encode(len, tmp,
2750 strlen(channel->channel_key->cipher->name),
2751 channel->channel_key->cipher->name,
2752 channel->key_len / 8, channel->key);
2754 /* If we are normal server then we will send it to our router. If we
2755 are router we will send it to all local servers that has clients on
2757 if (server->server_type == SILC_SERVER) {
2758 if (!server->standalone)
2759 silc_server_packet_send(server,
2760 cmd->server->router->connection,
2761 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2767 /* Send to locally connected clients on the channel */
2768 silc_server_packet_send_local_channel(server, channel,
2769 SILC_PACKET_CHANNEL_KEY, 0,
2770 packet->data, packet->len, FALSE);
2772 silc_buffer_free(packet);
2776 silc_server_command_free(cmd);
2779 /* Server side of command USERS. Resolves clients and their USERS currently
2780 joined on the requested channel. The list of Client ID's and their modes
2781 on the channel is sent back. */
2783 SILC_SERVER_CMD_FUNC(users)
2785 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2786 SilcServer server = cmd->server;
2787 SilcChannelEntry channel;
2788 SilcChannelClientEntry chl;
2791 unsigned char *channel_id;
2792 unsigned int channel_id_len;
2793 SilcBuffer client_id_list;
2794 SilcBuffer client_mode_list;
2796 unsigned char lc[4];
2797 unsigned int list_count = 0;
2798 unsigned short ident = silc_command_get_ident(cmd->payload);
2800 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
2802 /* Get Channel ID */
2803 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
2805 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
2806 SILC_STATUS_ERR_NO_CHANNEL_ID);
2809 id = silc_id_payload_parse_id(channel_id, channel_id_len);
2811 /* If we are server and we don't know about this channel we will send
2812 the command to our router. If we know about the channel then we also
2813 have the list of users already. */
2814 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
2816 if (server->server_type == SILC_SERVER && !server->standalone &&
2820 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2821 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2823 /* Send USERS command */
2824 silc_server_packet_send(server, server->router->connection,
2825 SILC_PACKET_COMMAND, cmd->packet->flags,
2826 tmpbuf->data, tmpbuf->len, TRUE);
2828 /* Reprocess this packet after received reply */
2829 silc_server_command_pending(server, SILC_COMMAND_USERS,
2830 silc_command_get_ident(cmd->payload),
2831 silc_server_command_users, (void *)cmd);
2832 cmd->pending = TRUE;
2833 silc_command_set_ident(cmd->payload, ident);
2835 silc_buffer_free(tmpbuf);
2840 /* We are router and we will check the global list as well. */
2841 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
2843 /* Channel really does not exist */
2844 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
2845 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2850 /* Assemble the lists now */
2852 client_id_list = silc_buffer_alloc((SILC_ID_CLIENT_LEN + 4) *
2853 silc_list_count(channel->user_list));
2854 silc_buffer_pull_tail(client_id_list, SILC_BUFFER_END(client_id_list));
2856 silc_buffer_alloc(4 * silc_list_count(channel->user_list));
2857 silc_buffer_pull_tail(client_mode_list, SILC_BUFFER_END(client_mode_list));
2859 silc_list_start(channel->user_list);
2860 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2862 idp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
2863 silc_buffer_put(client_id_list, idp->data, idp->len);
2864 silc_buffer_pull(client_id_list, idp->len);
2865 silc_buffer_free(idp);
2867 /* Client's mode on channel */
2868 SILC_PUT32_MSB(chl->mode, client_mode_list->data);
2869 silc_buffer_pull(client_mode_list, 4);
2873 silc_buffer_push(client_id_list,
2874 client_id_list->data - client_id_list->head);
2875 silc_buffer_push(client_mode_list,
2876 client_mode_list->data - client_mode_list->head);
2879 SILC_PUT32_MSB(list_count, lc);
2882 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
2883 SILC_STATUS_OK, 0, 4,
2884 2, channel_id, channel_id_len,
2886 4, client_id_list->data,
2887 client_id_list->len,
2888 5, client_mode_list->data,
2889 client_mode_list->len);
2890 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2891 packet->data, packet->len, FALSE);
2893 silc_buffer_free(packet);
2894 silc_buffer_free(client_id_list);
2895 silc_buffer_free(client_mode_list);
2899 silc_server_command_free(cmd);