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 + 1; 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 /* Cleanup all and fail */
370 for (i = 0; i < *client_id_count; i++)
371 silc_free((*client_id)[i]);
372 silc_free(*client_id);
375 (*client_id_count)++;
381 /* Command includes ID, use that */
384 /* Get the max count of reply messages allowed */
385 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
395 silc_server_command_whois_check(SilcServerCommandContext cmd,
396 SilcClientEntry *clients,
397 unsigned int clients_count)
399 SilcServer server = cmd->server;
401 SilcClientEntry entry;
403 for (i = 0; i < clients_count; i++) {
406 if (!entry->nickname || !entry->username) {
408 unsigned short old_ident;
413 old_ident = silc_command_get_ident(cmd->payload);
414 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
415 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
417 /* Send WHOIS command */
418 silc_server_packet_send(server, entry->router->connection,
419 SILC_PACKET_COMMAND, cmd->packet->flags,
420 tmpbuf->data, tmpbuf->len, TRUE);
422 /* Reprocess this packet after received reply */
423 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
424 silc_command_get_ident(cmd->payload),
425 silc_server_command_whois, (void *)cmd);
428 silc_command_set_ident(cmd->payload, old_ident);
430 silc_buffer_free(tmpbuf);
439 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
440 SilcClientEntry *clients,
441 unsigned int clients_count)
443 SilcServer server = cmd->server;
445 int i, count = 0, len;
446 SilcBuffer packet, idp;
447 SilcClientEntry entry;
448 SilcCommandStatus status;
449 unsigned short ident = silc_command_get_ident(cmd->payload);
451 status = SILC_STATUS_OK;
452 if (clients_count > 1)
453 status = SILC_STATUS_LIST_START;
455 for (i = 0; i < clients_count; i++) {
458 if (count && i - 1 == count)
461 if (clients_count > 2)
462 status = SILC_STATUS_LIST_ITEM;
464 if (clients_count > 1 && i == clients_count - 1)
465 status = SILC_STATUS_LIST_END;
467 /* Sanity check, however these should never fail. However, as
468 this sanity check has been added here they have failed. */
469 if (!entry->nickname || !entry->username)
472 /* Send WHOIS reply */
473 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
474 tmp = silc_argument_get_first_arg(cmd->args, NULL);
478 char nh[256], uh[256];
479 unsigned char idle[4];
480 SilcSocketConnection hsock;
482 memset(uh, 0, sizeof(uh));
483 memset(nh, 0, sizeof(nh));
485 strncat(nh, entry->nickname, strlen(entry->nickname));
486 if (!strchr(entry->nickname, '@')) {
488 len = entry->router ? strlen(entry->router->server_name) :
489 strlen(server->server_name);
490 strncat(nh, entry->router ? entry->router->server_name :
491 server->server_name, len);
494 strncat(uh, entry->username, strlen(entry->username));
495 if (!strchr(entry->username, '@')) {
497 hsock = (SilcSocketConnection)entry->connection;
498 len = strlen(hsock->hostname);
499 strncat(uh, hsock->hostname, len);
502 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
507 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
509 2, idp->data, idp->len,
513 strlen(entry->userinfo),
517 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
519 2, idp->data, idp->len,
525 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
526 0, packet->data, packet->len, FALSE);
528 silc_buffer_free(packet);
529 silc_buffer_free(idp);
534 silc_server_command_whois_from_client(SilcServerCommandContext cmd)
536 SilcServer server = cmd->server;
537 char *nick = NULL, *server_name = NULL;
538 int count = 0, clients_count = 0;
539 SilcClientEntry *clients = NULL, entry;
540 SilcClientID **client_id = NULL;
541 unsigned int client_id_count = 0;
544 /* Protocol dictates that we must always send the received WHOIS request
545 to our router if we are normal server, so let's do it now unless we
546 are standalone. We will not send any replies to the client until we
547 have received reply from the router. */
548 if (server->server_type == SILC_SERVER &&
549 !cmd->pending && !server->standalone) {
551 unsigned short old_ident;
553 old_ident = silc_command_get_ident(cmd->payload);
554 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
555 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
557 /* Send WHOIS command to our router */
558 silc_server_packet_send(server, (SilcSocketConnection)
559 server->router->connection,
560 SILC_PACKET_COMMAND, cmd->packet->flags,
561 tmpbuf->data, tmpbuf->len, TRUE);
563 /* Reprocess this packet after received reply from router */
564 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
565 silc_command_get_ident(cmd->payload),
566 silc_server_command_whois, (void *)cmd);
569 silc_command_set_ident(cmd->payload, old_ident);
571 silc_buffer_free(tmpbuf);
576 /* We are ready to process the command request. Let's search for the
577 requested client and send reply to the requesting client. */
579 /* Parse the whois request */
580 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
581 &nick, &server_name, &count,
585 /* Get all clients matching that ID or nickname from local list */
586 if (client_id_count) {
587 /* Check all Client ID's received in the command packet */
588 for (i = 0; i < client_id_count; i++) {
589 entry = silc_idlist_find_client_by_id(server->local_list,
592 clients = silc_realloc(clients, sizeof(*clients) *
593 (clients_count + 1));
594 clients[clients_count++] = entry;
598 clients = silc_idlist_get_clients_by_nickname(server->local_list,
603 /* Check global list as well */
605 if (client_id_count) {
606 /* Check all Client ID's received in the command packet */
607 for (i = 0; i < client_id_count; i++) {
608 entry = silc_idlist_find_client_by_id(server->global_list,
611 clients = silc_realloc(clients, sizeof(*clients) *
612 (clients_count + 1));
613 clients[clients_count++] = entry;
617 clients = silc_idlist_get_clients_by_nickname(server->global_list,
624 /* Such client(s) really does not exist in the SILC network. */
625 if (!client_id_count) {
626 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
627 SILC_STATUS_ERR_NO_SUCH_NICK,
628 3, nick, strlen(nick));
630 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
631 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
632 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
633 2, idp->data, idp->len);
634 silc_buffer_free(idp);
639 /* Router always finds the client entry if it exists in the SILC network.
640 However, it might be incomplete entry and does not include all the
641 mandatory fields that WHOIS command reply requires. Check for these and
642 make query from the server who owns the client if some fields are
644 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
649 /* Send the command reply to the client */
650 silc_server_command_whois_send_reply(cmd, clients, clients_count);
653 if (client_id_count) {
654 for (i = 0; i < client_id_count; i++)
655 silc_free(client_id[i]);
656 silc_free(client_id);
663 silc_free(server_name);
669 silc_server_command_whois_from_server(SilcServerCommandContext cmd)
671 SilcServer server = cmd->server;
672 char *nick = NULL, *server_name = NULL;
673 int count = 0, clients_count = 0;
674 SilcClientEntry *clients = NULL, entry;
675 SilcClientID **client_id = NULL;
676 unsigned int client_id_count = 0;
679 /* Parse the whois request */
680 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
681 &nick, &server_name, &count,
685 /* Process the command request. Let's search for the requested client and
686 send reply to the requesting server. */
688 if (client_id_count) {
689 /* Check all Client ID's received in the command packet */
690 for (i = 0; i < client_id_count; i++) {
691 entry = silc_idlist_find_client_by_id(server->local_list,
694 clients = silc_realloc(clients, sizeof(*clients) *
695 (clients_count + 1));
696 clients[clients_count++] = entry;
700 clients = silc_idlist_get_clients_by_nickname(server->local_list,
704 clients = silc_idlist_get_clients_by_hash(server->local_list,
705 nick, server->md5hash,
709 /* If we are router we will check our global list as well. */
710 if (!clients && server->server_type == SILC_ROUTER) {
711 if (client_id_count) {
712 /* Check all Client ID's received in the command packet */
713 for (i = 0; i < client_id_count; i++) {
714 entry = silc_idlist_find_client_by_id(server->global_list,
717 clients = silc_realloc(clients, sizeof(*clients) *
718 (clients_count + 1));
719 clients[clients_count++] = entry;
723 clients = silc_idlist_get_clients_by_nickname(server->global_list,
727 clients = silc_idlist_get_clients_by_hash(server->global_list,
728 nick, server->md5hash,
734 /* Such a client really does not exist in the SILC network. */
735 if (!client_id_count) {
736 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
737 SILC_STATUS_ERR_NO_SUCH_NICK,
738 3, nick, strlen(nick));
740 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
741 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
742 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
743 2, idp->data, idp->len);
744 silc_buffer_free(idp);
749 /* Router always finds the client entry if it exists in the SILC network.
750 However, it might be incomplete entry and does not include all the
751 mandatory fields that WHOIS command reply requires. Check for these and
752 make query from the server who owns the client if some fields are
754 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
759 /* Send the command reply to the client */
760 silc_server_command_whois_send_reply(cmd, clients, clients_count);
763 if (client_id_count) {
764 for (i = 0; i < client_id_count; i++)
765 silc_free(client_id[i]);
766 silc_free(client_id);
773 silc_free(server_name);
778 /* Server side of command WHOIS. Processes user's query and sends found
779 results as command replies back to the client. */
781 SILC_SERVER_CMD_FUNC(whois)
783 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
786 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOIS, cmd, 1, 3328);
788 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
789 ret = silc_server_command_whois_from_client(cmd);
791 ret = silc_server_command_whois_from_server(cmd);
794 silc_server_command_free(cmd);
797 SILC_SERVER_CMD_FUNC(whowas)
801 /******************************************************************************
805 ******************************************************************************/
807 /* Checks that all mandatory fields are present. If not then send WHOIS
808 request to the server who owns the client. We use WHOIS because we want
809 to get as much information as possible at once. */
812 silc_server_command_identify_check(SilcServerCommandContext cmd,
813 SilcClientEntry *clients,
814 unsigned int clients_count)
816 SilcServer server = cmd->server;
818 SilcClientEntry entry;
820 for (i = 0; i < clients_count; i++) {
823 if (!entry->nickname) {
825 unsigned short old_ident;
830 old_ident = silc_command_get_ident(cmd->payload);
831 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
832 silc_command_set_command(cmd->payload, SILC_COMMAND_WHOIS);
833 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
835 /* Send WHOIS request. We send WHOIS since we're doing the requesting
836 now anyway so make it a good one. */
837 silc_server_packet_send(server, entry->router->connection,
838 SILC_PACKET_COMMAND, cmd->packet->flags,
839 tmpbuf->data, tmpbuf->len, TRUE);
841 /* Reprocess this packet after received reply */
842 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
843 silc_command_get_ident(cmd->payload),
844 silc_server_command_identify, (void *)cmd);
847 /* Put old data back to the Command Payload we just changed */
848 silc_command_set_ident(cmd->payload, old_ident);
849 silc_command_set_command(cmd->payload, SILC_COMMAND_IDENTIFY);
851 silc_buffer_free(tmpbuf);
860 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
861 SilcClientEntry *clients,
862 unsigned int clients_count)
864 SilcServer server = cmd->server;
866 int i, count = 0, len;
867 SilcBuffer packet, idp;
868 SilcClientEntry entry;
869 SilcCommandStatus status;
870 unsigned short ident = silc_command_get_ident(cmd->payload);
872 status = SILC_STATUS_OK;
873 if (clients_count > 1)
874 status = SILC_STATUS_LIST_START;
876 for (i = 0; i < clients_count; i++) {
879 if (count && i - 1 == count)
882 if (clients_count > 2)
883 status = SILC_STATUS_LIST_ITEM;
885 if (clients_count > 1 && i == clients_count - 1)
886 status = SILC_STATUS_LIST_END;
888 /* Send IDENTIFY reply */
889 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
890 tmp = silc_argument_get_first_arg(cmd->args, NULL);
894 char nh[256], uh[256];
895 SilcSocketConnection hsock;
897 memset(uh, 0, sizeof(uh));
898 memset(nh, 0, sizeof(nh));
900 strncat(nh, entry->nickname, strlen(entry->nickname));
901 if (!strchr(entry->nickname, '@')) {
903 len = entry->router ? strlen(entry->router->server_name) :
904 strlen(server->server_name);
905 strncat(nh, entry->router ? entry->router->server_name :
906 server->server_name, len);
909 if (!entry->username) {
910 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
911 SILC_STATUS_OK, ident, 2,
912 2, idp->data, idp->len,
915 strncat(uh, entry->username, strlen(entry->username));
916 if (!strchr(entry->username, '@')) {
918 hsock = (SilcSocketConnection)entry->connection;
919 len = strlen(hsock->hostname);
920 strncat(uh, hsock->hostname, len);
923 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
924 SILC_STATUS_OK, ident, 3,
925 2, idp->data, idp->len,
930 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
931 0, packet->data, packet->len, FALSE);
933 silc_buffer_free(packet);
934 silc_buffer_free(idp);
940 silc_server_command_identify_from_client(SilcServerCommandContext cmd)
942 SilcServer server = cmd->server;
943 char *nick = NULL, *server_name = NULL;
944 int count = 0, clients_count = 0;
945 SilcClientEntry *clients = NULL, entry;
946 SilcClientID **client_id = NULL;
947 unsigned int client_id_count = 0;
950 /* Protocol dictates that we must always send the received IDENTIFY request
951 to our router if we are normal server, so let's do it now unless we
952 are standalone. We will not send any replies to the client until we
953 have received reply from the router. */
954 if (server->server_type == SILC_SERVER &&
955 !cmd->pending && !server->standalone) {
957 unsigned short old_ident;
959 old_ident = silc_command_get_ident(cmd->payload);
960 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
961 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
963 /* Send IDENTIFY command to our router */
964 silc_server_packet_send(server, (SilcSocketConnection)
965 server->router->connection,
966 SILC_PACKET_COMMAND, cmd->packet->flags,
967 tmpbuf->data, tmpbuf->len, TRUE);
969 /* Reprocess this packet after received reply from router */
970 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
971 silc_command_get_ident(cmd->payload),
972 silc_server_command_identify, (void *)cmd);
975 silc_command_set_ident(cmd->payload, old_ident);
977 silc_buffer_free(tmpbuf);
982 /* We are ready to process the command request. Let's search for the
983 requested client and send reply to the requesting client. */
985 /* Parse the IDENTIFY request */
986 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
987 &nick, &server_name, &count,
988 SILC_COMMAND_IDENTIFY))
991 /* Get all clients matching that ID or nickname from local list */
992 if (client_id_count) {
993 /* Check all Client ID's received in the command packet */
994 for (i = 0; i < client_id_count; i++) {
995 entry = silc_idlist_find_client_by_id(server->local_list,
998 clients = silc_realloc(clients, sizeof(*clients) *
999 (clients_count + 1));
1000 clients[clients_count++] = entry;
1004 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1009 /* Check global list as well */
1011 if (client_id_count) {
1012 /* Check all Client ID's received in the command packet */
1013 for (i = 0; i < client_id_count; i++) {
1014 entry = silc_idlist_find_client_by_id(server->global_list,
1015 client_id[i], NULL);
1017 clients = silc_realloc(clients, sizeof(*clients) *
1018 (clients_count + 1));
1019 clients[clients_count++] = entry;
1023 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1030 /* Such a client really does not exist in the SILC network. */
1031 if (!client_id_count) {
1032 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1033 SILC_STATUS_ERR_NO_SUCH_NICK,
1034 3, nick, strlen(nick));
1036 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1037 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1038 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1039 2, idp->data, idp->len);
1040 silc_buffer_free(idp);
1045 /* Check that all mandatory fields are present and request those data
1046 from the server who owns the client if necessary. */
1047 if (!cmd->pending &&
1048 !silc_server_command_identify_check(cmd, clients, clients_count)) {
1053 /* Send the command reply to the client */
1054 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1057 if (client_id_count) {
1058 for (i = 0; i < client_id_count; i++)
1059 silc_free(client_id[i]);
1060 silc_free(client_id);
1067 silc_free(server_name);
1073 silc_server_command_identify_from_server(SilcServerCommandContext cmd)
1075 SilcServer server = cmd->server;
1076 char *nick = NULL, *server_name = NULL;
1077 int count = 0, clients_count = 0;
1078 SilcClientEntry *clients = NULL, entry;
1079 SilcClientID **client_id = NULL;
1080 unsigned int client_id_count = 0;
1083 /* Parse the IDENTIFY request */
1084 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1085 &nick, &server_name, &count,
1086 SILC_COMMAND_IDENTIFY))
1089 /* Process the command request. Let's search for the requested client and
1090 send reply to the requesting server. */
1092 if (client_id_count) {
1093 /* Check all Client ID's received in the command packet */
1094 for (i = 0; i < client_id_count; i++) {
1095 entry = silc_idlist_find_client_by_id(server->local_list,
1096 client_id[i], NULL);
1098 clients = silc_realloc(clients, sizeof(*clients) *
1099 (clients_count + 1));
1100 clients[clients_count++] = entry;
1104 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1108 clients = silc_idlist_get_clients_by_hash(server->local_list,
1109 nick, server->md5hash,
1113 /* If we are router we will check our global list as well. */
1114 if (!clients && server->server_type == SILC_ROUTER) {
1115 if (client_id_count) {
1116 /* Check all Client ID's received in the command packet */
1117 for (i = 0; i < client_id_count; i++) {
1118 entry = silc_idlist_find_client_by_id(server->global_list,
1119 client_id[i], NULL);
1121 clients = silc_realloc(clients, sizeof(*clients) *
1122 (clients_count + 1));
1123 clients[clients_count++] = entry;
1127 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1131 clients = silc_idlist_get_clients_by_hash(server->global_list,
1132 nick, server->md5hash,
1138 /* Such a client really does not exist in the SILC network. */
1139 if (!client_id_count) {
1140 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1141 SILC_STATUS_ERR_NO_SUCH_NICK,
1142 3, nick, strlen(nick));
1144 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1145 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1146 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1147 2, idp->data, idp->len);
1148 silc_buffer_free(idp);
1153 /* Check that all mandatory fields are present and request those data
1154 from the server who owns the client if necessary. */
1155 if (!cmd->pending &&
1156 !silc_server_command_identify_check(cmd, clients, clients_count)) {
1161 /* Send the command reply */
1162 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1165 if (client_id_count) {
1166 for (i = 0; i < client_id_count; i++)
1167 silc_free(client_id[i]);
1168 silc_free(client_id);
1175 silc_free(server_name);
1180 SILC_SERVER_CMD_FUNC(identify)
1182 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1185 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1187 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1188 ret = silc_server_command_identify_from_client(cmd);
1190 ret = silc_server_command_identify_from_server(cmd);
1193 silc_server_command_free(cmd);
1196 /* Checks string for bad characters and returns TRUE if they are found. */
1198 static int silc_server_command_bad_chars(char *nick)
1200 if (strchr(nick, '\\')) return TRUE;
1201 if (strchr(nick, '\"')) return TRUE;
1202 if (strchr(nick, '´')) return TRUE;
1203 if (strchr(nick, '`')) return TRUE;
1204 if (strchr(nick, '\'')) return TRUE;
1205 if (strchr(nick, '*')) return TRUE;
1206 if (strchr(nick, '/')) return TRUE;
1207 if (strchr(nick, '@')) return TRUE;
1212 /* Server side of command NICK. Sets nickname for user. Setting
1213 nickname causes generation of a new client ID for the client. The
1214 new client ID is sent to the client after changing the nickname. */
1216 SILC_SERVER_CMD_FUNC(nick)
1218 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1219 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1220 SilcServer server = cmd->server;
1221 SilcBuffer packet, nidp, oidp;
1222 SilcClientID *new_id;
1225 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NICK, cmd, 1, 1);
1227 /* Check nickname */
1228 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1229 if (silc_server_command_bad_chars(nick) == TRUE) {
1230 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1231 SILC_STATUS_ERR_BAD_NICKNAME);
1235 /* Create new Client ID */
1236 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
1237 cmd->server->md5hash, nick,
1240 /* Send notify about nickname change to our router. We send the new
1241 ID and ask to replace it with the old one. If we are router the
1242 packet is broadcasted. */
1243 if (!server->standalone)
1244 silc_server_send_replace_id(server, server->router->connection,
1245 server->server_type == SILC_SERVER ?
1246 FALSE : TRUE, client->id,
1247 SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
1248 new_id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
1250 /* Remove old cache entry */
1251 silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
1254 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1258 memset(client->id, 0, SILC_ID_CLIENT_LEN);
1259 silc_free(client->id);
1262 /* Save the nickname as this client is our local client */
1263 if (client->nickname)
1264 silc_free(client->nickname);
1266 client->nickname = strdup(nick);
1267 client->id = new_id;
1269 /* Update client cache */
1270 silc_idcache_add(server->local_list->clients, client->nickname,
1271 SILC_ID_CLIENT, client->id, (void *)client, TRUE);
1273 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1275 /* Send NICK_CHANGE notify */
1276 silc_server_send_notify_on_channels(server, client,
1277 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1278 oidp->data, oidp->len,
1279 nidp->data, nidp->len);
1281 /* Send the new Client ID as reply command back to client */
1282 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
1283 SILC_STATUS_OK, 0, 1,
1284 2, nidp->data, nidp->len);
1285 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1286 0, packet->data, packet->len, FALSE);
1288 silc_buffer_free(packet);
1289 silc_buffer_free(nidp);
1290 silc_buffer_free(oidp);
1293 silc_server_command_free(cmd);
1296 SILC_SERVER_CMD_FUNC(list)
1300 /* Server side of TOPIC command. Sets topic for channel and/or returns
1301 current topic to client. */
1303 SILC_SERVER_CMD_FUNC(topic)
1305 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1306 SilcServer server = cmd->server;
1307 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1308 SilcChannelID *channel_id;
1309 SilcChannelEntry channel;
1310 SilcChannelClientEntry chl;
1311 SilcBuffer packet, idp;
1313 unsigned int argc, tmp_len;
1315 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
1317 argc = silc_argument_get_arg_num(cmd->args);
1319 /* Get Channel ID */
1320 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1322 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1323 SILC_STATUS_ERR_NO_CHANNEL_ID);
1326 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1328 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1329 SILC_STATUS_ERR_NO_CHANNEL_ID);
1333 /* Check whether the channel exists */
1334 channel = silc_idlist_find_channel_by_id(server->local_list,
1337 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1338 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1344 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1346 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1347 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1351 if (strlen(tmp) > 256) {
1352 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1353 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1357 /* See whether has rights to change topic */
1358 silc_list_start(channel->user_list);
1359 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
1360 if (chl->client == client) {
1361 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1362 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1363 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1371 /* Set the topic for channel */
1373 silc_free(channel->topic);
1374 channel->topic = strdup(tmp);
1376 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1378 /* Send notify about topic change to all clients on the channel */
1379 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
1380 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
1381 idp->data, idp->len,
1382 channel->topic, strlen(channel->topic));
1383 silc_buffer_free(idp);
1386 /* Send the topic to client as reply packet */
1387 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1389 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1390 SILC_STATUS_OK, 0, 2,
1391 2, idp->data, idp->len,
1393 strlen(channel->topic));
1395 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1396 SILC_STATUS_OK, 0, 1,
1397 2, idp->data, idp->len);
1398 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1399 0, packet->data, packet->len, FALSE);
1401 silc_buffer_free(packet);
1402 silc_buffer_free(idp);
1403 silc_free(channel_id);
1406 silc_server_command_free(cmd);
1409 /* Server side of INVITE command. Invites some client to join some channel. */
1411 SILC_SERVER_CMD_FUNC(invite)
1413 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1414 SilcServer server = cmd->server;
1415 SilcSocketConnection sock = cmd->sock, dest_sock;
1416 SilcClientEntry sender, dest;
1417 SilcClientID *dest_id;
1418 SilcChannelEntry channel;
1419 SilcChannelID *channel_id;
1424 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 2);
1426 /* Get destination ID */
1427 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1429 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1430 SILC_STATUS_ERR_NO_CLIENT_ID);
1433 dest_id = silc_id_payload_parse_id(tmp, len);
1435 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1436 SILC_STATUS_ERR_NO_CLIENT_ID);
1440 /* Get Channel ID */
1441 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1443 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1444 SILC_STATUS_ERR_NO_CHANNEL_ID);
1447 channel_id = silc_id_payload_parse_id(tmp, len);
1449 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1450 SILC_STATUS_ERR_NO_CHANNEL_ID);
1454 /* Check whether the channel exists */
1455 channel = silc_idlist_find_channel_by_id(server->local_list,
1458 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1459 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1463 /* Check whether the sender of this command is on the channel. */
1464 sender = (SilcClientEntry)sock->user_data;
1465 if (!silc_server_client_on_channel(sender, channel)) {
1466 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1467 SILC_STATUS_ERR_NOT_ON_CHANNEL);
1471 /* Check whether the channel is invite-only channel. If yes then the
1472 sender of this command must be at least channel operator. */
1473 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1474 SilcChannelClientEntry chl;
1476 silc_list_start(channel->user_list);
1477 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1478 if (chl->client == sender) {
1479 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1480 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1481 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1488 /* Find the connection data for the destination. If it is local we will
1489 send it directly otherwise we will send it to router for routing. */
1490 dest = silc_idlist_find_client_by_id(server->local_list, dest_id, NULL);
1492 dest_sock = (SilcSocketConnection)dest->connection;
1494 dest_sock = silc_server_route_get(server, dest_id, SILC_ID_CLIENT);
1496 /* Check whether the requested client is already on the channel. */
1497 /* XXX if we are normal server we don't know about global clients on
1498 the channel thus we must request it (USERS command), check from
1499 local cache as well. */
1500 if (silc_server_client_on_channel(dest, channel)) {
1501 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1502 SILC_STATUS_ERR_USER_ON_CHANNEL);
1506 sidp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1508 /* Send notify to the client that is invited to the channel */
1509 silc_server_send_notify_dest(server, dest_sock, dest_id, SILC_ID_CLIENT,
1510 SILC_NOTIFY_TYPE_INVITE, 2,
1511 sidp->data, sidp->len, tmp, len);
1513 /* Send command reply */
1514 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1517 silc_buffer_free(sidp);
1520 silc_server_command_free(cmd);
1523 /* Quits connection to client. This gets called if client won't
1524 close the connection even when it has issued QUIT command. */
1526 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
1528 SilcServer server = (SilcServer)context;
1529 SilcSocketConnection sock = server->sockets[fd];
1531 /* Free all client specific data, such as client entry and entires
1532 on channels this client may be on. */
1533 silc_server_free_sock_user_data(server, sock);
1535 /* Close the connection on our side */
1536 silc_server_close_connection(server, sock);
1539 /* Quits SILC session. This is the normal way to disconnect client. */
1541 SILC_SERVER_CMD_FUNC(quit)
1543 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1544 SilcServer server = cmd->server;
1545 SilcSocketConnection sock = cmd->sock;
1547 SILC_LOG_DEBUG(("Start"));
1549 /* We quit the connection with little timeout */
1550 silc_task_register(server->timeout_queue, sock->sock,
1551 silc_server_command_quit_cb, server,
1552 0, 300000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1554 silc_server_command_free(cmd);
1557 SILC_SERVER_CMD_FUNC(kill)
1561 /* Server side of command INFO. This sends information about us to
1562 the client. If client requested specific server we will send the
1563 command to that server. */
1565 SILC_SERVER_CMD_FUNC(info)
1567 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1568 SilcServer server = cmd->server;
1569 SilcBuffer packet, idp;
1570 char info_string[256], *dest_server;
1572 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 1);
1574 /* Get server name */
1575 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1577 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1578 SILC_STATUS_ERR_NO_SUCH_SERVER);
1582 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
1583 /* Send our reply */
1584 memset(info_string, 0, sizeof(info_string));
1585 snprintf(info_string, sizeof(info_string),
1586 "location: %s server: %s admin: %s <%s>",
1587 server->config->admin_info->location,
1588 server->config->admin_info->server_type,
1589 server->config->admin_info->admin_name,
1590 server->config->admin_info->admin_email);
1592 idp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1594 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
1595 SILC_STATUS_OK, 0, 2,
1596 2, idp->data, idp->len,
1598 strlen(info_string));
1599 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1600 packet->data, packet->len, FALSE);
1602 silc_buffer_free(packet);
1603 silc_buffer_free(idp);
1605 /* Send this command to the requested server */
1607 if (server->server_type == SILC_SERVER && !server->standalone) {
1611 if (server->server_type == SILC_ROUTER) {
1617 silc_server_command_free(cmd);
1620 SILC_SERVER_CMD_FUNC(connect)
1624 /* Server side of command PING. This just replies to the ping. */
1626 SILC_SERVER_CMD_FUNC(ping)
1628 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1629 SilcServer server = cmd->server;
1634 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
1637 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1639 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1640 SILC_STATUS_ERR_NO_SERVER_ID);
1643 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
1647 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
1648 /* Send our reply */
1649 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1652 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1653 SILC_STATUS_ERR_NO_SUCH_SERVER);
1660 silc_server_command_free(cmd);
1663 SILC_SERVER_CMD_FUNC(oper)
1667 /* Assembles USERS command and executes it. This is called when client
1668 joins to a channel and we wan't to send USERS command reply to the
1671 void silc_server_command_send_users(SilcServer server,
1672 SilcSocketConnection sock,
1673 SilcChannelEntry channel,
1676 SilcServerCommandContext cmd;
1677 SilcBuffer buffer, idp;
1678 SilcPacketContext *packet = silc_packet_context_alloc();
1680 SILC_LOG_DEBUG(("Start"));
1682 /* Create USERS command packet and process it. */
1683 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1684 buffer = silc_command_payload_encode_va(SILC_COMMAND_USERS, 0, 1,
1685 1, idp->data, idp->len);
1687 packet->buffer = silc_buffer_copy(buffer);
1688 packet->sock = sock;
1689 packet->type = SILC_PACKET_COMMAND;
1691 cmd = silc_calloc(1, sizeof(*cmd));
1692 cmd->payload = silc_command_payload_parse(buffer);
1693 if (!cmd->payload) {
1695 silc_buffer_free(buffer);
1696 silc_buffer_free(idp);
1697 silc_packet_context_free(packet);
1700 cmd->args = silc_command_get_args(cmd->payload);
1701 cmd->server = server;
1703 cmd->packet = silc_packet_context_dup(packet);
1704 cmd->pending = FALSE;
1707 /* If this function was called from pending command then instead of
1708 processing the command now, register a pending command callback which
1709 will process it after we've received the automatic USERS command
1711 silc_server_command_pending(server, SILC_COMMAND_USERS, 0,
1712 silc_server_command_users, (void *)cmd);
1713 cmd->pending = TRUE;
1714 silc_buffer_free(buffer);
1715 silc_buffer_free(idp);
1719 /* Process USERS command. */
1720 silc_server_command_users((void *)cmd);
1722 silc_buffer_free(buffer);
1723 silc_buffer_free(idp);
1724 silc_packet_context_free(packet);
1727 /* Internal routine to join channel. The channel sent to this function
1728 has been either created or resolved from ID lists. This joins the sent
1729 client to the channel. */
1731 static void silc_server_command_join_channel(SilcServer server,
1732 SilcServerCommandContext cmd,
1733 SilcChannelEntry channel,
1734 SilcClientID *client_id,
1738 SilcSocketConnection sock = cmd->sock;
1740 unsigned int tmp_len;
1741 unsigned char *passphrase = NULL, mode[4], tmp2[4];
1742 SilcClientEntry client;
1743 SilcChannelClientEntry chl;
1744 SilcBuffer reply, chidp, clidp, keyp;
1745 unsigned short ident = silc_command_get_ident(cmd->payload);
1747 SILC_LOG_DEBUG(("Start"));
1752 /* Get passphrase */
1753 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1755 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
1756 memcpy(passphrase, tmp, tmp_len);
1760 * Check channel modes
1763 /* Check invite list if channel is invite-only channel */
1764 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1765 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1766 /* Invite list is specified. Check whether client is invited in the
1767 list. If not, then check whether it has been invited otherwise. */
1770 /* XXX client must be invited to be able to join the channel */
1774 /* Check ban list if set */
1775 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1779 /* Check the channel passphrase if set. */
1780 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1781 if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
1782 strlen(channel->mode_data.passphrase))) {
1783 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1784 SILC_STATUS_ERR_BAD_PASSWORD);
1789 /* Check user count limit if set. */
1790 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
1791 if (silc_list_count(channel->user_list) + 1 >
1792 channel->mode_data.user_limit) {
1793 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1794 SILC_STATUS_ERR_CHANNEL_IS_FULL);
1800 * Client is allowed to join to the channel. Make it happen.
1803 /* Get the client entry */
1804 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1805 client = (SilcClientEntry)sock->user_data;
1807 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1810 /* XXX actually this is useless since router finds always cell's
1811 local clients from its local lists. */
1812 client = silc_idlist_find_client_by_id(server->global_list, client_id,
1819 /* Check whether the client already is on the channel */
1820 if (silc_server_client_on_channel(client, channel)) {
1821 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1822 SILC_STATUS_ERR_USER_ON_CHANNEL);
1826 /* Generate new channel key as protocol dictates */
1827 if (!created || !channel->channel_key)
1828 silc_server_create_channel_key(server, channel, 0);
1830 /* Send the channel key. This is broadcasted to the channel but is not
1831 sent to the client who is joining to the channel. */
1832 silc_server_send_channel_key(server, NULL, channel,
1833 server->server_type == SILC_ROUTER ?
1834 FALSE : server->standalone);
1836 /* Join the client to the channel by adding it to channel's user list.
1837 Add also the channel to client entry's channels list for fast cross-
1839 chl = silc_calloc(1, sizeof(*chl));
1841 chl->client = client;
1842 chl->channel = channel;
1843 silc_list_add(channel->user_list, chl);
1844 silc_list_add(client->channels, chl);
1846 /* Encode Client ID Payload of the original client who wants to join */
1847 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1849 /* Encode command reply packet */
1850 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1851 SILC_PUT32_MSB(channel->mode, mode);
1852 SILC_PUT32_MSB(created, tmp2);
1853 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1854 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
1855 SILC_ID_CHANNEL_LEN,
1856 channel->channel_key->cipher->name,
1857 channel->key_len / 8, channel->key);
1859 if (!channel->topic) {
1861 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1862 SILC_STATUS_OK, ident, 5,
1863 2, channel->channel_name,
1864 strlen(channel->channel_name),
1865 3, chidp->data, chidp->len,
1868 6, keyp->data, keyp->len);
1871 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1872 SILC_STATUS_OK, ident, 6,
1873 2, channel->channel_name,
1874 strlen(channel->channel_name),
1875 3, chidp->data, chidp->len,
1878 6, keyp->data, keyp->len,
1880 strlen(channel->topic));
1883 /* Send command reply */
1884 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
1885 reply->data, reply->len, FALSE);
1887 if (!cmd->pending) {
1888 /* Send JOIN notify to locally connected clients on the channel */
1889 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
1890 SILC_NOTIFY_TYPE_JOIN, 1,
1891 clidp->data, clidp->len);
1893 /* Send NEW_CHANNEL_USER packet to our primary router */
1894 if (!server->standalone)
1895 silc_server_send_new_channel_user(server, server->router->connection,
1896 server->server_type == SILC_SERVER ?
1898 channel->id, SILC_ID_CHANNEL_LEN,
1899 client->id, SILC_ID_CLIENT_LEN);
1902 /* Send USERS command reply to the joined channel so the user sees who
1903 is currently on the channel. */
1904 silc_server_command_send_users(server, sock, channel, cmd->pending);
1906 silc_buffer_free(reply);
1907 silc_buffer_free(clidp);
1908 silc_buffer_free(chidp);
1909 silc_buffer_free(keyp);
1913 silc_free(passphrase);
1916 /* Server side of command JOIN. Joins client into requested channel. If
1917 the channel does not exist it will be created. */
1919 SILC_SERVER_CMD_FUNC(join)
1921 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1922 SilcServer server = cmd->server;
1924 char *tmp, *channel_name = NULL, *cipher = NULL;
1925 SilcChannelEntry channel;
1926 unsigned int umode = 0;
1927 int created = FALSE;
1928 SilcClientID *client_id;
1930 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
1932 /* Get channel name */
1933 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1935 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1936 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1941 if (silc_server_command_bad_chars(channel_name) == TRUE) {
1942 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1943 SILC_STATUS_ERR_BAD_CHANNEL);
1944 silc_free(channel_name);
1948 /* Get Client ID of the client who is joining to the channel */
1949 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1951 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1952 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1955 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1957 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1958 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1962 /* Get cipher name */
1963 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
1965 /* See if the channel exists */
1966 channel = silc_idlist_find_channel_by_name(server->local_list,
1967 channel_name, NULL);
1969 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1970 /* If this is coming from client the Client ID in the command packet must
1971 be same as the client's ID. */
1972 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1973 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
1974 if (SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
1975 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1976 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1982 /* Channel not found */
1984 /* If we are standalone server we don't have a router, we just create
1985 the channel by ourselves. */
1986 if (server->standalone) {
1987 channel = silc_server_create_new_channel(server, server->id, cipher,
1989 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
1994 /* The channel does not exist on our server. If we are normal server
1995 we will send JOIN command to our router which will handle the
1996 joining procedure (either creates the channel if it doesn't exist
1997 or joins the client to it). */
1998 if (server->server_type == SILC_SERVER) {
2000 unsigned short old_ident;
2002 old_ident = silc_command_get_ident(cmd->payload);
2003 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2004 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2006 /* Send JOIN command to our router */
2007 silc_server_packet_send(server, (SilcSocketConnection)
2008 server->router->connection,
2009 SILC_PACKET_COMMAND, cmd->packet->flags,
2010 tmpbuf->data, tmpbuf->len, TRUE);
2012 /* Reprocess this packet after received reply from router */
2013 silc_server_command_pending(server, SILC_COMMAND_JOIN,
2014 silc_command_get_ident(cmd->payload),
2015 silc_server_command_join, context);
2016 cmd->pending = TRUE;
2020 /* We are router and the channel does not seem exist so we will check
2021 our global list as well for the channel. */
2022 channel = silc_idlist_find_channel_by_name(server->global_list,
2023 channel_name, NULL);
2025 /* Channel really does not exist, create it */
2026 channel = silc_server_create_new_channel(server, server->id, cipher,
2028 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2035 /* Channel not found */
2037 /* If the command came from router and/or we are normal server then
2038 something went wrong with the joining as the channel was not found.
2039 We can't do anything else but ignore this. */
2040 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
2041 server->server_type == SILC_SERVER)
2044 /* We are router and the channel does not seem exist so we will check
2045 our global list as well for the channel. */
2046 channel = silc_idlist_find_channel_by_name(server->global_list,
2047 channel_name, NULL);
2049 /* Channel really does not exist, create it */
2050 channel = silc_server_create_new_channel(server, server->id, cipher,
2052 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2058 /* If the channel does not have global users and is also empty it means the
2059 channel was created globally (by our router) and the client will be the
2060 channel founder and operator. */
2061 if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
2062 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2063 created = TRUE; /* Created globally by our router */
2066 /* Join to the channel */
2067 silc_server_command_join_channel(server, cmd, channel, client_id,
2070 silc_free(client_id);
2073 silc_server_command_free(cmd);
2076 /* Server side of command MOTD. Sends server's current "message of the
2077 day" to the client. */
2079 SILC_SERVER_CMD_FUNC(motd)
2081 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2082 SilcServer server = cmd->server;
2086 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 2);
2088 /* XXX show currently only our motd */
2090 if (server->config && server->config->motd &&
2091 server->config->motd->motd_file) {
2094 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
2099 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2105 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2110 silc_server_command_free(cmd);
2113 SILC_SERVER_CMD_FUNC(umode)
2117 /* Checks that client has rights to add or remove channel modes. If any
2118 of the checks fails FALSE is returned. */
2120 int silc_server_check_cmode_rights(SilcChannelEntry channel,
2121 SilcChannelClientEntry client,
2124 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
2125 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
2127 /* Check whether has rights to change anything */
2128 if (!is_op && !is_fo)
2131 /* Check whether has rights to change everything */
2135 /* We know that client is channel operator, check that they are not
2136 changing anything that requires channel founder rights. Rest of the
2137 modes are available automatically for channel operator. */
2139 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
2140 if (is_op && !is_fo)
2143 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2144 if (is_op && !is_fo)
2149 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2150 if (is_op && !is_fo)
2153 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2154 if (is_op && !is_fo)
2159 if (mode & SILC_CHANNEL_MODE_CIPHER) {
2160 if (is_op && !is_fo)
2163 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2164 if (is_op && !is_fo)
2172 /* Server side command of CMODE. Changes channel mode */
2174 SILC_SERVER_CMD_FUNC(cmode)
2176 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2177 SilcServer server = cmd->server;
2178 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2179 SilcChannelID *channel_id;
2180 SilcChannelEntry channel;
2181 SilcChannelClientEntry chl;
2182 SilcBuffer packet, cidp;
2183 unsigned char *tmp, *tmp_id, *tmp_mask;
2184 unsigned int argc, mode_mask, tmp_len, tmp_len2;
2186 SILC_LOG_DEBUG(("Start"));
2188 argc = silc_argument_get_arg_num(cmd->args);
2190 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2191 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2195 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2196 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2200 /* Get Channel ID */
2201 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2203 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2204 SILC_STATUS_ERR_NO_CHANNEL_ID);
2207 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
2209 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2210 SILC_STATUS_ERR_NO_CHANNEL_ID);
2214 /* Get the channel mode mask */
2215 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2217 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2218 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2221 SILC_GET32_MSB(mode_mask, tmp_mask);
2223 /* Get channel entry */
2224 channel = silc_idlist_find_channel_by_id(server->local_list,
2227 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2228 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2232 /* Check whether this client is on the channel */
2233 if (!silc_server_client_on_channel(client, channel)) {
2234 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2235 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2239 /* Get entry to the channel user list */
2240 silc_list_start(channel->user_list);
2241 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2242 if (chl->client == client)
2245 /* Check that client has rights to change any requested channel modes */
2246 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
2247 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2248 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2253 * Check the modes. Modes that requires nothing special operation are
2257 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2258 /* Channel uses private keys to protect traffic. Client(s) has set the
2259 key locally they want to use, server does not know that key. */
2260 /* Nothing interesting to do here now */
2262 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2263 /* The mode is removed and we need to generate and distribute
2264 new channel key. Clients are not using private channel keys
2265 anymore after this. */
2267 /* XXX Duplicated code, make own function for this!! LEAVE uses this
2270 /* Re-generate channel key */
2271 silc_server_create_channel_key(server, channel, 0);
2273 /* Encode channel key payload to be distributed on the channel */
2275 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2276 strlen(channel->channel_key->
2278 channel->channel_key->cipher->name,
2279 channel->key_len / 8, channel->key);
2281 /* If we are normal server then we will send it to our router. If we
2282 are router we will send it to all local servers that has clients on
2284 if (server->server_type == SILC_SERVER) {
2285 if (!server->standalone)
2286 silc_server_packet_send(server,
2287 cmd->server->router->connection,
2288 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2294 /* Send to locally connected clients on the channel */
2295 silc_server_packet_send_local_channel(server, channel,
2296 SILC_PACKET_CHANNEL_KEY, 0,
2297 packet->data, packet->len, FALSE);
2298 silc_buffer_free(packet);
2302 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2303 /* User limit is set on channel */
2304 unsigned int user_limit;
2306 /* Get user limit */
2307 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2309 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2310 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2311 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2315 SILC_GET32_MSB(user_limit, tmp);
2316 channel->mode_data.user_limit = user_limit;
2319 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2320 /* User limit mode is unset. Remove user limit */
2321 channel->mode_data.user_limit = 0;
2324 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
2325 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
2326 /* Passphrase has been set to channel */
2328 /* Get the passphrase */
2329 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
2331 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2332 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2336 /* Save the passphrase */
2337 channel->mode_data.passphrase = strdup(tmp);
2340 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2341 /* Passphrase mode is unset. remove the passphrase */
2342 if (channel->mode_data.passphrase) {
2343 silc_free(channel->mode_data.passphrase);
2344 channel->mode_data.passphrase = NULL;
2349 if (mode_mask & SILC_CHANNEL_MODE_BAN) {
2350 if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
2351 /* Ban list is specified for channel */
2354 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
2356 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2357 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2361 /* XXX check that channel founder is not banned */
2363 /* Save the ban list */
2364 channel->mode_data.ban_list = strdup(tmp);
2367 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2368 /* Ban mode is unset. Remove the entire ban list */
2369 if (channel->mode_data.ban_list) {
2370 silc_free(channel->mode_data.ban_list);
2371 channel->mode_data.ban_list = NULL;
2376 if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
2377 if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
2378 /* Invite list is specified for channel */
2380 /* Get invite list */
2381 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
2383 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2384 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2388 /* Save the invite linst */
2389 channel->mode_data.invite_list = strdup(tmp);
2392 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
2393 /* Invite list mode is unset. Remove the entire invite list */
2394 if (channel->mode_data.invite_list) {
2395 silc_free(channel->mode_data.invite_list);
2396 channel->mode_data.invite_list = NULL;
2401 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
2402 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
2403 /* Cipher to use protect the traffic */
2404 unsigned int key_len = 128;
2408 tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
2410 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2411 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2415 cp = strchr(tmp, ':');
2421 /* XXX Duplicated code, make own function for this!! */
2423 /* Delete old cipher and allocate the new one */
2424 silc_cipher_free(channel->channel_key);
2425 silc_cipher_alloc(tmp, &channel->channel_key);
2431 /* Re-generate channel key */
2432 silc_server_create_channel_key(server, channel, key_len);
2434 /* Encode channel key payload to be distributed on the channel */
2436 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2437 strlen(channel->channel_key->
2439 channel->channel_key->cipher->name,
2440 channel->key_len / 8, channel->key);
2442 /* If we are normal server then we will send it to our router. If we
2443 are router we will send it to all local servers that has clients on
2445 if (server->server_type == SILC_SERVER) {
2446 if (!server->standalone)
2447 silc_server_packet_send(server,
2448 cmd->server->router->connection,
2449 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2455 /* Send to locally connected clients on the channel */
2456 silc_server_packet_send_local_channel(server, channel,
2457 SILC_PACKET_CHANNEL_KEY, 0,
2458 packet->data, packet->len, FALSE);
2459 silc_buffer_free(packet);
2462 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2463 /* Cipher mode is unset. Remove the cipher and revert back to
2466 if (channel->mode_data.cipher) {
2467 silc_free(channel->mode_data.cipher);
2468 channel->mode_data.cipher = NULL;
2469 channel->mode_data.key_len = 0;
2472 /* Generate new cipher and key for the channel */
2474 /* XXX Duplicated code, make own function for this!! */
2476 /* Delete old cipher and allocate default one */
2477 silc_cipher_free(channel->channel_key);
2478 if (!channel->cipher)
2479 silc_cipher_alloc("twofish", &channel->channel_key);
2481 silc_cipher_alloc(channel->cipher, &channel->channel_key);
2483 /* Re-generate channel key */
2484 silc_server_create_channel_key(server, channel, 0);
2486 /* Encode channel key payload to be distributed on the channel */
2488 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2489 strlen(channel->channel_key->
2491 channel->channel_key->cipher->name,
2492 channel->key_len / 8, channel->key);
2494 /* If we are normal server then we will send it to our router. If we
2495 are router we will send it to all local servers that has clients on
2497 if (server->server_type == SILC_SERVER) {
2498 if (!server->standalone)
2499 silc_server_packet_send(server,
2500 cmd->server->router->connection,
2501 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2507 /* Send to locally connected clients on the channel */
2508 silc_server_packet_send_local_channel(server, channel,
2509 SILC_PACKET_CHANNEL_KEY, 0,
2510 packet->data, packet->len, FALSE);
2511 silc_buffer_free(packet);
2515 /* Finally, set the mode */
2516 channel->mode = mode_mask;
2518 /* Send CMODE_CHANGE notify */
2519 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2520 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2521 SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
2522 cidp->data, cidp->len,
2526 /* Send command reply to sender */
2527 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2528 SILC_STATUS_OK, 0, 1,
2530 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2531 packet->data, packet->len, FALSE);
2533 silc_buffer_free(packet);
2534 silc_free(channel_id);
2537 silc_server_command_free(cmd);
2540 /* Server side of CUMODE command. Changes client's mode on a channel. */
2542 SILC_SERVER_CMD_FUNC(cumode)
2544 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2545 SilcServer server = cmd->server;
2546 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2547 SilcChannelID *channel_id;
2548 SilcClientID *client_id;
2549 SilcChannelEntry channel;
2550 SilcClientEntry target_client;
2551 SilcChannelClientEntry chl;
2552 SilcBuffer packet, idp;
2553 unsigned char *tmp_id, *tmp_mask;
2554 unsigned int target_mask, sender_mask, tmp_len;
2557 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 3);
2559 /* Get Channel ID */
2560 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2562 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2563 SILC_STATUS_ERR_NO_CHANNEL_ID);
2566 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2568 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2569 SILC_STATUS_ERR_NO_CHANNEL_ID);
2573 /* Get channel entry */
2574 channel = silc_idlist_find_channel_by_id(server->local_list,
2577 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2578 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2582 /* Check whether sender is on the channel */
2583 if (!silc_server_client_on_channel(client, channel)) {
2584 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2585 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2589 /* Check that client has rights to change other's rights */
2590 silc_list_start(channel->user_list);
2591 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2592 if (chl->client == client) {
2593 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
2594 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2595 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2596 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2600 sender_mask = chl->mode;
2605 /* Get the target client's channel mode mask */
2606 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2608 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2609 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2612 SILC_GET32_MSB(target_mask, tmp_mask);
2614 /* Get target Client ID */
2615 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2617 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2618 SILC_STATUS_ERR_NO_CHANNEL_ID);
2621 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2623 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2624 SILC_STATUS_ERR_NO_CHANNEL_ID);
2628 /* Get target client's entry */
2629 target_client = silc_idlist_find_client_by_id(server->local_list,
2631 if (!target_client) {
2632 /* XXX If target client is not one of mine send to primary route */
2635 /* Check whether target client is on the channel */
2636 if (!silc_server_client_on_channel(target_client, channel)) {
2637 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2638 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2642 /* Get entry to the channel user list */
2643 silc_list_start(channel->user_list);
2644 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2645 if (chl->client == target_client)
2652 /* If the target client is founder, no one else can change their mode
2654 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
2655 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2656 SILC_STATUS_ERR_NOT_YOU);
2660 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
2661 /* Cannot promote anyone to channel founder */
2662 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2663 SILC_STATUS_ERR_NOT_YOU);
2666 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2667 if (target_client == client) {
2668 /* Remove channel founder rights from itself */
2669 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
2672 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2673 SILC_STATUS_ERR_NOT_YOU);
2679 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
2680 /* Promote to operator */
2681 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2682 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
2686 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
2687 /* Demote to normal user */
2688 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
2693 /* Send notify to channel, notify only if mode was actually changed. */
2695 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2696 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2697 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
2698 idp->data, idp->len,
2699 tmp_mask, 4, tmp_id, tmp_len);
2700 silc_buffer_free(idp);
2703 /* Send command reply to sender */
2704 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
2705 SILC_STATUS_OK, 0, 2,
2707 3, tmp_id, tmp_len);
2708 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2709 packet->data, packet->len, FALSE);
2711 silc_buffer_free(packet);
2712 silc_free(channel_id);
2713 silc_free(client_id);
2716 silc_server_command_free(cmd);
2719 /* Server side of KICK command. Kicks client out of channel. */
2721 SILC_SERVER_CMD_FUNC(kick)
2725 SILC_SERVER_CMD_FUNC(restart)
2729 SILC_SERVER_CMD_FUNC(close)
2733 SILC_SERVER_CMD_FUNC(die)
2737 SILC_SERVER_CMD_FUNC(silcoper)
2741 /* Server side command of LEAVE. Removes client from a channel. */
2743 SILC_SERVER_CMD_FUNC(leave)
2745 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2746 SilcServer server = cmd->server;
2747 SilcSocketConnection sock = cmd->sock;
2748 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
2750 SilcChannelEntry channel;
2752 unsigned int i, len;
2755 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
2757 /* Get Channel ID */
2758 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2760 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2761 SILC_STATUS_ERR_NO_CHANNEL_ID);
2764 id = silc_id_payload_parse_id(tmp, len);
2766 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2767 SILC_STATUS_ERR_NO_CHANNEL_ID);
2771 /* Get channel entry */
2772 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
2774 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2775 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2779 /* Check whether this client is on the channel */
2780 if (!silc_server_client_on_channel(id_entry, channel)) {
2781 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2782 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2786 /* Notify routers that they should remove this client from their list
2787 of clients on the channel. */
2788 if (!server->standalone)
2789 silc_server_send_remove_channel_user(server,
2790 server->router->connection,
2791 server->server_type == SILC_ROUTER ?
2792 TRUE : FALSE, id_entry->id, id);
2794 /* Remove client from channel */
2795 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
2797 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2800 /* If the channel does not exist anymore we won't send anything */
2804 /* Re-generate channel key */
2805 silc_server_create_channel_key(server, channel, 0);
2807 /* Encode channel key payload to be distributed on the channel */
2809 silc_channel_key_payload_encode(len, tmp,
2810 strlen(channel->channel_key->cipher->name),
2811 channel->channel_key->cipher->name,
2812 channel->key_len / 8, channel->key);
2814 /* If we are normal server then we will send it to our router. If we
2815 are router we will send it to all local servers that has clients on
2817 if (server->server_type == SILC_SERVER) {
2818 if (!server->standalone)
2819 silc_server_packet_send(server,
2820 cmd->server->router->connection,
2821 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2827 /* Send to locally connected clients on the channel */
2828 silc_server_packet_send_local_channel(server, channel,
2829 SILC_PACKET_CHANNEL_KEY, 0,
2830 packet->data, packet->len, FALSE);
2832 silc_buffer_free(packet);
2836 silc_server_command_free(cmd);
2839 /* Server side of command USERS. Resolves clients and their USERS currently
2840 joined on the requested channel. The list of Client ID's and their modes
2841 on the channel is sent back. */
2843 SILC_SERVER_CMD_FUNC(users)
2845 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2846 SilcServer server = cmd->server;
2847 SilcChannelEntry channel;
2848 SilcChannelClientEntry chl;
2851 unsigned char *channel_id;
2852 unsigned int channel_id_len;
2853 SilcBuffer client_id_list;
2854 SilcBuffer client_mode_list;
2856 unsigned char lc[4];
2857 unsigned int list_count = 0;
2858 unsigned short ident = silc_command_get_ident(cmd->payload);
2860 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
2862 /* Get Channel ID */
2863 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
2865 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
2866 SILC_STATUS_ERR_NO_CHANNEL_ID);
2869 id = silc_id_payload_parse_id(channel_id, channel_id_len);
2871 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
2872 SILC_STATUS_ERR_NO_CHANNEL_ID);
2876 /* If we are server and we don't know about this channel we will send
2877 the command to our router. If we know about the channel then we also
2878 have the list of users already. */
2879 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
2881 if (server->server_type == SILC_SERVER && !server->standalone &&
2885 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2886 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2888 /* Send USERS command */
2889 silc_server_packet_send(server, server->router->connection,
2890 SILC_PACKET_COMMAND, cmd->packet->flags,
2891 tmpbuf->data, tmpbuf->len, TRUE);
2893 /* Reprocess this packet after received reply */
2894 silc_server_command_pending(server, SILC_COMMAND_USERS,
2895 silc_command_get_ident(cmd->payload),
2896 silc_server_command_users, (void *)cmd);
2897 cmd->pending = TRUE;
2898 silc_command_set_ident(cmd->payload, ident);
2900 silc_buffer_free(tmpbuf);
2905 /* We are router and we will check the global list as well. */
2906 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
2908 /* Channel really does not exist */
2909 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
2910 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2915 /* Assemble the lists now */
2917 client_id_list = silc_buffer_alloc((SILC_ID_CLIENT_LEN + 4) *
2918 silc_list_count(channel->user_list));
2919 silc_buffer_pull_tail(client_id_list, SILC_BUFFER_END(client_id_list));
2921 silc_buffer_alloc(4 * silc_list_count(channel->user_list));
2922 silc_buffer_pull_tail(client_mode_list, SILC_BUFFER_END(client_mode_list));
2924 silc_list_start(channel->user_list);
2925 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2927 idp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
2928 silc_buffer_put(client_id_list, idp->data, idp->len);
2929 silc_buffer_pull(client_id_list, idp->len);
2930 silc_buffer_free(idp);
2932 /* Client's mode on channel */
2933 SILC_PUT32_MSB(chl->mode, client_mode_list->data);
2934 silc_buffer_pull(client_mode_list, 4);
2938 silc_buffer_push(client_id_list,
2939 client_id_list->data - client_id_list->head);
2940 silc_buffer_push(client_mode_list,
2941 client_mode_list->data - client_mode_list->head);
2944 SILC_PUT32_MSB(list_count, lc);
2947 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
2948 SILC_STATUS_OK, 0, 4,
2949 2, channel_id, channel_id_len,
2951 4, client_id_list->data,
2952 client_id_list->len,
2953 5, client_mode_list->data,
2954 client_mode_list->len);
2955 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2956 packet->data, packet->len, FALSE);
2958 silc_buffer_free(packet);
2959 silc_buffer_free(client_id_list);
2960 silc_buffer_free(client_mode_list);
2964 silc_server_command_free(cmd);