5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2000 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
22 #include "serverincludes.h"
23 #include "server_internal.h"
25 static int silc_server_is_registered(SilcServer server,
26 SilcSocketConnection sock,
27 SilcServerCommandContext cmd,
30 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
32 SilcCommandStatus status);
34 silc_server_command_send_status_data(SilcServerCommandContext cmd,
36 SilcCommandStatus status,
37 unsigned int arg_type,
39 unsigned int arg_len);
40 static void silc_server_command_free(SilcServerCommandContext cmd);
41 void silc_server_command_send_users(SilcServer server,
42 SilcSocketConnection sock,
43 SilcChannelEntry channel,
46 /* Server command list. */
47 SilcServerCommand silc_command_list[] =
49 SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
50 SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
51 SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
52 SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG | SILC_CF_REG),
53 SILC_SERVER_CMD(list, LIST, SILC_CF_LAG | SILC_CF_REG),
54 SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
55 SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
56 SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
57 SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
58 SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
59 SILC_SERVER_CMD(connect, CONNECT,
60 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
61 SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
62 SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
63 SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG | SILC_CF_REG),
64 SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
65 SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
66 SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG | SILC_CF_REG),
67 SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
68 SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG | SILC_CF_REG),
69 SILC_SERVER_CMD(restart, RESTART,
70 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
71 SILC_SERVER_CMD(close, CLOSE,
72 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
73 SILC_SERVER_CMD(die, DIE, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
74 SILC_SERVER_CMD(silcoper, SILCOPER,
75 SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
76 SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG | SILC_CF_REG),
77 SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
82 #define SILC_SERVER_COMMAND_CHECK_ARGC(command, context, min, max) \
84 unsigned int _argc = silc_argument_get_arg_num(cmd->args); \
86 SILC_LOG_DEBUG(("Start")); \
89 silc_server_command_send_status_reply(cmd, command, \
90 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
91 silc_server_command_free(cmd); \
95 silc_server_command_send_status_reply(cmd, command, \
96 SILC_STATUS_ERR_TOO_MANY_PARAMS); \
97 silc_server_command_free(cmd); \
102 /* Returns TRUE if the connection is registered. Unregistered connections
103 usually cannot send commands hence the check. */
105 static int silc_server_is_registered(SilcServer server,
106 SilcSocketConnection sock,
107 SilcServerCommandContext cmd,
110 SilcIDListData idata = (SilcIDListData)sock->user_data;
111 if (idata->registered)
114 silc_server_command_send_status_reply(cmd, command,
115 SILC_STATUS_ERR_NOT_REGISTERED);
116 silc_server_command_free(cmd);
120 /* Processes received command packet. */
122 void silc_server_command_process(SilcServer server,
123 SilcSocketConnection sock,
124 SilcPacketContext *packet)
126 SilcServerCommandContext ctx;
127 SilcServerCommand *cmd;
130 /* XXX allow commands in but do not execute them more than once per
133 /* Check whether it is allowed for this connection to execute any
135 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
137 SilcClientEntry client = (SilcClientEntry)sock->user_data;
142 /* Allow only one command executed in 2 seconds. */
143 curtime = time(NULL);
144 if (client->last_command && (curtime - client->last_command) < 2)
147 /* Update access time */
148 client->last_command = curtime;
152 /* Allocate command context. This must be free'd by the
153 command routine receiving it. */
154 ctx = silc_calloc(1, sizeof(*ctx));
155 ctx->server = server;
157 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
159 /* Parse the command payload in the packet */
160 ctx->payload = silc_command_payload_parse(packet->buffer);
162 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
163 silc_buffer_free(packet->buffer);
164 silc_packet_context_free(packet);
168 ctx->args = silc_command_get_args(ctx->payload);
170 /* Execute command. If this fails the packet is dropped. */
171 for (cmd = silc_command_list; cmd->cb; cmd++)
172 if (cmd->cmd == silc_command_get(ctx->payload)) {
174 if (!(cmd->flags & SILC_CF_REG)) {
179 if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) {
186 SILC_LOG_ERROR(("Unknown command, packet dropped"));
187 silc_server_command_free(ctx);
192 /* Add new pending command to be executed when reply to a command has been
193 received. The `reply_cmd' is the command that will call the `callback'
194 with `context' when reply has been received. If `ident' is non-zero
195 the `callback' will be executed when received reply with command
196 identifier `ident'. */
198 void silc_server_command_pending(SilcServer server,
199 SilcCommand reply_cmd,
200 unsigned short ident,
201 SilcCommandCb callback,
204 SilcServerCommandPending *reply;
206 reply = silc_calloc(1, sizeof(*reply));
207 reply->reply_cmd = reply_cmd;
208 reply->ident = ident;
209 reply->context = context;
210 reply->callback = callback;
211 silc_dlist_add(server->pending_commands, reply);
214 /* Deletes pending command by reply command type. */
216 void silc_server_command_pending_del(SilcServer server,
217 SilcCommand reply_cmd,
218 unsigned short ident)
220 SilcServerCommandPending *r;
222 silc_dlist_start(server->pending_commands);
223 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
224 if (r->reply_cmd == reply_cmd && r->ident == ident) {
225 silc_dlist_del(server->pending_commands, r);
231 /* Checks for pending commands and marks callbacks to be called from
232 the command reply function. Returns TRUE if there were pending command. */
234 int silc_server_command_pending_check(SilcServer server,
235 SilcServerCommandReplyContext ctx,
237 unsigned short ident)
239 SilcServerCommandPending *r;
241 silc_dlist_start(server->pending_commands);
242 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
243 if (r->reply_cmd == command && r->ident == ident) {
244 ctx->context = r->context;
245 ctx->callback = r->callback;
254 /* Free's the command context allocated before executing the command */
256 static void silc_server_command_free(SilcServerCommandContext cmd)
260 silc_command_free_payload(cmd->payload);
262 silc_packet_context_free(cmd->packet);
267 /* Sends simple status message as command reply packet */
270 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
272 SilcCommandStatus status)
276 SILC_LOG_DEBUG(("Sending command status %d", status));
278 buffer = silc_command_reply_payload_encode_va(command, status, 0, 0);
279 silc_server_packet_send(cmd->server, cmd->sock,
280 SILC_PACKET_COMMAND_REPLY, 0,
281 buffer->data, buffer->len, FALSE);
282 silc_buffer_free(buffer);
285 /* Sends command status reply with one extra argument. The argument
286 type must be sent as argument. */
289 silc_server_command_send_status_data(SilcServerCommandContext cmd,
291 SilcCommandStatus status,
292 unsigned int arg_type,
294 unsigned int arg_len)
298 SILC_LOG_DEBUG(("Sending command status %d", status));
300 buffer = silc_command_reply_payload_encode_va(command, status, 0, 1,
301 arg_type, arg, arg_len);
302 silc_server_packet_send(cmd->server, cmd->sock,
303 SILC_PACKET_COMMAND_REPLY, 0,
304 buffer->data, buffer->len, FALSE);
305 silc_buffer_free(buffer);
308 /******************************************************************************
312 ******************************************************************************/
315 silc_server_command_whois_parse(SilcServerCommandContext cmd,
316 SilcClientID ***client_id,
317 unsigned int *client_id_count,
325 unsigned int argc = silc_argument_get_arg_num(cmd->args);
328 /* If client ID is in the command it must be used instead of nickname */
329 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
331 /* No ID, get the nickname@server string and parse it. */
332 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
334 if (strchr(tmp, '@')) {
335 len = strcspn(tmp, "@");
336 *nickname = silc_calloc(len + 1, sizeof(char));
337 memcpy(*nickname, tmp, len);
338 *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
339 memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
341 *nickname = strdup(tmp);
344 silc_server_command_send_status_reply(cmd, command,
345 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
349 /* Command includes ID, we must use that. Also check whether the command
350 has more than one ID set - take them all. */
352 *client_id = silc_calloc(1, sizeof(**client_id));
353 (*client_id)[0] = silc_id_payload_parse_id(tmp, len);
354 *client_id_count = 1;
356 /* Take all ID's from the command packet */
358 for (k = 1, i = 4; i < argc; i++) {
359 tmp = silc_argument_get_arg_type(cmd->args, i, &len);
361 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
362 (*client_id_count + 1));
363 (*client_id)[k++] = silc_id_payload_parse_id(tmp, len);
364 (*client_id_count)++;
369 /* Command includes ID, use that */
372 /* Get the max count of reply messages allowed */
373 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
383 silc_server_command_whois_check(SilcServerCommandContext cmd,
384 SilcClientEntry *clients,
385 unsigned int clients_count)
387 SilcServer server = cmd->server;
389 SilcClientEntry entry;
391 for (i = 0; i < clients_count; i++) {
394 if (!entry->nickname || !entry->username || !entry->userinfo) {
396 unsigned short old_ident;
398 old_ident = silc_command_get_ident(cmd->payload);
399 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
400 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
402 /* Send WHOIS command */
403 silc_server_packet_send(server, entry->router->connection,
404 SILC_PACKET_COMMAND, cmd->packet->flags,
405 tmpbuf->data, tmpbuf->len, TRUE);
407 /* Reprocess this packet after received reply */
408 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
409 silc_command_get_ident(cmd->payload),
410 silc_server_command_whois, (void *)cmd);
413 silc_command_set_ident(cmd->payload, old_ident);
415 silc_buffer_free(tmpbuf);
424 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
425 SilcClientEntry *clients,
426 unsigned int clients_count)
428 SilcServer server = cmd->server;
430 int i, count = 0, len;
431 SilcBuffer packet, idp;
432 SilcClientEntry entry;
433 SilcCommandStatus status;
434 unsigned short ident = silc_command_get_ident(cmd->payload);
436 status = SILC_STATUS_OK;
437 if (clients_count > 1)
438 status = SILC_STATUS_LIST_START;
440 for (i = 0; i < clients_count; i++) {
443 if (count && i - 1 == count)
446 if (clients_count > 2)
447 status = SILC_STATUS_LIST_ITEM;
449 if (clients_count > 1 && i == clients_count - 1)
450 status = SILC_STATUS_LIST_END;
452 /* Send WHOIS reply */
453 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
454 tmp = silc_argument_get_first_arg(cmd->args, NULL);
458 char nh[256], uh[256];
459 unsigned char idle[4];
460 SilcSocketConnection hsock;
462 memset(uh, 0, sizeof(uh));
463 memset(nh, 0, sizeof(nh));
465 strncat(nh, entry->nickname, strlen(entry->nickname));
466 if (!strchr(entry->nickname, '@')) {
468 len = entry->router ? strlen(entry->router->server_name) :
469 strlen(server->server_name);
470 strncat(nh, entry->router ? entry->router->server_name :
471 server->server_name, len);
474 strncat(uh, entry->username, strlen(entry->username));
475 if (!strchr(entry->username, '@')) {
477 hsock = (SilcSocketConnection)entry->connection;
478 len = strlen(hsock->hostname);
479 strncat(uh, hsock->hostname, len);
482 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
487 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
489 2, idp->data, idp->len,
493 strlen(entry->userinfo),
497 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
499 2, idp->data, idp->len,
505 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
506 0, packet->data, packet->len, FALSE);
508 silc_buffer_free(packet);
509 silc_buffer_free(idp);
514 silc_server_command_whois_from_client(SilcServerCommandContext cmd)
516 SilcServer server = cmd->server;
517 char *nick = NULL, *server_name = NULL;
518 int count = 0, clients_count = 0;
519 SilcClientEntry *clients = NULL, entry;
520 SilcClientID **client_id = NULL;
521 unsigned int client_id_count = 0;
524 /* Protocol dictates that we must always send the received WHOIS request
525 to our router if we are normal server, so let's do it now unless we
526 are standalone. We will not send any replies to the client until we
527 have received reply from the router. */
528 if (server->server_type == SILC_SERVER &&
529 !cmd->pending && !server->standalone) {
531 unsigned short old_ident;
533 old_ident = silc_command_get_ident(cmd->payload);
534 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
535 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
537 /* Send WHOIS command to our router */
538 silc_server_packet_send(server, (SilcSocketConnection)
539 server->router->connection,
540 SILC_PACKET_COMMAND, cmd->packet->flags,
541 tmpbuf->data, tmpbuf->len, TRUE);
543 /* Reprocess this packet after received reply from router */
544 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
545 silc_command_get_ident(cmd->payload),
546 silc_server_command_whois, (void *)cmd);
549 silc_command_set_ident(cmd->payload, old_ident);
551 silc_buffer_free(tmpbuf);
556 /* We are ready to process the command request. Let's search for the
557 requested client and send reply to the requesting client. */
559 /* Parse the whois request */
560 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
561 &nick, &server_name, &count,
565 /* Get all clients matching that ID or nickname from local list */
566 if (client_id_count) {
567 /* Check all Client ID's received in the command packet */
568 for (i = 0; i < client_id_count; i++) {
569 entry = silc_idlist_find_client_by_id(server->local_list,
572 clients = silc_realloc(clients, sizeof(*clients) *
573 (clients_count + 1));
574 clients[clients_count++] = entry;
578 clients = silc_idlist_get_clients_by_nickname(server->local_list,
583 /* Check global list as well */
585 if (client_id_count) {
586 /* Check all Client ID's received in the command packet */
587 for (i = 0; i < client_id_count; i++) {
588 entry = silc_idlist_find_client_by_id(server->global_list,
591 clients = silc_realloc(clients, sizeof(*clients) *
592 (clients_count + 1));
593 clients[clients_count++] = entry;
597 clients = silc_idlist_get_clients_by_nickname(server->global_list,
604 /* Such client(s) really does not exist in the SILC network. */
605 if (!client_id_count) {
606 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
607 SILC_STATUS_ERR_NO_SUCH_NICK,
608 3, nick, strlen(nick));
610 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
611 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
612 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
613 2, idp->data, idp->len);
614 silc_buffer_free(idp);
619 /* Router always finds the client entry if it exists in the SILC network.
620 However, it might be incomplete entry and does not include all the
621 mandatory fields that WHOIS command reply requires. Check for these and
622 make query from the server who owns the client if some fields are
624 if (server->server_type == SILC_ROUTER &&
625 !silc_server_command_whois_check(cmd, clients, clients_count)) {
630 /* Send the command reply to the client */
631 silc_server_command_whois_send_reply(cmd, clients, clients_count);
634 if (client_id_count) {
635 for (i = 0; i < client_id_count; i++)
636 silc_free(client_id[i]);
637 silc_free(client_id);
644 silc_free(server_name);
650 silc_server_command_whois_from_server(SilcServerCommandContext cmd)
652 SilcServer server = cmd->server;
653 char *nick = NULL, *server_name = NULL;
654 int count = 0, clients_count = 0;
655 SilcClientEntry *clients = NULL, entry;
656 SilcClientID **client_id = NULL;
657 unsigned int client_id_count = 0;
660 /* Parse the whois request */
661 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
662 &nick, &server_name, &count,
666 /* Process the command request. Let's search for the requested client and
667 send reply to the requesting server. */
669 if (client_id_count) {
670 /* Check all Client ID's received in the command packet */
671 for (i = 0; i < client_id_count; i++) {
672 entry = silc_idlist_find_client_by_id(server->local_list,
675 clients = silc_realloc(clients, sizeof(*clients) *
676 (clients_count + 1));
677 clients[clients_count++] = entry;
681 clients = silc_idlist_get_clients_by_nickname(server->local_list,
685 clients = silc_idlist_get_clients_by_hash(server->local_list,
686 nick, server->md5hash,
690 /* If we are router we will check our global list as well. */
691 if (!clients && server->server_type == SILC_ROUTER) {
692 if (client_id_count) {
693 /* Check all Client ID's received in the command packet */
694 for (i = 0; i < client_id_count; i++) {
695 entry = silc_idlist_find_client_by_id(server->global_list,
698 clients = silc_realloc(clients, sizeof(*clients) *
699 (clients_count + 1));
700 clients[clients_count++] = entry;
704 clients = silc_idlist_get_clients_by_nickname(server->global_list,
708 clients = silc_idlist_get_clients_by_hash(server->global_list,
709 nick, server->md5hash,
715 /* Such a client really does not exist in the SILC network. */
716 if (!client_id_count) {
717 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
718 SILC_STATUS_ERR_NO_SUCH_NICK,
719 3, nick, strlen(nick));
721 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
722 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
723 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
724 2, idp->data, idp->len);
725 silc_buffer_free(idp);
730 /* Router always finds the client entry if it exists in the SILC network.
731 However, it might be incomplete entry and does not include all the
732 mandatory fields that WHOIS command reply requires. Check for these and
733 make query from the server who owns the client if some fields are
735 if (server->server_type == SILC_ROUTER &&
736 !silc_server_command_whois_check(cmd, clients, clients_count)) {
741 /* Send the command reply to the client */
742 silc_server_command_whois_send_reply(cmd, clients, clients_count);
745 if (client_id_count) {
746 for (i = 0; i < client_id_count; i++)
747 silc_free(client_id[i]);
748 silc_free(client_id);
755 silc_free(server_name);
760 /* Server side of command WHOIS. Processes user's query and sends found
761 results as command replies back to the client. */
763 SILC_SERVER_CMD_FUNC(whois)
765 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
768 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOIS, cmd, 1, 3);
770 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
771 ret = silc_server_command_whois_from_client(cmd);
773 ret = silc_server_command_whois_from_server(cmd);
776 silc_server_command_free(cmd);
779 SILC_SERVER_CMD_FUNC(whowas)
783 /******************************************************************************
787 ******************************************************************************/
789 /* Checks that all mandatory fields are present. If not then send WHOIS
790 request to the server who owns the client. We use WHOIS because we want
791 to get as much information as possible at once. */
794 silc_server_command_identify_check(SilcServerCommandContext cmd,
795 SilcClientEntry *clients,
796 unsigned int clients_count)
798 SilcServer server = cmd->server;
800 SilcClientEntry entry;
802 for (i = 0; i < clients_count; i++) {
805 if (!entry->nickname) {
807 unsigned short old_ident;
809 old_ident = silc_command_get_ident(cmd->payload);
810 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
811 silc_command_set_command(cmd->payload, SILC_COMMAND_WHOIS);
812 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
814 /* Send WHOIS request. We send WHOIS since we're doing the requesting
815 now anyway so make it a good one. */
816 silc_server_packet_send(server, entry->router->connection,
817 SILC_PACKET_COMMAND, cmd->packet->flags,
818 tmpbuf->data, tmpbuf->len, TRUE);
820 /* Reprocess this packet after received reply */
821 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
822 silc_command_get_ident(cmd->payload),
823 silc_server_command_identify, (void *)cmd);
826 /* Put old data back to the Command Payload we just changed */
827 silc_command_set_ident(cmd->payload, old_ident);
828 silc_command_set_command(cmd->payload, SILC_COMMAND_IDENTIFY);
830 silc_buffer_free(tmpbuf);
839 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
840 SilcClientEntry *clients,
841 unsigned int clients_count)
843 SilcServer server = cmd->server;
845 int i, count = 0, len;
846 SilcBuffer packet, idp;
847 SilcClientEntry entry;
848 SilcCommandStatus status;
849 unsigned short ident = silc_command_get_ident(cmd->payload);
851 status = SILC_STATUS_OK;
852 if (clients_count > 1)
853 status = SILC_STATUS_LIST_START;
855 for (i = 0; i < clients_count; i++) {
858 if (count && i - 1 == count)
861 if (clients_count > 2)
862 status = SILC_STATUS_LIST_ITEM;
864 if (clients_count > 1 && i == clients_count - 1)
865 status = SILC_STATUS_LIST_END;
867 /* Send IDENTIFY reply */
868 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
869 tmp = silc_argument_get_first_arg(cmd->args, NULL);
873 char nh[256], uh[256];
874 SilcSocketConnection hsock;
876 memset(uh, 0, sizeof(uh));
877 memset(nh, 0, sizeof(nh));
879 strncat(nh, entry->nickname, strlen(entry->nickname));
880 if (!strchr(entry->nickname, '@')) {
882 len = entry->router ? strlen(entry->router->server_name) :
883 strlen(server->server_name);
884 strncat(nh, entry->router ? entry->router->server_name :
885 server->server_name, len);
888 if (!entry->username) {
889 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
890 SILC_STATUS_OK, ident, 2,
891 2, idp->data, idp->len,
894 strncat(uh, entry->username, strlen(entry->username));
895 if (!strchr(entry->username, '@')) {
897 hsock = (SilcSocketConnection)entry->connection;
898 len = strlen(hsock->hostname);
899 strncat(uh, hsock->hostname, len);
902 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
903 SILC_STATUS_OK, ident, 3,
904 2, idp->data, idp->len,
909 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
910 0, packet->data, packet->len, FALSE);
912 silc_buffer_free(packet);
913 silc_buffer_free(idp);
919 silc_server_command_identify_from_client(SilcServerCommandContext cmd)
921 SilcServer server = cmd->server;
922 char *nick = NULL, *server_name = NULL;
923 int count = 0, clients_count = 0;
924 SilcClientEntry *clients = NULL, entry;
925 SilcClientID **client_id = NULL;
926 unsigned int client_id_count = 0;
929 /* Protocol dictates that we must always send the received IDENTIFY request
930 to our router if we are normal server, so let's do it now unless we
931 are standalone. We will not send any replies to the client until we
932 have received reply from the router. */
933 if (server->server_type == SILC_SERVER &&
934 !cmd->pending && !server->standalone) {
936 unsigned short old_ident;
938 old_ident = silc_command_get_ident(cmd->payload);
939 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
940 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
942 /* Send IDENTIFY command to our router */
943 silc_server_packet_send(server, (SilcSocketConnection)
944 server->router->connection,
945 SILC_PACKET_COMMAND, cmd->packet->flags,
946 tmpbuf->data, tmpbuf->len, TRUE);
948 /* Reprocess this packet after received reply from router */
949 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
950 silc_command_get_ident(cmd->payload),
951 silc_server_command_identify, (void *)cmd);
954 silc_command_set_ident(cmd->payload, old_ident);
956 silc_buffer_free(tmpbuf);
961 /* We are ready to process the command request. Let's search for the
962 requested client and send reply to the requesting client. */
964 /* Parse the IDENTIFY request */
965 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
966 &nick, &server_name, &count,
967 SILC_COMMAND_IDENTIFY))
970 /* Get all clients matching that ID or nickname from local list */
971 if (client_id_count) {
972 /* Check all Client ID's received in the command packet */
973 for (i = 0; i < client_id_count; i++) {
974 entry = silc_idlist_find_client_by_id(server->local_list,
977 clients = silc_realloc(clients, sizeof(*clients) *
978 (clients_count + 1));
979 clients[clients_count++] = entry;
983 clients = silc_idlist_get_clients_by_nickname(server->local_list,
988 /* Check global list as well */
990 if (client_id_count) {
991 /* Check all Client ID's received in the command packet */
992 for (i = 0; i < client_id_count; i++) {
993 entry = silc_idlist_find_client_by_id(server->global_list,
996 clients = silc_realloc(clients, sizeof(*clients) *
997 (clients_count + 1));
998 clients[clients_count++] = entry;
1002 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1009 /* Such a client really does not exist in the SILC network. */
1010 if (!client_id_count) {
1011 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1012 SILC_STATUS_ERR_NO_SUCH_NICK,
1013 3, nick, strlen(nick));
1015 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1016 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1017 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1018 2, idp->data, idp->len);
1019 silc_buffer_free(idp);
1024 /* Check that all mandatory fields are present and request those data
1025 from the server who owns the client if necessary. */
1026 if (!cmd->pending && server->server_type == SILC_ROUTER &&
1027 !silc_server_command_identify_check(cmd, clients, clients_count)) {
1032 /* Send the command reply to the client */
1033 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1036 if (client_id_count) {
1037 for (i = 0; i < client_id_count; i++)
1038 silc_free(client_id[i]);
1039 silc_free(client_id);
1046 silc_free(server_name);
1052 silc_server_command_identify_from_server(SilcServerCommandContext cmd)
1054 SilcServer server = cmd->server;
1055 char *nick = NULL, *server_name = NULL;
1056 int count = 0, clients_count = 0;
1057 SilcClientEntry *clients = NULL, entry;
1058 SilcClientID **client_id = NULL;
1059 unsigned int client_id_count = 0;
1062 /* Parse the IDENTIFY request */
1063 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1064 &nick, &server_name, &count,
1065 SILC_COMMAND_IDENTIFY))
1068 /* Process the command request. Let's search for the requested client and
1069 send reply to the requesting server. */
1071 if (client_id_count) {
1072 /* Check all Client ID's received in the command packet */
1073 for (i = 0; i < client_id_count; i++) {
1074 entry = silc_idlist_find_client_by_id(server->local_list,
1075 client_id[i], NULL);
1077 clients = silc_realloc(clients, sizeof(*clients) *
1078 (clients_count + 1));
1079 clients[clients_count++] = entry;
1083 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1087 clients = silc_idlist_get_clients_by_hash(server->local_list,
1088 nick, server->md5hash,
1092 /* If we are router we will check our global list as well. */
1093 if (!clients && server->server_type == SILC_ROUTER) {
1094 if (client_id_count) {
1095 /* Check all Client ID's received in the command packet */
1096 for (i = 0; i < client_id_count; i++) {
1097 entry = silc_idlist_find_client_by_id(server->global_list,
1098 client_id[i], NULL);
1100 clients = silc_realloc(clients, sizeof(*clients) *
1101 (clients_count + 1));
1102 clients[clients_count++] = entry;
1106 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1110 clients = silc_idlist_get_clients_by_hash(server->global_list,
1111 nick, server->md5hash,
1117 /* Such a client really does not exist in the SILC network. */
1118 if (!client_id_count) {
1119 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1120 SILC_STATUS_ERR_NO_SUCH_NICK,
1121 3, nick, strlen(nick));
1123 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1124 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1125 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1126 2, idp->data, idp->len);
1127 silc_buffer_free(idp);
1132 /* Check that all mandatory fields are present and request those data
1133 from the server who owns the client if necessary. */
1134 if (!cmd->pending && server->server_type == SILC_ROUTER &&
1135 !silc_server_command_identify_check(cmd, clients, clients_count)) {
1140 /* Send the command reply */
1141 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1144 if (client_id_count) {
1145 for (i = 0; i < client_id_count; i++)
1146 silc_free(client_id[i]);
1147 silc_free(client_id);
1154 silc_free(server_name);
1159 SILC_SERVER_CMD_FUNC(identify)
1161 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1164 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3);
1166 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1167 ret = silc_server_command_identify_from_client(cmd);
1169 ret = silc_server_command_identify_from_server(cmd);
1172 silc_server_command_free(cmd);
1175 /* Checks string for bad characters and returns TRUE if they are found. */
1177 static int silc_server_command_bad_chars(char *nick)
1179 if (strchr(nick, '\\')) return TRUE;
1180 if (strchr(nick, '\"')) return TRUE;
1181 if (strchr(nick, '´')) return TRUE;
1182 if (strchr(nick, '`')) return TRUE;
1183 if (strchr(nick, '\'')) return TRUE;
1184 if (strchr(nick, '*')) return TRUE;
1185 if (strchr(nick, '/')) return TRUE;
1186 if (strchr(nick, '@')) return TRUE;
1191 /* Server side of command NICK. Sets nickname for user. Setting
1192 nickname causes generation of a new client ID for the client. The
1193 new client ID is sent to the client after changing the nickname. */
1195 SILC_SERVER_CMD_FUNC(nick)
1197 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1198 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1199 SilcServer server = cmd->server;
1200 SilcBuffer packet, nidp, oidp;
1201 SilcClientID *new_id;
1204 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NICK, cmd, 1, 1);
1206 /* Check nickname */
1207 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1208 if (silc_server_command_bad_chars(nick) == TRUE) {
1209 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1210 SILC_STATUS_ERR_BAD_NICKNAME);
1214 /* Create new Client ID */
1215 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
1216 cmd->server->md5hash, nick,
1219 /* Send notify about nickname change to our router. We send the new
1220 ID and ask to replace it with the old one. If we are router the
1221 packet is broadcasted. */
1222 if (!cmd->server->standalone)
1223 silc_server_send_replace_id(server, server->router->connection,
1224 server->server_type == SILC_SERVER ?
1225 FALSE : TRUE, client->id,
1226 SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
1227 new_id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
1229 /* Remove old cache entry */
1230 silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
1233 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1237 memset(client->id, 0, SILC_ID_CLIENT_LEN);
1238 silc_free(client->id);
1241 /* Save the nickname as this client is our local client */
1242 if (client->nickname)
1243 silc_free(client->nickname);
1245 client->nickname = strdup(nick);
1246 client->id = new_id;
1248 /* Update client cache */
1249 silc_idcache_add(server->local_list->clients, client->nickname,
1250 SILC_ID_CLIENT, client->id, (void *)client, TRUE);
1252 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1254 /* Send NICK_CHANGE notify */
1255 silc_server_send_notify_on_channels(server, client,
1256 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1257 oidp->data, oidp->len,
1258 nidp->data, nidp->len);
1260 /* Send the new Client ID as reply command back to client */
1261 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
1262 SILC_STATUS_OK, 0, 1,
1263 2, nidp->data, nidp->len);
1264 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1265 0, packet->data, packet->len, FALSE);
1267 silc_buffer_free(packet);
1268 silc_buffer_free(nidp);
1269 silc_buffer_free(oidp);
1272 silc_server_command_free(cmd);
1275 SILC_SERVER_CMD_FUNC(list)
1279 /* Server side of TOPIC command. Sets topic for channel and/or returns
1280 current topic to client. */
1282 SILC_SERVER_CMD_FUNC(topic)
1284 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1285 SilcServer server = cmd->server;
1286 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1287 SilcChannelID *channel_id;
1288 SilcChannelEntry channel;
1289 SilcChannelClientEntry chl;
1290 SilcBuffer packet, idp;
1292 unsigned int argc, tmp_len;
1294 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
1296 argc = silc_argument_get_arg_num(cmd->args);
1298 /* Get Channel ID */
1299 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1301 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1302 SILC_STATUS_ERR_NO_CHANNEL_ID);
1305 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1307 /* Check whether the channel exists */
1308 channel = silc_idlist_find_channel_by_id(server->local_list,
1311 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1312 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1318 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1320 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1321 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1325 if (strlen(tmp) > 256) {
1326 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1327 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1331 /* See whether has rights to change topic */
1332 silc_list_start(channel->user_list);
1333 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
1334 if (chl->client == client) {
1335 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1336 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1337 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1345 /* Set the topic for channel */
1347 silc_free(channel->topic);
1348 channel->topic = strdup(tmp);
1350 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1352 /* Send notify about topic change to all clients on the channel */
1353 silc_server_send_notify_to_channel(server, channel, TRUE,
1354 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
1355 idp->data, idp->len,
1356 channel->topic, strlen(channel->topic));
1357 silc_buffer_free(idp);
1360 /* Send the topic to client as reply packet */
1361 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1363 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1364 SILC_STATUS_OK, 0, 2,
1365 2, idp->data, idp->len,
1367 strlen(channel->topic));
1369 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1370 SILC_STATUS_OK, 0, 1,
1371 2, idp->data, idp->len);
1372 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1373 0, packet->data, packet->len, FALSE);
1375 silc_buffer_free(packet);
1376 silc_buffer_free(idp);
1377 silc_free(channel_id);
1380 silc_server_command_free(cmd);
1383 /* Server side of INVITE command. Invites some client to join some channel. */
1385 SILC_SERVER_CMD_FUNC(invite)
1387 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1388 SilcServer server = cmd->server;
1389 SilcSocketConnection sock = cmd->sock, dest_sock;
1390 SilcClientEntry sender, dest;
1391 SilcClientID *dest_id;
1392 SilcChannelEntry channel;
1393 SilcChannelID *channel_id;
1398 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 2);
1400 /* Get destination ID */
1401 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1403 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1404 SILC_STATUS_ERR_NO_CLIENT_ID);
1407 dest_id = silc_id_payload_parse_id(tmp, len);
1409 /* Get Channel ID */
1410 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1412 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1413 SILC_STATUS_ERR_NO_CHANNEL_ID);
1416 channel_id = silc_id_payload_parse_id(tmp, len);
1418 /* Check whether the channel exists */
1419 channel = silc_idlist_find_channel_by_id(server->local_list,
1422 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1423 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1427 /* Check whether the sender of this command is on the channel. */
1428 sender = (SilcClientEntry)sock->user_data;
1429 if (!silc_server_client_on_channel(sender, channel)) {
1430 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1431 SILC_STATUS_ERR_NOT_ON_CHANNEL);
1435 /* Check whether the channel is invite-only channel. If yes then the
1436 sender of this command must be at least channel operator. */
1437 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1438 SilcChannelClientEntry chl;
1440 silc_list_start(channel->user_list);
1441 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1442 if (chl->client == sender) {
1443 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1444 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1445 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1452 /* Find the connection data for the destination. If it is local we will
1453 send it directly otherwise we will send it to router for routing. */
1454 dest = silc_idlist_find_client_by_id(server->local_list, dest_id, NULL);
1456 dest_sock = (SilcSocketConnection)dest->connection;
1458 dest_sock = silc_server_route_get(server, dest_id, SILC_ID_CLIENT);
1460 /* Check whether the requested client is already on the channel. */
1461 /* XXX if we are normal server we don't know about global clients on
1462 the channel thus we must request it (USERS command), check from
1463 local cache as well. */
1464 if (silc_server_client_on_channel(dest, channel)) {
1465 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1466 SILC_STATUS_ERR_USER_ON_CHANNEL);
1470 sidp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1472 /* Send notify to the client that is invited to the channel */
1473 silc_server_send_notify_dest(server, dest_sock, dest_id, SILC_ID_CLIENT,
1474 SILC_NOTIFY_TYPE_INVITE, 2,
1475 sidp->data, sidp->len, tmp, len);
1477 /* Send command reply */
1478 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1481 silc_buffer_free(sidp);
1484 silc_server_command_free(cmd);
1487 /* Quits connection to client. This gets called if client won't
1488 close the connection even when it has issued QUIT command. */
1490 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
1492 SilcServer server = (SilcServer)context;
1493 SilcSocketConnection sock = server->sockets[fd];
1495 /* Free all client specific data, such as client entry and entires
1496 on channels this client may be on. */
1497 silc_server_free_sock_user_data(server, sock);
1499 /* Close the connection on our side */
1500 silc_server_close_connection(server, sock);
1503 /* Quits SILC session. This is the normal way to disconnect client. */
1505 SILC_SERVER_CMD_FUNC(quit)
1507 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1508 SilcServer server = cmd->server;
1509 SilcSocketConnection sock = cmd->sock;
1511 SILC_LOG_DEBUG(("Start"));
1513 /* We quit the connection with little timeout */
1514 silc_task_register(server->timeout_queue, sock->sock,
1515 silc_server_command_quit_cb, server,
1516 0, 300000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1518 silc_server_command_free(cmd);
1521 SILC_SERVER_CMD_FUNC(kill)
1525 /* Server side of command INFO. This sends information about us to
1526 the client. If client requested specific server we will send the
1527 command to that server. */
1529 SILC_SERVER_CMD_FUNC(info)
1531 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1532 SilcServer server = cmd->server;
1533 SilcBuffer packet, idp;
1534 char info_string[256], *dest_server;
1536 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 1);
1538 /* Get server name */
1539 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1541 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1542 SILC_STATUS_ERR_NO_SUCH_SERVER);
1546 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
1547 /* Send our reply */
1548 memset(info_string, 0, sizeof(info_string));
1549 snprintf(info_string, sizeof(info_string),
1550 "location: %s server: %s admin: %s <%s>",
1551 server->config->admin_info->location,
1552 server->config->admin_info->server_type,
1553 server->config->admin_info->admin_name,
1554 server->config->admin_info->admin_email);
1556 idp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1558 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
1559 SILC_STATUS_OK, 0, 2,
1560 2, idp->data, idp->len,
1562 strlen(info_string));
1563 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1564 packet->data, packet->len, FALSE);
1566 silc_buffer_free(packet);
1567 silc_buffer_free(idp);
1569 /* Send this command to the requested server */
1571 if (server->server_type == SILC_SERVER && !server->standalone) {
1575 if (server->server_type == SILC_ROUTER) {
1581 silc_server_command_free(cmd);
1584 SILC_SERVER_CMD_FUNC(connect)
1588 /* Server side of command PING. This just replies to the ping. */
1590 SILC_SERVER_CMD_FUNC(ping)
1592 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1593 SilcServer server = cmd->server;
1598 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
1601 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1603 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1604 SILC_STATUS_ERR_NO_SERVER_ID);
1607 id = silc_id_str2id(tmp, SILC_ID_SERVER);
1611 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
1612 /* Send our reply */
1613 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1616 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1617 SILC_STATUS_ERR_NO_SUCH_SERVER);
1624 silc_server_command_free(cmd);
1627 SILC_SERVER_CMD_FUNC(oper)
1631 /* Assembles USERS command and executes it. This is called when client
1632 joins to a channel and we wan't to send USERS command reply to the
1635 void silc_server_command_send_users(SilcServer server,
1636 SilcSocketConnection sock,
1637 SilcChannelEntry channel,
1640 SilcServerCommandContext cmd;
1641 SilcBuffer buffer, idp;
1642 SilcPacketContext *packet = silc_packet_context_alloc();
1644 /* Create USERS command packet and process it. */
1645 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1646 buffer = silc_command_payload_encode_va(SILC_COMMAND_USERS, 0, 1,
1647 1, idp->data, idp->len);
1649 packet->buffer = silc_buffer_copy(buffer);
1650 packet->sock = sock;
1651 packet->type = SILC_PACKET_COMMAND;
1653 cmd = silc_calloc(1, sizeof(*cmd));
1654 cmd->payload = silc_command_payload_parse(buffer);
1655 cmd->args = silc_command_get_args(cmd->payload);
1656 cmd->server = server;
1658 cmd->packet = silc_packet_context_dup(packet);
1659 cmd->pending = FALSE;
1662 /* If this function was called from pending command then instead of
1663 processing the command now, register a pending command callback which
1664 will process it after we've received the automatic USERS command
1666 silc_server_command_pending(server, SILC_COMMAND_USERS, 0,
1667 silc_server_command_users, (void *)cmd);
1668 cmd->pending = TRUE;
1674 /* Process USERS command. */
1675 silc_server_command_users((void *)cmd);
1679 silc_packet_context_free(packet);
1682 /* Internal routine to join channel. The channel sent to this function
1683 has been either created or resolved from ID lists. This joins the sent
1684 client to the channel. */
1686 static void silc_server_command_join_channel(SilcServer server,
1687 SilcServerCommandContext cmd,
1688 SilcChannelEntry channel,
1689 SilcClientID *client_id,
1693 SilcSocketConnection sock = cmd->sock;
1695 unsigned int tmp_len;
1696 unsigned char *passphrase = NULL, mode[4], tmp2[4];
1697 SilcClientEntry client;
1698 SilcChannelClientEntry chl;
1699 SilcBuffer reply, chidp, clidp, keyp;
1700 unsigned short ident = silc_command_get_ident(cmd->payload);
1702 SILC_LOG_DEBUG(("Start"));
1707 /* Get passphrase */
1708 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1710 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
1711 memcpy(passphrase, tmp, tmp_len);
1715 * Check channel modes
1718 /* Check invite list if channel is invite-only channel */
1719 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1720 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1721 /* Invite list is specified. Check whether client is invited in the
1722 list. If not, then check whether it has been invited otherwise. */
1725 /* XXX client must be invited to be able to join the channel */
1729 /* Check ban list if set */
1730 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1734 /* Check the channel passphrase if set. */
1735 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1736 if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
1737 strlen(channel->mode_data.passphrase))) {
1738 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1739 SILC_STATUS_ERR_BAD_PASSWORD);
1744 /* Check user count limit if set. */
1745 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
1746 if (silc_list_count(channel->user_list) + 1 >
1747 channel->mode_data.user_limit) {
1748 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1749 SILC_STATUS_ERR_CHANNEL_IS_FULL);
1755 * Client is allowed to join to the channel. Make it happen.
1758 /* Get the client entry */
1759 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1760 client = (SilcClientEntry)sock->user_data;
1762 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1765 /* XXX actually this is useless since router finds always cell's
1766 local clients from its local lists. */
1767 client = silc_idlist_find_client_by_id(server->global_list, client_id,
1774 /* Check whether the client already is on the channel */
1775 if (silc_server_client_on_channel(client, channel)) {
1776 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1777 SILC_STATUS_ERR_USER_ON_CHANNEL);
1781 /* Generate new channel key as protocol dictates */
1782 if (!created || !channel->channel_key)
1783 silc_server_create_channel_key(server, channel, 0);
1785 /* Send the channel key. This is broadcasted to the channel but is not
1786 sent to the client who is joining to the channel. */
1787 silc_server_send_channel_key(server, channel,
1788 server->server_type == SILC_ROUTER ?
1789 FALSE : server->standalone);
1791 /* Join the client to the channel by adding it to channel's user list.
1792 Add also the channel to client entry's channels list for fast cross-
1794 chl = silc_calloc(1, sizeof(*chl));
1796 chl->client = client;
1797 chl->channel = channel;
1798 silc_list_add(channel->user_list, chl);
1799 silc_list_add(client->channels, chl);
1801 /* Encode Client ID Payload of the original client who wants to join */
1802 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1804 /* Encode command reply packet */
1805 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1806 SILC_PUT32_MSB(channel->mode, mode);
1807 SILC_PUT32_MSB(created, tmp2);
1808 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1809 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
1810 SILC_ID_CHANNEL_LEN,
1811 channel->channel_key->cipher->name,
1812 channel->key_len / 8, channel->key);
1814 if (!channel->topic) {
1816 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1817 SILC_STATUS_OK, ident, 5,
1818 2, channel->channel_name,
1819 strlen(channel->channel_name),
1820 3, chidp->data, chidp->len,
1823 6, keyp->data, keyp->len);
1826 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1827 SILC_STATUS_OK, ident, 6,
1828 2, channel->channel_name,
1829 strlen(channel->channel_name),
1830 3, chidp->data, chidp->len,
1833 6, keyp->data, keyp->len,
1835 strlen(channel->topic));
1838 /* Send command reply */
1839 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
1840 reply->data, reply->len, FALSE);
1842 if (!cmd->pending) {
1843 /* Send JOIN notify to locally connected clients on the channel */
1844 silc_server_send_notify_to_channel(server, channel, FALSE,
1845 SILC_NOTIFY_TYPE_JOIN, 1,
1846 clidp->data, clidp->len);
1848 /* Send NEW_CHANNEL_USER packet to our primary router */
1849 if (!server->standalone)
1850 silc_server_send_new_channel_user(server, server->router->connection,
1851 server->server_type == SILC_SERVER ?
1853 channel->id, SILC_ID_CHANNEL_LEN,
1854 client->id, SILC_ID_CLIENT_LEN);
1857 /* Send USERS command reply to the joined channel so the user sees who
1858 is currently on the channel. */
1859 silc_server_command_send_users(server, sock, channel, cmd->pending);
1861 silc_buffer_free(reply);
1862 silc_buffer_free(clidp);
1863 silc_buffer_free(chidp);
1864 silc_buffer_free(keyp);
1868 silc_free(passphrase);
1871 /* Server side of command JOIN. Joins client into requested channel. If
1872 the channel does not exist it will be created. */
1874 SILC_SERVER_CMD_FUNC(join)
1876 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1877 SilcServer server = cmd->server;
1879 char *tmp, *channel_name = NULL, *cipher = NULL;
1880 SilcChannelEntry channel;
1881 unsigned int umode = 0;
1882 int created = FALSE;
1883 SilcClientID *client_id;
1885 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
1887 /* Get channel name */
1888 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1890 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1891 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1896 if (silc_server_command_bad_chars(channel_name) == TRUE) {
1897 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1898 SILC_STATUS_ERR_BAD_CHANNEL);
1899 silc_free(channel_name);
1903 /* Get Client ID of the client who is joining to the channel */
1904 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1906 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1907 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1910 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1912 /* Get cipher name */
1913 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
1915 /* See if the channel exists */
1916 channel = silc_idlist_find_channel_by_name(server->local_list,
1917 channel_name, NULL);
1919 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1920 /* If this is coming from client the Client ID in the command packet must
1921 be same as the client's ID. */
1922 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1923 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
1924 if (SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
1925 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1926 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1932 /* Channel not found */
1934 /* If we are standalone server we don't have a router, we just create
1935 the channel by ourselves. */
1936 if (server->standalone) {
1937 channel = silc_server_create_new_channel(server, server->id, cipher,
1939 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
1944 /* The channel does not exist on our server. If we are normal server
1945 we will send JOIN command to our router which will handle the
1946 joining procedure (either creates the channel if it doesn't exist
1947 or joins the client to it). */
1948 if (server->server_type == SILC_SERVER) {
1950 unsigned short old_ident;
1952 old_ident = silc_command_get_ident(cmd->payload);
1953 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1954 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1956 /* Send JOIN command to our router */
1957 silc_server_packet_send(server, (SilcSocketConnection)
1958 server->router->connection,
1959 SILC_PACKET_COMMAND, cmd->packet->flags,
1960 tmpbuf->data, tmpbuf->len, TRUE);
1962 /* Reprocess this packet after received reply from router */
1963 silc_server_command_pending(server, SILC_COMMAND_JOIN,
1964 silc_command_get_ident(cmd->payload),
1965 silc_server_command_join, context);
1966 cmd->pending = TRUE;
1970 /* We are router and the channel does not seem exist so we will check
1971 our global list as well for the channel. */
1972 channel = silc_idlist_find_channel_by_name(server->global_list,
1973 channel_name, NULL);
1975 /* Channel really does not exist, create it */
1976 channel = silc_server_create_new_channel(server, server->id, cipher,
1978 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
1985 /* Channel not found */
1987 /* If the command came from router and/or we are normal server then
1988 something went wrong with the joining as the channel was not found.
1989 We can't do anything else but ignore this. */
1990 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
1991 server->server_type == SILC_SERVER)
1994 /* We are router and the channel does not seem exist so we will check
1995 our global list as well for the channel. */
1996 channel = silc_idlist_find_channel_by_name(server->global_list,
1997 channel_name, NULL);
1999 /* Channel really does not exist, create it */
2000 channel = silc_server_create_new_channel(server, server->id, cipher,
2002 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2008 /* If the channel does not have global users and is also empty it means the
2009 channel was created globally (by our router) and the client will be the
2010 channel founder and operator. */
2011 if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
2012 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2013 created = TRUE; /* Created globally by our router */
2016 /* Join to the channel */
2017 silc_server_command_join_channel(server, cmd, channel, client_id,
2020 silc_free(client_id);
2023 silc_server_command_free(cmd);
2026 /* Server side of command MOTD. Sends server's current "message of the
2027 day" to the client. */
2029 SILC_SERVER_CMD_FUNC(motd)
2031 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2032 SilcServer server = cmd->server;
2036 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 2);
2038 /* XXX show currently only our motd */
2040 if (server->config && server->config->motd &&
2041 server->config->motd->motd_file) {
2044 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
2049 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2055 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2060 silc_server_command_free(cmd);
2063 SILC_SERVER_CMD_FUNC(umode)
2067 /* Checks that client has rights to add or remove channel modes. If any
2068 of the checks fails FALSE is returned. */
2070 int silc_server_check_cmode_rights(SilcChannelEntry channel,
2071 SilcChannelClientEntry client,
2074 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
2075 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
2077 /* Check whether has rights to change anything */
2078 if (!is_op && !is_fo)
2081 /* Check whether has rights to change everything */
2085 /* We know that client is channel operator, check that they are not
2086 changing anything that requires channel founder rights. Rest of the
2087 modes are available automatically for channel operator. */
2089 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
2090 if (is_op && !is_fo)
2093 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2094 if (is_op && !is_fo)
2099 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2100 if (is_op && !is_fo)
2103 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2104 if (is_op && !is_fo)
2109 if (mode & SILC_CHANNEL_MODE_CIPHER) {
2110 if (is_op && !is_fo)
2113 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2114 if (is_op && !is_fo)
2122 /* Server side command of CMODE. Changes channel mode */
2124 SILC_SERVER_CMD_FUNC(cmode)
2126 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2127 SilcServer server = cmd->server;
2128 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2129 SilcChannelID *channel_id;
2130 SilcChannelEntry channel;
2131 SilcChannelClientEntry chl;
2132 SilcBuffer packet, cidp;
2133 unsigned char *tmp, *tmp_id, *tmp_mask;
2134 unsigned int argc, mode_mask, tmp_len, tmp_len2;
2136 SILC_LOG_DEBUG(("Start"));
2138 argc = silc_argument_get_arg_num(cmd->args);
2140 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2141 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2145 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2146 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2150 /* Get Channel ID */
2151 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2153 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2154 SILC_STATUS_ERR_NO_CHANNEL_ID);
2157 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
2159 /* Get the channel mode mask */
2160 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2162 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2163 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2166 SILC_GET32_MSB(mode_mask, tmp_mask);
2168 /* Get channel entry */
2169 channel = silc_idlist_find_channel_by_id(server->local_list,
2172 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2173 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2177 /* Check whether this client is on the channel */
2178 if (!silc_server_client_on_channel(client, channel)) {
2179 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2180 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2184 /* Get entry to the channel user list */
2185 silc_list_start(channel->user_list);
2186 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2187 if (chl->client == client)
2190 /* Check that client has rights to change any requested channel modes */
2191 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
2192 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2193 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2198 * Check the modes. Modes that requires nothing special operation are
2202 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2203 /* Channel uses private keys to protect traffic. Client(s) has set the
2204 key locally they want to use, server does not know that key. */
2205 /* Nothing interesting to do here now */
2207 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2208 /* The mode is removed and we need to generate and distribute
2209 new channel key. Clients are not using private channel keys
2210 anymore after this. */
2212 /* XXX Duplicated code, make own function for this!! LEAVE uses this
2215 /* Re-generate channel key */
2216 silc_server_create_channel_key(server, channel, 0);
2218 /* Encode channel key payload to be distributed on the channel */
2220 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2221 strlen(channel->channel_key->
2223 channel->channel_key->cipher->name,
2224 channel->key_len / 8, channel->key);
2226 /* If we are normal server then we will send it to our router. If we
2227 are router we will send it to all local servers that has clients on
2229 if (server->server_type == SILC_SERVER) {
2230 if (!server->standalone)
2231 silc_server_packet_send(server,
2232 cmd->server->router->connection,
2233 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2239 /* Send to locally connected clients on the channel */
2240 silc_server_packet_send_local_channel(server, channel,
2241 SILC_PACKET_CHANNEL_KEY, 0,
2242 packet->data, packet->len, FALSE);
2243 silc_buffer_free(packet);
2247 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2248 /* User limit is set on channel */
2249 unsigned int user_limit;
2251 /* Get user limit */
2252 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2254 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2255 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2256 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2260 SILC_GET32_MSB(user_limit, tmp);
2261 channel->mode_data.user_limit = user_limit;
2264 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2265 /* User limit mode is unset. Remove user limit */
2266 channel->mode_data.user_limit = 0;
2269 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
2270 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
2271 /* Passphrase has been set to channel */
2273 /* Get the passphrase */
2274 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
2276 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2277 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2281 /* Save the passphrase */
2282 channel->mode_data.passphrase = strdup(tmp);
2285 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2286 /* Passphrase mode is unset. remove the passphrase */
2287 if (channel->mode_data.passphrase) {
2288 silc_free(channel->mode_data.passphrase);
2289 channel->mode_data.passphrase = NULL;
2294 if (mode_mask & SILC_CHANNEL_MODE_BAN) {
2295 if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
2296 /* Ban list is specified for channel */
2299 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
2301 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2302 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2306 /* XXX check that channel founder is not banned */
2308 /* Save the ban list */
2309 channel->mode_data.ban_list = strdup(tmp);
2312 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2313 /* Ban mode is unset. Remove the entire ban list */
2314 if (channel->mode_data.ban_list) {
2315 silc_free(channel->mode_data.ban_list);
2316 channel->mode_data.ban_list = NULL;
2321 if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
2322 if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
2323 /* Invite list is specified for channel */
2325 /* Get invite list */
2326 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
2328 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2329 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2333 /* Save the invite linst */
2334 channel->mode_data.invite_list = strdup(tmp);
2337 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
2338 /* Invite list mode is unset. Remove the entire invite list */
2339 if (channel->mode_data.invite_list) {
2340 silc_free(channel->mode_data.invite_list);
2341 channel->mode_data.invite_list = NULL;
2346 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
2347 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
2348 /* Cipher to use protect the traffic */
2349 unsigned int key_len = 128;
2353 tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
2355 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2356 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2360 cp = strchr(tmp, ':');
2366 /* XXX Duplicated code, make own function for this!! */
2368 /* Delete old cipher and allocate the new one */
2369 silc_cipher_free(channel->channel_key);
2370 silc_cipher_alloc(tmp, &channel->channel_key);
2376 /* Re-generate channel key */
2377 silc_server_create_channel_key(server, channel, key_len);
2379 /* Encode channel key payload to be distributed on the channel */
2381 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2382 strlen(channel->channel_key->
2384 channel->channel_key->cipher->name,
2385 channel->key_len / 8, channel->key);
2387 /* If we are normal server then we will send it to our router. If we
2388 are router we will send it to all local servers that has clients on
2390 if (server->server_type == SILC_SERVER) {
2391 if (!server->standalone)
2392 silc_server_packet_send(server,
2393 cmd->server->router->connection,
2394 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2400 /* Send to locally connected clients on the channel */
2401 silc_server_packet_send_local_channel(server, channel,
2402 SILC_PACKET_CHANNEL_KEY, 0,
2403 packet->data, packet->len, FALSE);
2404 silc_buffer_free(packet);
2407 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2408 /* Cipher mode is unset. Remove the cipher and revert back to
2411 if (channel->mode_data.cipher) {
2412 silc_free(channel->mode_data.cipher);
2413 channel->mode_data.cipher = NULL;
2414 channel->mode_data.key_len = 0;
2417 /* Generate new cipher and key for the channel */
2419 /* XXX Duplicated code, make own function for this!! */
2421 /* Delete old cipher and allocate default one */
2422 silc_cipher_free(channel->channel_key);
2423 if (!channel->cipher)
2424 silc_cipher_alloc("twofish", &channel->channel_key);
2426 silc_cipher_alloc(channel->cipher, &channel->channel_key);
2428 /* Re-generate channel key */
2429 silc_server_create_channel_key(server, channel, 0);
2431 /* Encode channel key payload to be distributed on the channel */
2433 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2434 strlen(channel->channel_key->
2436 channel->channel_key->cipher->name,
2437 channel->key_len / 8, channel->key);
2439 /* If we are normal server then we will send it to our router. If we
2440 are router we will send it to all local servers that has clients on
2442 if (server->server_type == SILC_SERVER) {
2443 if (!server->standalone)
2444 silc_server_packet_send(server,
2445 cmd->server->router->connection,
2446 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2452 /* Send to locally connected clients on the channel */
2453 silc_server_packet_send_local_channel(server, channel,
2454 SILC_PACKET_CHANNEL_KEY, 0,
2455 packet->data, packet->len, FALSE);
2456 silc_buffer_free(packet);
2460 /* Finally, set the mode */
2461 channel->mode = mode_mask;
2463 /* Send CMODE_CHANGE notify */
2464 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2465 silc_server_send_notify_to_channel(server, channel, TRUE,
2466 SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
2467 cidp->data, cidp->len,
2471 /* Send command reply to sender */
2472 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2473 SILC_STATUS_OK, 0, 1,
2475 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2476 packet->data, packet->len, FALSE);
2478 silc_buffer_free(packet);
2479 silc_free(channel_id);
2482 silc_server_command_free(cmd);
2485 /* Server side of CUMODE command. Changes client's mode on a channel. */
2487 SILC_SERVER_CMD_FUNC(cumode)
2489 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2490 SilcServer server = cmd->server;
2491 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2492 SilcChannelID *channel_id;
2493 SilcClientID *client_id;
2494 SilcChannelEntry channel;
2495 SilcClientEntry target_client;
2496 SilcChannelClientEntry chl;
2497 SilcBuffer packet, idp;
2498 unsigned char *tmp_id, *tmp_mask;
2499 unsigned int target_mask, sender_mask, tmp_len;
2502 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 3);
2504 /* Get Channel ID */
2505 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2507 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2508 SILC_STATUS_ERR_NO_CHANNEL_ID);
2511 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2513 /* Get channel entry */
2514 channel = silc_idlist_find_channel_by_id(server->local_list,
2517 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2518 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2522 /* Check whether sender is on the channel */
2523 if (!silc_server_client_on_channel(client, channel)) {
2524 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2525 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2529 /* Check that client has rights to change other's rights */
2530 silc_list_start(channel->user_list);
2531 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2532 if (chl->client == client) {
2533 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
2534 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2535 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2536 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2540 sender_mask = chl->mode;
2545 /* Get the target client's channel mode mask */
2546 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2548 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2549 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2552 SILC_GET32_MSB(target_mask, tmp_mask);
2554 /* Get target Client ID */
2555 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2557 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2558 SILC_STATUS_ERR_NO_CHANNEL_ID);
2561 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2563 /* Get target client's entry */
2564 target_client = silc_idlist_find_client_by_id(server->local_list,
2566 if (!target_client) {
2567 /* XXX If target client is not one of mine send to primary route */
2570 /* Check whether target client is on the channel */
2571 if (!silc_server_client_on_channel(target_client, channel)) {
2572 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2573 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2577 /* Get entry to the channel user list */
2578 silc_list_start(channel->user_list);
2579 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2580 if (chl->client == target_client)
2587 /* If the target client is founder, no one else can change their mode
2589 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
2590 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2591 SILC_STATUS_ERR_NOT_YOU);
2595 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
2596 /* Cannot promote anyone to channel founder */
2597 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2598 SILC_STATUS_ERR_NOT_YOU);
2601 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2602 if (target_client == client) {
2603 /* Remove channel founder rights from itself */
2604 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
2607 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2608 SILC_STATUS_ERR_NOT_YOU);
2614 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
2615 /* Promote to operator */
2616 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2617 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
2621 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
2622 /* Demote to normal user */
2623 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
2628 /* Send notify to channel, notify only if mode was actually changed. */
2630 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2631 silc_server_send_notify_to_channel(server, channel, TRUE,
2632 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
2633 idp->data, idp->len,
2634 tmp_mask, 4, tmp_id, tmp_len);
2635 silc_buffer_free(idp);
2638 /* Send command reply to sender */
2639 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
2640 SILC_STATUS_OK, 0, 2,
2642 3, tmp_id, tmp_len);
2643 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2644 packet->data, packet->len, FALSE);
2646 silc_buffer_free(packet);
2647 silc_free(channel_id);
2648 silc_free(client_id);
2651 silc_server_command_free(cmd);
2654 /* Server side of KICK command. Kicks client out of channel. */
2656 SILC_SERVER_CMD_FUNC(kick)
2660 SILC_SERVER_CMD_FUNC(restart)
2664 SILC_SERVER_CMD_FUNC(close)
2668 SILC_SERVER_CMD_FUNC(die)
2672 SILC_SERVER_CMD_FUNC(silcoper)
2676 /* Server side command of LEAVE. Removes client from a channel. */
2678 SILC_SERVER_CMD_FUNC(leave)
2680 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2681 SilcServer server = cmd->server;
2682 SilcSocketConnection sock = cmd->sock;
2683 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
2685 SilcChannelEntry channel;
2687 unsigned int i, len;
2690 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
2692 /* Get Channel ID */
2693 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2695 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2696 SILC_STATUS_ERR_NO_CHANNEL_ID);
2699 id = silc_id_payload_parse_id(tmp, len);
2701 /* Get channel entry */
2702 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
2704 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2705 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2709 /* Check whether this client is on the channel */
2710 if (!silc_server_client_on_channel(id_entry, channel)) {
2711 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2712 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2716 /* Notify routers that they should remove this client from their list
2717 of clients on the channel. */
2718 if (!server->standalone)
2719 silc_server_send_remove_channel_user(server,
2720 server->router->connection,
2721 server->server_type == SILC_ROUTER ?
2722 TRUE : FALSE, id_entry->id, id);
2724 /* Remove client from channel */
2725 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
2727 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2730 /* If the channel does not exist anymore we won't send anything */
2734 /* Re-generate channel key */
2735 silc_server_create_channel_key(server, channel, 0);
2737 /* Encode channel key payload to be distributed on the channel */
2739 silc_channel_key_payload_encode(len, tmp,
2740 strlen(channel->channel_key->cipher->name),
2741 channel->channel_key->cipher->name,
2742 channel->key_len / 8, channel->key);
2744 /* If we are normal server then we will send it to our router. If we
2745 are router we will send it to all local servers that has clients on
2747 if (server->server_type == SILC_SERVER) {
2748 if (!server->standalone)
2749 silc_server_packet_send(server,
2750 cmd->server->router->connection,
2751 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2757 /* Send to locally connected clients on the channel */
2758 silc_server_packet_send_local_channel(server, channel,
2759 SILC_PACKET_CHANNEL_KEY, 0,
2760 packet->data, packet->len, FALSE);
2762 silc_buffer_free(packet);
2766 silc_server_command_free(cmd);
2769 /* Server side of command USERS. Resolves clients and their USERS currently
2770 joined on the requested channel. The list of Client ID's and their modes
2771 on the channel is sent back. */
2773 SILC_SERVER_CMD_FUNC(users)
2775 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2776 SilcServer server = cmd->server;
2777 SilcChannelEntry channel;
2778 SilcChannelClientEntry chl;
2781 unsigned char *channel_id;
2782 unsigned int channel_id_len;
2783 SilcBuffer client_id_list;
2784 SilcBuffer client_mode_list;
2786 unsigned char lc[4];
2787 unsigned int list_count = 0;
2788 unsigned short ident = silc_command_get_ident(cmd->payload);
2790 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 2);
2792 /* Get Channel ID */
2793 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
2795 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
2796 SILC_STATUS_ERR_NO_CHANNEL_ID);
2799 id = silc_id_payload_parse_id(channel_id, channel_id_len);
2801 /* If we are server and we don't know about this channel we will send
2802 the command to our router. If we know about the channel then we also
2803 have the list of users already. */
2804 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
2806 if (server->server_type == SILC_SERVER && !server->standalone &&
2810 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2811 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2813 /* Send USERS command */
2814 silc_server_packet_send(server, server->router->connection,
2815 SILC_PACKET_COMMAND, cmd->packet->flags,
2816 tmpbuf->data, tmpbuf->len, TRUE);
2818 /* Reprocess this packet after received reply */
2819 silc_server_command_pending(server, SILC_COMMAND_USERS,
2820 silc_command_get_ident(cmd->payload),
2821 silc_server_command_users, (void *)cmd);
2822 cmd->pending = TRUE;
2823 silc_command_set_ident(cmd->payload, ident);
2825 silc_buffer_free(tmpbuf);
2830 /* We are router and we will check the global list as well. */
2831 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
2833 /* Channel really does not exist */
2834 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
2835 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2840 /* Assemble the lists now */
2842 client_id_list = silc_buffer_alloc((SILC_ID_CLIENT_LEN + 4) *
2843 silc_list_count(channel->user_list));
2844 silc_buffer_pull_tail(client_id_list, SILC_BUFFER_END(client_id_list));
2846 silc_buffer_alloc(4 * silc_list_count(channel->user_list));
2847 silc_buffer_pull_tail(client_mode_list, SILC_BUFFER_END(client_mode_list));
2849 silc_list_start(channel->user_list);
2850 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2852 idp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
2853 silc_buffer_put(client_id_list, idp->data, idp->len);
2854 silc_buffer_pull(client_id_list, idp->len);
2855 silc_buffer_free(idp);
2857 /* Client's mode on channel */
2858 SILC_PUT32_MSB(chl->mode, client_mode_list->data);
2859 silc_buffer_pull(client_mode_list, 4);
2863 silc_buffer_push(client_id_list,
2864 client_id_list->data - client_id_list->head);
2865 silc_buffer_push(client_mode_list,
2866 client_mode_list->data - client_mode_list->head);
2869 SILC_PUT32_MSB(list_count, lc);
2872 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
2873 SILC_STATUS_OK, 0, 4,
2874 2, channel_id, channel_id_len,
2876 4, client_id_list->data,
2877 client_id_list->len,
2878 5, client_mode_list->data,
2879 client_mode_list->len);
2880 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2881 packet->data, packet->len, FALSE);
2883 silc_buffer_free(packet);
2884 silc_buffer_free(client_id_list);
2885 silc_buffer_free(client_mode_list);
2889 silc_server_command_free(cmd);