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 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 if ((*client_id)[0] == NULL) {
355 silc_free(*client_id);
358 *client_id_count = 1;
360 /* Take all ID's from the command packet */
362 for (k = 1, i = 4; i < argc; i++) {
363 tmp = silc_argument_get_arg_type(cmd->args, i, &len);
365 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
366 (*client_id_count + 1));
367 (*client_id)[k] = silc_id_payload_parse_id(tmp, len);
368 if ((*client_id)[k] == NULL) {
369 for (i = 0; i < k; i++)
370 silc_free((*client_id)[i]);
371 silc_free(*client_id);
374 (*client_id_count)++;
380 /* Command includes ID, use that */
383 /* Get the max count of reply messages allowed */
384 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
394 silc_server_command_whois_check(SilcServerCommandContext cmd,
395 SilcClientEntry *clients,
396 unsigned int clients_count)
398 SilcServer server = cmd->server;
400 SilcClientEntry entry;
402 for (i = 0; i < clients_count; i++) {
405 if (!entry->nickname || !entry->username || !entry->userinfo) {
407 unsigned short old_ident;
412 old_ident = silc_command_get_ident(cmd->payload);
413 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
414 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
416 /* Send WHOIS command */
417 silc_server_packet_send(server, entry->router->connection,
418 SILC_PACKET_COMMAND, cmd->packet->flags,
419 tmpbuf->data, tmpbuf->len, TRUE);
421 /* Reprocess this packet after received reply */
422 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
423 silc_command_get_ident(cmd->payload),
424 silc_server_command_whois, (void *)cmd);
427 silc_command_set_ident(cmd->payload, old_ident);
429 silc_buffer_free(tmpbuf);
438 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
439 SilcClientEntry *clients,
440 unsigned int clients_count)
442 SilcServer server = cmd->server;
444 int i, count = 0, len;
445 SilcBuffer packet, idp;
446 SilcClientEntry entry;
447 SilcCommandStatus status;
448 unsigned short ident = silc_command_get_ident(cmd->payload);
450 status = SILC_STATUS_OK;
451 if (clients_count > 1)
452 status = SILC_STATUS_LIST_START;
454 for (i = 0; i < clients_count; i++) {
457 if (count && i - 1 == count)
460 if (clients_count > 2)
461 status = SILC_STATUS_LIST_ITEM;
463 if (clients_count > 1 && i == clients_count - 1)
464 status = SILC_STATUS_LIST_END;
466 /* Send WHOIS reply */
467 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
468 tmp = silc_argument_get_first_arg(cmd->args, NULL);
472 char nh[256], uh[256];
473 unsigned char idle[4];
474 SilcSocketConnection hsock;
476 memset(uh, 0, sizeof(uh));
477 memset(nh, 0, sizeof(nh));
479 strncat(nh, entry->nickname, strlen(entry->nickname));
480 if (!strchr(entry->nickname, '@')) {
482 len = entry->router ? strlen(entry->router->server_name) :
483 strlen(server->server_name);
484 strncat(nh, entry->router ? entry->router->server_name :
485 server->server_name, len);
488 strncat(uh, entry->username, strlen(entry->username));
489 if (!strchr(entry->username, '@')) {
491 hsock = (SilcSocketConnection)entry->connection;
492 len = strlen(hsock->hostname);
493 strncat(uh, hsock->hostname, len);
496 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
501 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
503 2, idp->data, idp->len,
507 strlen(entry->userinfo),
511 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
513 2, idp->data, idp->len,
519 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
520 0, packet->data, packet->len, FALSE);
522 silc_buffer_free(packet);
523 silc_buffer_free(idp);
528 silc_server_command_whois_from_client(SilcServerCommandContext cmd)
530 SilcServer server = cmd->server;
531 char *nick = NULL, *server_name = NULL;
532 int count = 0, clients_count = 0;
533 SilcClientEntry *clients = NULL, entry;
534 SilcClientID **client_id = NULL;
535 unsigned int client_id_count = 0;
538 /* Protocol dictates that we must always send the received WHOIS request
539 to our router if we are normal server, so let's do it now unless we
540 are standalone. We will not send any replies to the client until we
541 have received reply from the router. */
542 if (server->server_type == SILC_SERVER &&
543 !cmd->pending && !server->standalone) {
545 unsigned short old_ident;
547 old_ident = silc_command_get_ident(cmd->payload);
548 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
549 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
551 /* Send WHOIS command to our router */
552 silc_server_packet_send(server, (SilcSocketConnection)
553 server->router->connection,
554 SILC_PACKET_COMMAND, cmd->packet->flags,
555 tmpbuf->data, tmpbuf->len, TRUE);
557 /* Reprocess this packet after received reply from router */
558 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
559 silc_command_get_ident(cmd->payload),
560 silc_server_command_whois, (void *)cmd);
563 silc_command_set_ident(cmd->payload, old_ident);
565 silc_buffer_free(tmpbuf);
570 /* We are ready to process the command request. Let's search for the
571 requested client and send reply to the requesting client. */
573 /* Parse the whois request */
574 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
575 &nick, &server_name, &count,
579 /* Get all clients matching that ID or nickname from local list */
580 if (client_id_count) {
581 /* Check all Client ID's received in the command packet */
582 for (i = 0; i < client_id_count; i++) {
583 entry = silc_idlist_find_client_by_id(server->local_list,
586 clients = silc_realloc(clients, sizeof(*clients) *
587 (clients_count + 1));
588 clients[clients_count++] = entry;
592 clients = silc_idlist_get_clients_by_nickname(server->local_list,
597 /* Check global list as well */
599 if (client_id_count) {
600 /* Check all Client ID's received in the command packet */
601 for (i = 0; i < client_id_count; i++) {
602 entry = silc_idlist_find_client_by_id(server->global_list,
605 clients = silc_realloc(clients, sizeof(*clients) *
606 (clients_count + 1));
607 clients[clients_count++] = entry;
611 clients = silc_idlist_get_clients_by_nickname(server->global_list,
618 /* Such client(s) really does not exist in the SILC network. */
619 if (!client_id_count) {
620 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
621 SILC_STATUS_ERR_NO_SUCH_NICK,
622 3, nick, strlen(nick));
624 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
625 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
626 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
627 2, idp->data, idp->len);
628 silc_buffer_free(idp);
633 /* Router always finds the client entry if it exists in the SILC network.
634 However, it might be incomplete entry and does not include all the
635 mandatory fields that WHOIS command reply requires. Check for these and
636 make query from the server who owns the client if some fields are
638 if (server->server_type == SILC_ROUTER &&
639 !silc_server_command_whois_check(cmd, clients, clients_count)) {
644 /* Send the command reply to the client */
645 silc_server_command_whois_send_reply(cmd, clients, clients_count);
648 if (client_id_count) {
649 for (i = 0; i < client_id_count; i++)
650 silc_free(client_id[i]);
651 silc_free(client_id);
658 silc_free(server_name);
664 silc_server_command_whois_from_server(SilcServerCommandContext cmd)
666 SilcServer server = cmd->server;
667 char *nick = NULL, *server_name = NULL;
668 int count = 0, clients_count = 0;
669 SilcClientEntry *clients = NULL, entry;
670 SilcClientID **client_id = NULL;
671 unsigned int client_id_count = 0;
674 /* Parse the whois request */
675 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
676 &nick, &server_name, &count,
680 /* Process the command request. Let's search for the requested client and
681 send reply to the requesting server. */
683 if (client_id_count) {
684 /* Check all Client ID's received in the command packet */
685 for (i = 0; i < client_id_count; i++) {
686 entry = silc_idlist_find_client_by_id(server->local_list,
689 clients = silc_realloc(clients, sizeof(*clients) *
690 (clients_count + 1));
691 clients[clients_count++] = entry;
695 clients = silc_idlist_get_clients_by_nickname(server->local_list,
699 clients = silc_idlist_get_clients_by_hash(server->local_list,
700 nick, server->md5hash,
704 /* If we are router we will check our global list as well. */
705 if (!clients && server->server_type == SILC_ROUTER) {
706 if (client_id_count) {
707 /* Check all Client ID's received in the command packet */
708 for (i = 0; i < client_id_count; i++) {
709 entry = silc_idlist_find_client_by_id(server->global_list,
712 clients = silc_realloc(clients, sizeof(*clients) *
713 (clients_count + 1));
714 clients[clients_count++] = entry;
718 clients = silc_idlist_get_clients_by_nickname(server->global_list,
722 clients = silc_idlist_get_clients_by_hash(server->global_list,
723 nick, server->md5hash,
729 /* Such a client really does not exist in the SILC network. */
730 if (!client_id_count) {
731 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
732 SILC_STATUS_ERR_NO_SUCH_NICK,
733 3, nick, strlen(nick));
735 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
736 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
737 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
738 2, idp->data, idp->len);
739 silc_buffer_free(idp);
744 /* Router always finds the client entry if it exists in the SILC network.
745 However, it might be incomplete entry and does not include all the
746 mandatory fields that WHOIS command reply requires. Check for these and
747 make query from the server who owns the client if some fields are
749 if (server->server_type == SILC_ROUTER &&
750 !silc_server_command_whois_check(cmd, clients, clients_count)) {
755 /* Send the command reply to the client */
756 silc_server_command_whois_send_reply(cmd, clients, clients_count);
759 if (client_id_count) {
760 for (i = 0; i < client_id_count; i++)
761 silc_free(client_id[i]);
762 silc_free(client_id);
769 silc_free(server_name);
774 /* Server side of command WHOIS. Processes user's query and sends found
775 results as command replies back to the client. */
777 SILC_SERVER_CMD_FUNC(whois)
779 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
782 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOIS, cmd, 1, 3328);
784 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
785 ret = silc_server_command_whois_from_client(cmd);
787 ret = silc_server_command_whois_from_server(cmd);
790 silc_server_command_free(cmd);
793 SILC_SERVER_CMD_FUNC(whowas)
797 /******************************************************************************
801 ******************************************************************************/
803 /* Checks that all mandatory fields are present. If not then send WHOIS
804 request to the server who owns the client. We use WHOIS because we want
805 to get as much information as possible at once. */
808 silc_server_command_identify_check(SilcServerCommandContext cmd,
809 SilcClientEntry *clients,
810 unsigned int clients_count)
812 SilcServer server = cmd->server;
814 SilcClientEntry entry;
816 for (i = 0; i < clients_count; i++) {
819 if (!entry->nickname) {
821 unsigned short old_ident;
826 old_ident = silc_command_get_ident(cmd->payload);
827 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
828 silc_command_set_command(cmd->payload, SILC_COMMAND_WHOIS);
829 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
831 /* Send WHOIS request. We send WHOIS since we're doing the requesting
832 now anyway so make it a good one. */
833 silc_server_packet_send(server, entry->router->connection,
834 SILC_PACKET_COMMAND, cmd->packet->flags,
835 tmpbuf->data, tmpbuf->len, TRUE);
837 /* Reprocess this packet after received reply */
838 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
839 silc_command_get_ident(cmd->payload),
840 silc_server_command_identify, (void *)cmd);
843 /* Put old data back to the Command Payload we just changed */
844 silc_command_set_ident(cmd->payload, old_ident);
845 silc_command_set_command(cmd->payload, SILC_COMMAND_IDENTIFY);
847 silc_buffer_free(tmpbuf);
856 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
857 SilcClientEntry *clients,
858 unsigned int clients_count)
860 SilcServer server = cmd->server;
862 int i, count = 0, len;
863 SilcBuffer packet, idp;
864 SilcClientEntry entry;
865 SilcCommandStatus status;
866 unsigned short ident = silc_command_get_ident(cmd->payload);
868 status = SILC_STATUS_OK;
869 if (clients_count > 1)
870 status = SILC_STATUS_LIST_START;
872 for (i = 0; i < clients_count; i++) {
875 if (count && i - 1 == count)
878 if (clients_count > 2)
879 status = SILC_STATUS_LIST_ITEM;
881 if (clients_count > 1 && i == clients_count - 1)
882 status = SILC_STATUS_LIST_END;
884 /* Send IDENTIFY reply */
885 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
886 tmp = silc_argument_get_first_arg(cmd->args, NULL);
890 char nh[256], uh[256];
891 SilcSocketConnection hsock;
893 memset(uh, 0, sizeof(uh));
894 memset(nh, 0, sizeof(nh));
896 strncat(nh, entry->nickname, strlen(entry->nickname));
897 if (!strchr(entry->nickname, '@')) {
899 len = entry->router ? strlen(entry->router->server_name) :
900 strlen(server->server_name);
901 strncat(nh, entry->router ? entry->router->server_name :
902 server->server_name, len);
905 if (!entry->username) {
906 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
907 SILC_STATUS_OK, ident, 2,
908 2, idp->data, idp->len,
911 strncat(uh, entry->username, strlen(entry->username));
912 if (!strchr(entry->username, '@')) {
914 hsock = (SilcSocketConnection)entry->connection;
915 len = strlen(hsock->hostname);
916 strncat(uh, hsock->hostname, len);
919 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
920 SILC_STATUS_OK, ident, 3,
921 2, idp->data, idp->len,
926 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
927 0, packet->data, packet->len, FALSE);
929 silc_buffer_free(packet);
930 silc_buffer_free(idp);
936 silc_server_command_identify_from_client(SilcServerCommandContext cmd)
938 SilcServer server = cmd->server;
939 char *nick = NULL, *server_name = NULL;
940 int count = 0, clients_count = 0;
941 SilcClientEntry *clients = NULL, entry;
942 SilcClientID **client_id = NULL;
943 unsigned int client_id_count = 0;
946 /* Protocol dictates that we must always send the received IDENTIFY request
947 to our router if we are normal server, so let's do it now unless we
948 are standalone. We will not send any replies to the client until we
949 have received reply from the router. */
950 if (server->server_type == SILC_SERVER &&
951 !cmd->pending && !server->standalone) {
953 unsigned short old_ident;
955 old_ident = silc_command_get_ident(cmd->payload);
956 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
957 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
959 /* Send IDENTIFY command to our router */
960 silc_server_packet_send(server, (SilcSocketConnection)
961 server->router->connection,
962 SILC_PACKET_COMMAND, cmd->packet->flags,
963 tmpbuf->data, tmpbuf->len, TRUE);
965 /* Reprocess this packet after received reply from router */
966 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
967 silc_command_get_ident(cmd->payload),
968 silc_server_command_identify, (void *)cmd);
971 silc_command_set_ident(cmd->payload, old_ident);
973 silc_buffer_free(tmpbuf);
978 /* We are ready to process the command request. Let's search for the
979 requested client and send reply to the requesting client. */
981 /* Parse the IDENTIFY request */
982 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
983 &nick, &server_name, &count,
984 SILC_COMMAND_IDENTIFY))
987 /* Get all clients matching that ID or nickname from local list */
988 if (client_id_count) {
989 /* Check all Client ID's received in the command packet */
990 for (i = 0; i < client_id_count; i++) {
991 entry = silc_idlist_find_client_by_id(server->local_list,
994 clients = silc_realloc(clients, sizeof(*clients) *
995 (clients_count + 1));
996 clients[clients_count++] = entry;
1000 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1005 /* Check global list as well */
1007 if (client_id_count) {
1008 /* Check all Client ID's received in the command packet */
1009 for (i = 0; i < client_id_count; i++) {
1010 entry = silc_idlist_find_client_by_id(server->global_list,
1011 client_id[i], NULL);
1013 clients = silc_realloc(clients, sizeof(*clients) *
1014 (clients_count + 1));
1015 clients[clients_count++] = entry;
1019 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1026 /* Such a client really does not exist in the SILC network. */
1027 if (!client_id_count) {
1028 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1029 SILC_STATUS_ERR_NO_SUCH_NICK,
1030 3, nick, strlen(nick));
1032 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1033 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1034 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1035 2, idp->data, idp->len);
1036 silc_buffer_free(idp);
1041 /* Check that all mandatory fields are present and request those data
1042 from the server who owns the client if necessary. */
1043 if (!cmd->pending && server->server_type == SILC_ROUTER &&
1044 !silc_server_command_identify_check(cmd, clients, clients_count)) {
1049 /* Send the command reply to the client */
1050 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1053 if (client_id_count) {
1054 for (i = 0; i < client_id_count; i++)
1055 silc_free(client_id[i]);
1056 silc_free(client_id);
1063 silc_free(server_name);
1069 silc_server_command_identify_from_server(SilcServerCommandContext cmd)
1071 SilcServer server = cmd->server;
1072 char *nick = NULL, *server_name = NULL;
1073 int count = 0, clients_count = 0;
1074 SilcClientEntry *clients = NULL, entry;
1075 SilcClientID **client_id = NULL;
1076 unsigned int client_id_count = 0;
1079 /* Parse the IDENTIFY request */
1080 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1081 &nick, &server_name, &count,
1082 SILC_COMMAND_IDENTIFY))
1085 /* Process the command request. Let's search for the requested client and
1086 send reply to the requesting server. */
1088 if (client_id_count) {
1089 /* Check all Client ID's received in the command packet */
1090 for (i = 0; i < client_id_count; i++) {
1091 entry = silc_idlist_find_client_by_id(server->local_list,
1092 client_id[i], NULL);
1094 clients = silc_realloc(clients, sizeof(*clients) *
1095 (clients_count + 1));
1096 clients[clients_count++] = entry;
1100 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1104 clients = silc_idlist_get_clients_by_hash(server->local_list,
1105 nick, server->md5hash,
1109 /* If we are router we will check our global list as well. */
1110 if (!clients && server->server_type == SILC_ROUTER) {
1111 if (client_id_count) {
1112 /* Check all Client ID's received in the command packet */
1113 for (i = 0; i < client_id_count; i++) {
1114 entry = silc_idlist_find_client_by_id(server->global_list,
1115 client_id[i], NULL);
1117 clients = silc_realloc(clients, sizeof(*clients) *
1118 (clients_count + 1));
1119 clients[clients_count++] = entry;
1123 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1127 clients = silc_idlist_get_clients_by_hash(server->global_list,
1128 nick, server->md5hash,
1134 /* Such a client really does not exist in the SILC network. */
1135 if (!client_id_count) {
1136 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1137 SILC_STATUS_ERR_NO_SUCH_NICK,
1138 3, nick, strlen(nick));
1140 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1141 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1142 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1143 2, idp->data, idp->len);
1144 silc_buffer_free(idp);
1149 /* Check that all mandatory fields are present and request those data
1150 from the server who owns the client if necessary. */
1151 if (!cmd->pending && server->server_type == SILC_ROUTER &&
1152 !silc_server_command_identify_check(cmd, clients, clients_count)) {
1157 /* Send the command reply */
1158 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1161 if (client_id_count) {
1162 for (i = 0; i < client_id_count; i++)
1163 silc_free(client_id[i]);
1164 silc_free(client_id);
1171 silc_free(server_name);
1176 SILC_SERVER_CMD_FUNC(identify)
1178 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1181 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1183 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1184 ret = silc_server_command_identify_from_client(cmd);
1186 ret = silc_server_command_identify_from_server(cmd);
1189 silc_server_command_free(cmd);
1192 /* Checks string for bad characters and returns TRUE if they are found. */
1194 static int silc_server_command_bad_chars(char *nick)
1196 if (strchr(nick, '\\')) return TRUE;
1197 if (strchr(nick, '\"')) return TRUE;
1198 if (strchr(nick, '´')) return TRUE;
1199 if (strchr(nick, '`')) return TRUE;
1200 if (strchr(nick, '\'')) return TRUE;
1201 if (strchr(nick, '*')) return TRUE;
1202 if (strchr(nick, '/')) return TRUE;
1203 if (strchr(nick, '@')) return TRUE;
1208 /* Server side of command NICK. Sets nickname for user. Setting
1209 nickname causes generation of a new client ID for the client. The
1210 new client ID is sent to the client after changing the nickname. */
1212 SILC_SERVER_CMD_FUNC(nick)
1214 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1215 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1216 SilcServer server = cmd->server;
1217 SilcBuffer packet, nidp, oidp;
1218 SilcClientID *new_id;
1221 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NICK, cmd, 1, 1);
1223 /* Check nickname */
1224 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1225 if (silc_server_command_bad_chars(nick) == TRUE) {
1226 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1227 SILC_STATUS_ERR_BAD_NICKNAME);
1231 /* Create new Client ID */
1232 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
1233 cmd->server->md5hash, nick,
1236 /* Send notify about nickname change to our router. We send the new
1237 ID and ask to replace it with the old one. If we are router the
1238 packet is broadcasted. */
1239 if (!server->standalone)
1240 silc_server_send_replace_id(server, server->router->connection,
1241 server->server_type == SILC_SERVER ?
1242 FALSE : TRUE, client->id,
1243 SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
1244 new_id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
1246 /* Remove old cache entry */
1247 silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
1250 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1254 memset(client->id, 0, SILC_ID_CLIENT_LEN);
1255 silc_free(client->id);
1258 /* Save the nickname as this client is our local client */
1259 if (client->nickname)
1260 silc_free(client->nickname);
1262 client->nickname = strdup(nick);
1263 client->id = new_id;
1265 /* Update client cache */
1266 silc_idcache_add(server->local_list->clients, client->nickname,
1267 SILC_ID_CLIENT, client->id, (void *)client, TRUE);
1269 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1271 /* Send NICK_CHANGE notify */
1272 silc_server_send_notify_on_channels(server, client,
1273 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1274 oidp->data, oidp->len,
1275 nidp->data, nidp->len);
1277 /* Send the new Client ID as reply command back to client */
1278 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
1279 SILC_STATUS_OK, 0, 1,
1280 2, nidp->data, nidp->len);
1281 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1282 0, packet->data, packet->len, FALSE);
1284 silc_buffer_free(packet);
1285 silc_buffer_free(nidp);
1286 silc_buffer_free(oidp);
1289 silc_server_command_free(cmd);
1292 SILC_SERVER_CMD_FUNC(list)
1296 /* Server side of TOPIC command. Sets topic for channel and/or returns
1297 current topic to client. */
1299 SILC_SERVER_CMD_FUNC(topic)
1301 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1302 SilcServer server = cmd->server;
1303 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1304 SilcChannelID *channel_id;
1305 SilcChannelEntry channel;
1306 SilcChannelClientEntry chl;
1307 SilcBuffer packet, idp;
1309 unsigned int argc, tmp_len;
1311 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
1313 argc = silc_argument_get_arg_num(cmd->args);
1315 /* Get Channel ID */
1316 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1318 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1319 SILC_STATUS_ERR_NO_CHANNEL_ID);
1322 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1324 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1325 SILC_STATUS_ERR_NO_CHANNEL_ID);
1329 /* Check whether the channel exists */
1330 channel = silc_idlist_find_channel_by_id(server->local_list,
1333 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1334 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1340 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1342 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1343 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1347 if (strlen(tmp) > 256) {
1348 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1349 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1353 /* See whether has rights to change topic */
1354 silc_list_start(channel->user_list);
1355 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
1356 if (chl->client == client) {
1357 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1358 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1359 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1367 /* Set the topic for channel */
1369 silc_free(channel->topic);
1370 channel->topic = strdup(tmp);
1372 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1374 /* Send notify about topic change to all clients on the channel */
1375 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
1376 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
1377 idp->data, idp->len,
1378 channel->topic, strlen(channel->topic));
1379 silc_buffer_free(idp);
1382 /* Send the topic to client as reply packet */
1383 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1385 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1386 SILC_STATUS_OK, 0, 2,
1387 2, idp->data, idp->len,
1389 strlen(channel->topic));
1391 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1392 SILC_STATUS_OK, 0, 1,
1393 2, idp->data, idp->len);
1394 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1395 0, packet->data, packet->len, FALSE);
1397 silc_buffer_free(packet);
1398 silc_buffer_free(idp);
1399 silc_free(channel_id);
1402 silc_server_command_free(cmd);
1405 /* Server side of INVITE command. Invites some client to join some channel. */
1407 SILC_SERVER_CMD_FUNC(invite)
1409 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1410 SilcServer server = cmd->server;
1411 SilcSocketConnection sock = cmd->sock, dest_sock;
1412 SilcClientEntry sender, dest;
1413 SilcClientID *dest_id;
1414 SilcChannelEntry channel;
1415 SilcChannelID *channel_id;
1420 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 2);
1422 /* Get destination ID */
1423 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1425 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1426 SILC_STATUS_ERR_NO_CLIENT_ID);
1429 dest_id = silc_id_payload_parse_id(tmp, len);
1431 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1432 SILC_STATUS_ERR_NO_CLIENT_ID);
1436 /* Get Channel ID */
1437 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1439 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1440 SILC_STATUS_ERR_NO_CHANNEL_ID);
1443 channel_id = silc_id_payload_parse_id(tmp, len);
1445 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1446 SILC_STATUS_ERR_NO_CHANNEL_ID);
1450 /* Check whether the channel exists */
1451 channel = silc_idlist_find_channel_by_id(server->local_list,
1454 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1455 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1459 /* Check whether the sender of this command is on the channel. */
1460 sender = (SilcClientEntry)sock->user_data;
1461 if (!silc_server_client_on_channel(sender, channel)) {
1462 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1463 SILC_STATUS_ERR_NOT_ON_CHANNEL);
1467 /* Check whether the channel is invite-only channel. If yes then the
1468 sender of this command must be at least channel operator. */
1469 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1470 SilcChannelClientEntry chl;
1472 silc_list_start(channel->user_list);
1473 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1474 if (chl->client == sender) {
1475 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1476 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1477 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1484 /* Find the connection data for the destination. If it is local we will
1485 send it directly otherwise we will send it to router for routing. */
1486 dest = silc_idlist_find_client_by_id(server->local_list, dest_id, NULL);
1488 dest_sock = (SilcSocketConnection)dest->connection;
1490 dest_sock = silc_server_route_get(server, dest_id, SILC_ID_CLIENT);
1492 /* Check whether the requested client is already on the channel. */
1493 /* XXX if we are normal server we don't know about global clients on
1494 the channel thus we must request it (USERS command), check from
1495 local cache as well. */
1496 if (silc_server_client_on_channel(dest, channel)) {
1497 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1498 SILC_STATUS_ERR_USER_ON_CHANNEL);
1502 sidp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1504 /* Send notify to the client that is invited to the channel */
1505 silc_server_send_notify_dest(server, dest_sock, dest_id, SILC_ID_CLIENT,
1506 SILC_NOTIFY_TYPE_INVITE, 2,
1507 sidp->data, sidp->len, tmp, len);
1509 /* Send command reply */
1510 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1513 silc_buffer_free(sidp);
1516 silc_server_command_free(cmd);
1519 /* Quits connection to client. This gets called if client won't
1520 close the connection even when it has issued QUIT command. */
1522 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
1524 SilcServer server = (SilcServer)context;
1525 SilcSocketConnection sock = server->sockets[fd];
1527 /* Free all client specific data, such as client entry and entires
1528 on channels this client may be on. */
1529 silc_server_free_sock_user_data(server, sock);
1531 /* Close the connection on our side */
1532 silc_server_close_connection(server, sock);
1535 /* Quits SILC session. This is the normal way to disconnect client. */
1537 SILC_SERVER_CMD_FUNC(quit)
1539 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1540 SilcServer server = cmd->server;
1541 SilcSocketConnection sock = cmd->sock;
1543 SILC_LOG_DEBUG(("Start"));
1545 /* We quit the connection with little timeout */
1546 silc_task_register(server->timeout_queue, sock->sock,
1547 silc_server_command_quit_cb, server,
1548 0, 300000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1550 silc_server_command_free(cmd);
1553 SILC_SERVER_CMD_FUNC(kill)
1557 /* Server side of command INFO. This sends information about us to
1558 the client. If client requested specific server we will send the
1559 command to that server. */
1561 SILC_SERVER_CMD_FUNC(info)
1563 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1564 SilcServer server = cmd->server;
1565 SilcBuffer packet, idp;
1566 char info_string[256], *dest_server;
1568 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 1);
1570 /* Get server name */
1571 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1573 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1574 SILC_STATUS_ERR_NO_SUCH_SERVER);
1578 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
1579 /* Send our reply */
1580 memset(info_string, 0, sizeof(info_string));
1581 snprintf(info_string, sizeof(info_string),
1582 "location: %s server: %s admin: %s <%s>",
1583 server->config->admin_info->location,
1584 server->config->admin_info->server_type,
1585 server->config->admin_info->admin_name,
1586 server->config->admin_info->admin_email);
1588 idp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1590 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
1591 SILC_STATUS_OK, 0, 2,
1592 2, idp->data, idp->len,
1594 strlen(info_string));
1595 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1596 packet->data, packet->len, FALSE);
1598 silc_buffer_free(packet);
1599 silc_buffer_free(idp);
1601 /* Send this command to the requested server */
1603 if (server->server_type == SILC_SERVER && !server->standalone) {
1607 if (server->server_type == SILC_ROUTER) {
1613 silc_server_command_free(cmd);
1616 SILC_SERVER_CMD_FUNC(connect)
1620 /* Server side of command PING. This just replies to the ping. */
1622 SILC_SERVER_CMD_FUNC(ping)
1624 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1625 SilcServer server = cmd->server;
1630 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
1633 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1635 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1636 SILC_STATUS_ERR_NO_SERVER_ID);
1639 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
1643 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
1644 /* Send our reply */
1645 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1648 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1649 SILC_STATUS_ERR_NO_SUCH_SERVER);
1656 silc_server_command_free(cmd);
1659 SILC_SERVER_CMD_FUNC(oper)
1663 /* Assembles USERS command and executes it. This is called when client
1664 joins to a channel and we wan't to send USERS command reply to the
1667 void silc_server_command_send_users(SilcServer server,
1668 SilcSocketConnection sock,
1669 SilcChannelEntry channel,
1672 SilcServerCommandContext cmd;
1673 SilcBuffer buffer, idp;
1674 SilcPacketContext *packet = silc_packet_context_alloc();
1676 SILC_LOG_DEBUG(("Start"));
1678 /* Create USERS command packet and process it. */
1679 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1680 buffer = silc_command_payload_encode_va(SILC_COMMAND_USERS, 0, 1,
1681 1, idp->data, idp->len);
1683 packet->buffer = silc_buffer_copy(buffer);
1684 packet->sock = sock;
1685 packet->type = SILC_PACKET_COMMAND;
1687 cmd = silc_calloc(1, sizeof(*cmd));
1688 cmd->payload = silc_command_payload_parse(buffer);
1689 if (!cmd->payload) {
1691 silc_buffer_free(buffer);
1692 silc_buffer_free(idp);
1693 silc_packet_context_free(packet);
1696 cmd->args = silc_command_get_args(cmd->payload);
1697 cmd->server = server;
1699 cmd->packet = silc_packet_context_dup(packet);
1700 cmd->pending = FALSE;
1703 /* If this function was called from pending command then instead of
1704 processing the command now, register a pending command callback which
1705 will process it after we've received the automatic USERS command
1707 silc_server_command_pending(server, SILC_COMMAND_USERS, 0,
1708 silc_server_command_users, (void *)cmd);
1709 cmd->pending = TRUE;
1710 silc_buffer_free(buffer);
1711 silc_buffer_free(idp);
1715 /* Process USERS command. */
1716 silc_server_command_users((void *)cmd);
1718 silc_buffer_free(buffer);
1719 silc_buffer_free(idp);
1720 silc_packet_context_free(packet);
1723 /* Internal routine to join channel. The channel sent to this function
1724 has been either created or resolved from ID lists. This joins the sent
1725 client to the channel. */
1727 static void silc_server_command_join_channel(SilcServer server,
1728 SilcServerCommandContext cmd,
1729 SilcChannelEntry channel,
1730 SilcClientID *client_id,
1734 SilcSocketConnection sock = cmd->sock;
1736 unsigned int tmp_len;
1737 unsigned char *passphrase = NULL, mode[4], tmp2[4];
1738 SilcClientEntry client;
1739 SilcChannelClientEntry chl;
1740 SilcBuffer reply, chidp, clidp, keyp;
1741 unsigned short ident = silc_command_get_ident(cmd->payload);
1743 SILC_LOG_DEBUG(("Start"));
1748 /* Get passphrase */
1749 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1751 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
1752 memcpy(passphrase, tmp, tmp_len);
1756 * Check channel modes
1759 /* Check invite list if channel is invite-only channel */
1760 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1761 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1762 /* Invite list is specified. Check whether client is invited in the
1763 list. If not, then check whether it has been invited otherwise. */
1766 /* XXX client must be invited to be able to join the channel */
1770 /* Check ban list if set */
1771 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1775 /* Check the channel passphrase if set. */
1776 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1777 if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
1778 strlen(channel->mode_data.passphrase))) {
1779 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1780 SILC_STATUS_ERR_BAD_PASSWORD);
1785 /* Check user count limit if set. */
1786 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
1787 if (silc_list_count(channel->user_list) + 1 >
1788 channel->mode_data.user_limit) {
1789 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1790 SILC_STATUS_ERR_CHANNEL_IS_FULL);
1796 * Client is allowed to join to the channel. Make it happen.
1799 /* Get the client entry */
1800 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1801 client = (SilcClientEntry)sock->user_data;
1803 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1806 /* XXX actually this is useless since router finds always cell's
1807 local clients from its local lists. */
1808 client = silc_idlist_find_client_by_id(server->global_list, client_id,
1815 /* Check whether the client already is on the channel */
1816 if (silc_server_client_on_channel(client, channel)) {
1817 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1818 SILC_STATUS_ERR_USER_ON_CHANNEL);
1822 /* Generate new channel key as protocol dictates */
1823 if (!created || !channel->channel_key)
1824 silc_server_create_channel_key(server, channel, 0);
1826 /* Send the channel key. This is broadcasted to the channel but is not
1827 sent to the client who is joining to the channel. */
1828 silc_server_send_channel_key(server, NULL, channel,
1829 server->server_type == SILC_ROUTER ?
1830 FALSE : server->standalone);
1832 /* Join the client to the channel by adding it to channel's user list.
1833 Add also the channel to client entry's channels list for fast cross-
1835 chl = silc_calloc(1, sizeof(*chl));
1837 chl->client = client;
1838 chl->channel = channel;
1839 silc_list_add(channel->user_list, chl);
1840 silc_list_add(client->channels, chl);
1842 /* Encode Client ID Payload of the original client who wants to join */
1843 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1845 /* Encode command reply packet */
1846 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1847 SILC_PUT32_MSB(channel->mode, mode);
1848 SILC_PUT32_MSB(created, tmp2);
1849 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1850 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
1851 SILC_ID_CHANNEL_LEN,
1852 channel->channel_key->cipher->name,
1853 channel->key_len / 8, channel->key);
1855 if (!channel->topic) {
1857 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1858 SILC_STATUS_OK, ident, 5,
1859 2, channel->channel_name,
1860 strlen(channel->channel_name),
1861 3, chidp->data, chidp->len,
1864 6, keyp->data, keyp->len);
1867 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1868 SILC_STATUS_OK, ident, 6,
1869 2, channel->channel_name,
1870 strlen(channel->channel_name),
1871 3, chidp->data, chidp->len,
1874 6, keyp->data, keyp->len,
1876 strlen(channel->topic));
1879 /* Send command reply */
1880 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
1881 reply->data, reply->len, FALSE);
1883 if (!cmd->pending) {
1884 /* Send JOIN notify to locally connected clients on the channel */
1885 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
1886 SILC_NOTIFY_TYPE_JOIN, 1,
1887 clidp->data, clidp->len);
1889 /* Send NEW_CHANNEL_USER packet to our primary router */
1890 if (!server->standalone)
1891 silc_server_send_new_channel_user(server, server->router->connection,
1892 server->server_type == SILC_SERVER ?
1894 channel->id, SILC_ID_CHANNEL_LEN,
1895 client->id, SILC_ID_CLIENT_LEN);
1898 /* Send USERS command reply to the joined channel so the user sees who
1899 is currently on the channel. */
1900 silc_server_command_send_users(server, sock, channel, cmd->pending);
1902 silc_buffer_free(reply);
1903 silc_buffer_free(clidp);
1904 silc_buffer_free(chidp);
1905 silc_buffer_free(keyp);
1909 silc_free(passphrase);
1912 /* Server side of command JOIN. Joins client into requested channel. If
1913 the channel does not exist it will be created. */
1915 SILC_SERVER_CMD_FUNC(join)
1917 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1918 SilcServer server = cmd->server;
1920 char *tmp, *channel_name = NULL, *cipher = NULL;
1921 SilcChannelEntry channel;
1922 unsigned int umode = 0;
1923 int created = FALSE;
1924 SilcClientID *client_id;
1926 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
1928 /* Get channel name */
1929 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1931 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1932 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1937 if (silc_server_command_bad_chars(channel_name) == TRUE) {
1938 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1939 SILC_STATUS_ERR_BAD_CHANNEL);
1940 silc_free(channel_name);
1944 /* Get Client ID of the client who is joining to the channel */
1945 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1947 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1948 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1951 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1953 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1954 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1958 /* Get cipher name */
1959 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
1961 /* See if the channel exists */
1962 channel = silc_idlist_find_channel_by_name(server->local_list,
1963 channel_name, NULL);
1965 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1966 /* If this is coming from client the Client ID in the command packet must
1967 be same as the client's ID. */
1968 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1969 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
1970 if (SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
1971 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1972 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1978 /* Channel not found */
1980 /* If we are standalone server we don't have a router, we just create
1981 the channel by ourselves. */
1982 if (server->standalone) {
1983 channel = silc_server_create_new_channel(server, server->id, cipher,
1985 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
1990 /* The channel does not exist on our server. If we are normal server
1991 we will send JOIN command to our router which will handle the
1992 joining procedure (either creates the channel if it doesn't exist
1993 or joins the client to it). */
1994 if (server->server_type == SILC_SERVER) {
1996 unsigned short old_ident;
1998 old_ident = silc_command_get_ident(cmd->payload);
1999 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2000 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2002 /* Send JOIN command to our router */
2003 silc_server_packet_send(server, (SilcSocketConnection)
2004 server->router->connection,
2005 SILC_PACKET_COMMAND, cmd->packet->flags,
2006 tmpbuf->data, tmpbuf->len, TRUE);
2008 /* Reprocess this packet after received reply from router */
2009 silc_server_command_pending(server, SILC_COMMAND_JOIN,
2010 silc_command_get_ident(cmd->payload),
2011 silc_server_command_join, context);
2012 cmd->pending = TRUE;
2016 /* We are router and the channel does not seem exist so we will check
2017 our global list as well for the channel. */
2018 channel = silc_idlist_find_channel_by_name(server->global_list,
2019 channel_name, NULL);
2021 /* Channel really does not exist, create it */
2022 channel = silc_server_create_new_channel(server, server->id, cipher,
2024 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2031 /* Channel not found */
2033 /* If the command came from router and/or we are normal server then
2034 something went wrong with the joining as the channel was not found.
2035 We can't do anything else but ignore this. */
2036 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
2037 server->server_type == SILC_SERVER)
2040 /* We are router and the channel does not seem exist so we will check
2041 our global list as well for the channel. */
2042 channel = silc_idlist_find_channel_by_name(server->global_list,
2043 channel_name, NULL);
2045 /* Channel really does not exist, create it */
2046 channel = silc_server_create_new_channel(server, server->id, cipher,
2048 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2054 /* If the channel does not have global users and is also empty it means the
2055 channel was created globally (by our router) and the client will be the
2056 channel founder and operator. */
2057 if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
2058 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2059 created = TRUE; /* Created globally by our router */
2062 /* Join to the channel */
2063 silc_server_command_join_channel(server, cmd, channel, client_id,
2066 silc_free(client_id);
2069 silc_server_command_free(cmd);
2072 /* Server side of command MOTD. Sends server's current "message of the
2073 day" to the client. */
2075 SILC_SERVER_CMD_FUNC(motd)
2077 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2078 SilcServer server = cmd->server;
2082 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 2);
2084 /* XXX show currently only our motd */
2086 if (server->config && server->config->motd &&
2087 server->config->motd->motd_file) {
2090 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
2095 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2101 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2106 silc_server_command_free(cmd);
2109 SILC_SERVER_CMD_FUNC(umode)
2113 /* Checks that client has rights to add or remove channel modes. If any
2114 of the checks fails FALSE is returned. */
2116 int silc_server_check_cmode_rights(SilcChannelEntry channel,
2117 SilcChannelClientEntry client,
2120 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
2121 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
2123 /* Check whether has rights to change anything */
2124 if (!is_op && !is_fo)
2127 /* Check whether has rights to change everything */
2131 /* We know that client is channel operator, check that they are not
2132 changing anything that requires channel founder rights. Rest of the
2133 modes are available automatically for channel operator. */
2135 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
2136 if (is_op && !is_fo)
2139 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2140 if (is_op && !is_fo)
2145 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2146 if (is_op && !is_fo)
2149 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2150 if (is_op && !is_fo)
2155 if (mode & SILC_CHANNEL_MODE_CIPHER) {
2156 if (is_op && !is_fo)
2159 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2160 if (is_op && !is_fo)
2168 /* Server side command of CMODE. Changes channel mode */
2170 SILC_SERVER_CMD_FUNC(cmode)
2172 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2173 SilcServer server = cmd->server;
2174 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2175 SilcChannelID *channel_id;
2176 SilcChannelEntry channel;
2177 SilcChannelClientEntry chl;
2178 SilcBuffer packet, cidp;
2179 unsigned char *tmp, *tmp_id, *tmp_mask;
2180 unsigned int argc, mode_mask, tmp_len, tmp_len2;
2182 SILC_LOG_DEBUG(("Start"));
2184 argc = silc_argument_get_arg_num(cmd->args);
2186 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2187 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2191 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2192 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2196 /* Get Channel ID */
2197 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2199 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2200 SILC_STATUS_ERR_NO_CHANNEL_ID);
2203 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
2205 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2206 SILC_STATUS_ERR_NO_CHANNEL_ID);
2210 /* Get the channel mode mask */
2211 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2213 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2214 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2217 SILC_GET32_MSB(mode_mask, tmp_mask);
2219 /* Get channel entry */
2220 channel = silc_idlist_find_channel_by_id(server->local_list,
2223 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2224 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2228 /* Check whether this client is on the channel */
2229 if (!silc_server_client_on_channel(client, channel)) {
2230 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2231 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2235 /* Get entry to the channel user list */
2236 silc_list_start(channel->user_list);
2237 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2238 if (chl->client == client)
2241 /* Check that client has rights to change any requested channel modes */
2242 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
2243 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2244 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2249 * Check the modes. Modes that requires nothing special operation are
2253 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2254 /* Channel uses private keys to protect traffic. Client(s) has set the
2255 key locally they want to use, server does not know that key. */
2256 /* Nothing interesting to do here now */
2258 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2259 /* The mode is removed and we need to generate and distribute
2260 new channel key. Clients are not using private channel keys
2261 anymore after this. */
2263 /* XXX Duplicated code, make own function for this!! LEAVE uses this
2266 /* Re-generate channel key */
2267 silc_server_create_channel_key(server, channel, 0);
2269 /* Encode channel key payload to be distributed on the channel */
2271 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2272 strlen(channel->channel_key->
2274 channel->channel_key->cipher->name,
2275 channel->key_len / 8, channel->key);
2277 /* If we are normal server then we will send it to our router. If we
2278 are router we will send it to all local servers that has clients on
2280 if (server->server_type == SILC_SERVER) {
2281 if (!server->standalone)
2282 silc_server_packet_send(server,
2283 cmd->server->router->connection,
2284 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2290 /* Send to locally connected clients on the channel */
2291 silc_server_packet_send_local_channel(server, channel,
2292 SILC_PACKET_CHANNEL_KEY, 0,
2293 packet->data, packet->len, FALSE);
2294 silc_buffer_free(packet);
2298 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2299 /* User limit is set on channel */
2300 unsigned int user_limit;
2302 /* Get user limit */
2303 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2305 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2306 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2307 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2311 SILC_GET32_MSB(user_limit, tmp);
2312 channel->mode_data.user_limit = user_limit;
2315 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2316 /* User limit mode is unset. Remove user limit */
2317 channel->mode_data.user_limit = 0;
2320 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
2321 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
2322 /* Passphrase has been set to channel */
2324 /* Get the passphrase */
2325 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
2327 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2328 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2332 /* Save the passphrase */
2333 channel->mode_data.passphrase = strdup(tmp);
2336 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2337 /* Passphrase mode is unset. remove the passphrase */
2338 if (channel->mode_data.passphrase) {
2339 silc_free(channel->mode_data.passphrase);
2340 channel->mode_data.passphrase = NULL;
2345 if (mode_mask & SILC_CHANNEL_MODE_BAN) {
2346 if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
2347 /* Ban list is specified for channel */
2350 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
2352 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2353 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2357 /* XXX check that channel founder is not banned */
2359 /* Save the ban list */
2360 channel->mode_data.ban_list = strdup(tmp);
2363 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2364 /* Ban mode is unset. Remove the entire ban list */
2365 if (channel->mode_data.ban_list) {
2366 silc_free(channel->mode_data.ban_list);
2367 channel->mode_data.ban_list = NULL;
2372 if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
2373 if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
2374 /* Invite list is specified for channel */
2376 /* Get invite list */
2377 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
2379 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2380 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2384 /* Save the invite linst */
2385 channel->mode_data.invite_list = strdup(tmp);
2388 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
2389 /* Invite list mode is unset. Remove the entire invite list */
2390 if (channel->mode_data.invite_list) {
2391 silc_free(channel->mode_data.invite_list);
2392 channel->mode_data.invite_list = NULL;
2397 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
2398 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
2399 /* Cipher to use protect the traffic */
2400 unsigned int key_len = 128;
2404 tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
2406 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2407 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2411 cp = strchr(tmp, ':');
2417 /* XXX Duplicated code, make own function for this!! */
2419 /* Delete old cipher and allocate the new one */
2420 silc_cipher_free(channel->channel_key);
2421 silc_cipher_alloc(tmp, &channel->channel_key);
2427 /* Re-generate channel key */
2428 silc_server_create_channel_key(server, channel, key_len);
2430 /* Encode channel key payload to be distributed on the channel */
2432 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2433 strlen(channel->channel_key->
2435 channel->channel_key->cipher->name,
2436 channel->key_len / 8, channel->key);
2438 /* If we are normal server then we will send it to our router. If we
2439 are router we will send it to all local servers that has clients on
2441 if (server->server_type == SILC_SERVER) {
2442 if (!server->standalone)
2443 silc_server_packet_send(server,
2444 cmd->server->router->connection,
2445 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2451 /* Send to locally connected clients on the channel */
2452 silc_server_packet_send_local_channel(server, channel,
2453 SILC_PACKET_CHANNEL_KEY, 0,
2454 packet->data, packet->len, FALSE);
2455 silc_buffer_free(packet);
2458 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2459 /* Cipher mode is unset. Remove the cipher and revert back to
2462 if (channel->mode_data.cipher) {
2463 silc_free(channel->mode_data.cipher);
2464 channel->mode_data.cipher = NULL;
2465 channel->mode_data.key_len = 0;
2468 /* Generate new cipher and key for the channel */
2470 /* XXX Duplicated code, make own function for this!! */
2472 /* Delete old cipher and allocate default one */
2473 silc_cipher_free(channel->channel_key);
2474 if (!channel->cipher)
2475 silc_cipher_alloc("twofish", &channel->channel_key);
2477 silc_cipher_alloc(channel->cipher, &channel->channel_key);
2479 /* Re-generate channel key */
2480 silc_server_create_channel_key(server, channel, 0);
2482 /* Encode channel key payload to be distributed on the channel */
2484 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2485 strlen(channel->channel_key->
2487 channel->channel_key->cipher->name,
2488 channel->key_len / 8, channel->key);
2490 /* If we are normal server then we will send it to our router. If we
2491 are router we will send it to all local servers that has clients on
2493 if (server->server_type == SILC_SERVER) {
2494 if (!server->standalone)
2495 silc_server_packet_send(server,
2496 cmd->server->router->connection,
2497 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2503 /* Send to locally connected clients on the channel */
2504 silc_server_packet_send_local_channel(server, channel,
2505 SILC_PACKET_CHANNEL_KEY, 0,
2506 packet->data, packet->len, FALSE);
2507 silc_buffer_free(packet);
2511 /* Finally, set the mode */
2512 channel->mode = mode_mask;
2514 /* Send CMODE_CHANGE notify */
2515 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2516 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2517 SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
2518 cidp->data, cidp->len,
2522 /* Send command reply to sender */
2523 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2524 SILC_STATUS_OK, 0, 1,
2526 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2527 packet->data, packet->len, FALSE);
2529 silc_buffer_free(packet);
2530 silc_free(channel_id);
2533 silc_server_command_free(cmd);
2536 /* Server side of CUMODE command. Changes client's mode on a channel. */
2538 SILC_SERVER_CMD_FUNC(cumode)
2540 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2541 SilcServer server = cmd->server;
2542 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2543 SilcChannelID *channel_id;
2544 SilcClientID *client_id;
2545 SilcChannelEntry channel;
2546 SilcClientEntry target_client;
2547 SilcChannelClientEntry chl;
2548 SilcBuffer packet, idp;
2549 unsigned char *tmp_id, *tmp_mask;
2550 unsigned int target_mask, sender_mask, tmp_len;
2553 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 3);
2555 /* Get Channel ID */
2556 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2558 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2559 SILC_STATUS_ERR_NO_CHANNEL_ID);
2562 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2564 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2565 SILC_STATUS_ERR_NO_CHANNEL_ID);
2569 /* Get channel entry */
2570 channel = silc_idlist_find_channel_by_id(server->local_list,
2573 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2574 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2578 /* Check whether sender is on the channel */
2579 if (!silc_server_client_on_channel(client, channel)) {
2580 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2581 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2585 /* Check that client has rights to change other's rights */
2586 silc_list_start(channel->user_list);
2587 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2588 if (chl->client == client) {
2589 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
2590 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2591 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2592 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2596 sender_mask = chl->mode;
2601 /* Get the target client's channel mode mask */
2602 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2604 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2605 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2608 SILC_GET32_MSB(target_mask, tmp_mask);
2610 /* Get target Client ID */
2611 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2613 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2614 SILC_STATUS_ERR_NO_CHANNEL_ID);
2617 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2619 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2620 SILC_STATUS_ERR_NO_CHANNEL_ID);
2624 /* Get target client's entry */
2625 target_client = silc_idlist_find_client_by_id(server->local_list,
2627 if (!target_client) {
2628 /* XXX If target client is not one of mine send to primary route */
2631 /* Check whether target client is on the channel */
2632 if (!silc_server_client_on_channel(target_client, channel)) {
2633 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2634 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2638 /* Get entry to the channel user list */
2639 silc_list_start(channel->user_list);
2640 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2641 if (chl->client == target_client)
2648 /* If the target client is founder, no one else can change their mode
2650 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
2651 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2652 SILC_STATUS_ERR_NOT_YOU);
2656 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
2657 /* Cannot promote anyone to channel founder */
2658 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2659 SILC_STATUS_ERR_NOT_YOU);
2662 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2663 if (target_client == client) {
2664 /* Remove channel founder rights from itself */
2665 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
2668 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2669 SILC_STATUS_ERR_NOT_YOU);
2675 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
2676 /* Promote to operator */
2677 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2678 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
2682 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
2683 /* Demote to normal user */
2684 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
2689 /* Send notify to channel, notify only if mode was actually changed. */
2691 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2692 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2693 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
2694 idp->data, idp->len,
2695 tmp_mask, 4, tmp_id, tmp_len);
2696 silc_buffer_free(idp);
2699 /* Send command reply to sender */
2700 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
2701 SILC_STATUS_OK, 0, 2,
2703 3, tmp_id, tmp_len);
2704 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2705 packet->data, packet->len, FALSE);
2707 silc_buffer_free(packet);
2708 silc_free(channel_id);
2709 silc_free(client_id);
2712 silc_server_command_free(cmd);
2715 /* Server side of KICK command. Kicks client out of channel. */
2717 SILC_SERVER_CMD_FUNC(kick)
2721 SILC_SERVER_CMD_FUNC(restart)
2725 SILC_SERVER_CMD_FUNC(close)
2729 SILC_SERVER_CMD_FUNC(die)
2733 SILC_SERVER_CMD_FUNC(silcoper)
2737 /* Server side command of LEAVE. Removes client from a channel. */
2739 SILC_SERVER_CMD_FUNC(leave)
2741 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2742 SilcServer server = cmd->server;
2743 SilcSocketConnection sock = cmd->sock;
2744 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
2746 SilcChannelEntry channel;
2748 unsigned int i, len;
2751 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
2753 /* Get Channel ID */
2754 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2756 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2757 SILC_STATUS_ERR_NO_CHANNEL_ID);
2760 id = silc_id_payload_parse_id(tmp, len);
2762 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2763 SILC_STATUS_ERR_NO_CHANNEL_ID);
2767 /* Get channel entry */
2768 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
2770 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2771 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2775 /* Check whether this client is on the channel */
2776 if (!silc_server_client_on_channel(id_entry, channel)) {
2777 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2778 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2782 /* Notify routers that they should remove this client from their list
2783 of clients on the channel. */
2784 if (!server->standalone)
2785 silc_server_send_remove_channel_user(server,
2786 server->router->connection,
2787 server->server_type == SILC_ROUTER ?
2788 TRUE : FALSE, id_entry->id, id);
2790 /* Remove client from channel */
2791 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
2793 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2796 /* If the channel does not exist anymore we won't send anything */
2800 /* Re-generate channel key */
2801 silc_server_create_channel_key(server, channel, 0);
2803 /* Encode channel key payload to be distributed on the channel */
2805 silc_channel_key_payload_encode(len, tmp,
2806 strlen(channel->channel_key->cipher->name),
2807 channel->channel_key->cipher->name,
2808 channel->key_len / 8, channel->key);
2810 /* If we are normal server then we will send it to our router. If we
2811 are router we will send it to all local servers that has clients on
2813 if (server->server_type == SILC_SERVER) {
2814 if (!server->standalone)
2815 silc_server_packet_send(server,
2816 cmd->server->router->connection,
2817 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2823 /* Send to locally connected clients on the channel */
2824 silc_server_packet_send_local_channel(server, channel,
2825 SILC_PACKET_CHANNEL_KEY, 0,
2826 packet->data, packet->len, FALSE);
2828 silc_buffer_free(packet);
2832 silc_server_command_free(cmd);
2835 /* Server side of command USERS. Resolves clients and their USERS currently
2836 joined on the requested channel. The list of Client ID's and their modes
2837 on the channel is sent back. */
2839 SILC_SERVER_CMD_FUNC(users)
2841 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2842 SilcServer server = cmd->server;
2843 SilcChannelEntry channel;
2844 SilcChannelClientEntry chl;
2847 unsigned char *channel_id;
2848 unsigned int channel_id_len;
2849 SilcBuffer client_id_list;
2850 SilcBuffer client_mode_list;
2852 unsigned char lc[4];
2853 unsigned int list_count = 0;
2854 unsigned short ident = silc_command_get_ident(cmd->payload);
2856 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
2858 /* Get Channel ID */
2859 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
2861 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
2862 SILC_STATUS_ERR_NO_CHANNEL_ID);
2865 id = silc_id_payload_parse_id(channel_id, channel_id_len);
2867 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
2868 SILC_STATUS_ERR_NO_CHANNEL_ID);
2872 /* If we are server and we don't know about this channel we will send
2873 the command to our router. If we know about the channel then we also
2874 have the list of users already. */
2875 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
2877 if (server->server_type == SILC_SERVER && !server->standalone &&
2881 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2882 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2884 /* Send USERS command */
2885 silc_server_packet_send(server, server->router->connection,
2886 SILC_PACKET_COMMAND, cmd->packet->flags,
2887 tmpbuf->data, tmpbuf->len, TRUE);
2889 /* Reprocess this packet after received reply */
2890 silc_server_command_pending(server, SILC_COMMAND_USERS,
2891 silc_command_get_ident(cmd->payload),
2892 silc_server_command_users, (void *)cmd);
2893 cmd->pending = TRUE;
2894 silc_command_set_ident(cmd->payload, ident);
2896 silc_buffer_free(tmpbuf);
2901 /* We are router and we will check the global list as well. */
2902 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
2904 /* Channel really does not exist */
2905 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
2906 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2911 /* Assemble the lists now */
2913 client_id_list = silc_buffer_alloc((SILC_ID_CLIENT_LEN + 4) *
2914 silc_list_count(channel->user_list));
2915 silc_buffer_pull_tail(client_id_list, SILC_BUFFER_END(client_id_list));
2917 silc_buffer_alloc(4 * silc_list_count(channel->user_list));
2918 silc_buffer_pull_tail(client_mode_list, SILC_BUFFER_END(client_mode_list));
2920 silc_list_start(channel->user_list);
2921 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2923 idp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
2924 silc_buffer_put(client_id_list, idp->data, idp->len);
2925 silc_buffer_pull(client_id_list, idp->len);
2926 silc_buffer_free(idp);
2928 /* Client's mode on channel */
2929 SILC_PUT32_MSB(chl->mode, client_mode_list->data);
2930 silc_buffer_pull(client_mode_list, 4);
2934 silc_buffer_push(client_id_list,
2935 client_id_list->data - client_id_list->head);
2936 silc_buffer_push(client_mode_list,
2937 client_mode_list->data - client_mode_list->head);
2940 SILC_PUT32_MSB(list_count, lc);
2943 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
2944 SILC_STATUS_OK, 0, 4,
2945 2, channel_id, channel_id_len,
2947 4, client_id_list->data,
2948 client_id_list->len,
2949 5, client_mode_list->data,
2950 client_mode_list->len);
2951 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2952 packet->data, packet->len, FALSE);
2954 silc_buffer_free(packet);
2955 silc_buffer_free(client_id_list);
2956 silc_buffer_free(client_mode_list);
2960 silc_server_command_free(cmd);