5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2001 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
22 #include "serverincludes.h"
23 #include "server_internal.h"
25 static int silc_server_is_registered(SilcServer server,
26 SilcSocketConnection sock,
27 SilcServerCommandContext cmd,
30 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
32 SilcCommandStatus status);
34 silc_server_command_send_status_data(SilcServerCommandContext cmd,
36 SilcCommandStatus status,
37 unsigned int arg_type,
39 unsigned int arg_len);
40 SILC_TASK_CALLBACK(silc_server_command_process_timeout);
42 /* Server command list. */
43 SilcServerCommand silc_command_list[] =
45 SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
46 SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
47 SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
48 SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
49 SILC_SERVER_CMD(list, LIST, SILC_CF_LAG_STRICT | SILC_CF_REG),
50 SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
51 SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
52 SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
53 SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG_STRICT | SILC_CF_REG | SILC_CF_OPER),
54 SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
55 SILC_SERVER_CMD(connect, CONNECT,
56 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
57 SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
58 SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
59 SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG_STRICT | SILC_CF_REG),
60 SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
61 SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
62 SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG | SILC_CF_REG),
63 SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
64 SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
65 SILC_SERVER_CMD(restart, RESTART,
66 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
67 SILC_SERVER_CMD(close, CLOSE,
68 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
69 SILC_SERVER_CMD(shutdown, SHUTDOWN, SILC_CF_LAG | SILC_CF_REG |
71 SILC_SERVER_CMD(silcoper, SILCOPER,
72 SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
73 SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
74 SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
79 #define SILC_SERVER_COMMAND_CHECK_ARGC(command, context, min, max) \
81 unsigned int _argc = silc_argument_get_arg_num(cmd->args); \
83 SILC_LOG_DEBUG(("Start")); \
86 silc_server_command_send_status_reply(cmd, command, \
87 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
88 silc_server_command_free(cmd); \
92 silc_server_command_send_status_reply(cmd, command, \
93 SILC_STATUS_ERR_TOO_MANY_PARAMS); \
94 silc_server_command_free(cmd); \
99 /* Returns TRUE if the connection is registered. Unregistered connections
100 usually cannot send commands hence the check. */
102 static int silc_server_is_registered(SilcServer server,
103 SilcSocketConnection sock,
104 SilcServerCommandContext cmd,
107 SilcIDListData idata = (SilcIDListData)sock->user_data;
108 if (idata->registered)
111 silc_server_command_send_status_reply(cmd, command,
112 SILC_STATUS_ERR_NOT_REGISTERED);
113 silc_server_command_free(cmd);
117 /* Internal context to hold data when executed command with timeout. */
119 SilcServerCommandContext ctx;
120 SilcServerCommand *cmd;
121 } *SilcServerCommandTimeout;
123 /* Timeout callback to process commands with timeout for client. Client's
124 commands are always executed with timeout. */
126 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
128 SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
129 SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data;
131 /* Update access time */
132 client->last_command = time(NULL);
134 if (!(timeout->cmd->flags & SILC_CF_REG))
135 timeout->cmd->cb(timeout->ctx);
136 else if (silc_server_is_registered(timeout->ctx->server,
140 timeout->cmd->cb(timeout->ctx);
145 /* Processes received command packet. */
147 void silc_server_command_process(SilcServer server,
148 SilcSocketConnection sock,
149 SilcPacketContext *packet)
151 SilcServerCommandContext ctx;
152 SilcServerCommand *cmd;
154 /* Allocate command context. This must be free'd by the
155 command routine receiving it. */
156 ctx = silc_server_command_alloc();
157 ctx->server = server;
158 ctx->sock = silc_socket_dup(sock);
159 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
161 /* Parse the command payload in the packet */
162 ctx->payload = silc_command_payload_parse(packet->buffer);
164 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
165 silc_buffer_free(packet->buffer);
166 silc_packet_context_free(packet);
167 silc_socket_free(ctx->sock);
171 ctx->args = silc_command_get_args(ctx->payload);
173 /* Get the command */
174 for (cmd = silc_command_list; cmd->cb; cmd++)
175 if (cmd->cmd == silc_command_get(ctx->payload))
179 SILC_LOG_ERROR(("Unknown command, packet dropped"));
180 silc_server_command_free(ctx);
184 /* Execute client's commands always with timeout. Normally they are
185 executed with zero (0) timeout but if client is sending command more
186 frequently than once in 2 seconds, then the timeout may be 0 to 2
188 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
189 SilcClientEntry client = (SilcClientEntry)sock->user_data;
190 SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
196 if (client->last_command && (time(NULL) - client->last_command) < 2) {
197 client->fast_command++;
200 client->fast_command = ((client->fast_command - 1) <= 0 ? 0 :
201 client->fast_command--);
205 if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
206 (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
207 silc_task_register(server->timeout_queue, sock->sock,
208 silc_server_command_process_timeout,
210 2 - (time(NULL) - client->last_command), 0,
212 SILC_TASK_PRI_NORMAL);
214 silc_task_register(server->timeout_queue, sock->sock,
215 silc_server_command_process_timeout,
219 SILC_TASK_PRI_NORMAL);
223 /* Execute for server */
225 if (!(cmd->flags & SILC_CF_REG))
227 else if (silc_server_is_registered(server, sock, ctx, cmd->cmd))
231 /* Allocate Command Context */
233 SilcServerCommandContext silc_server_command_alloc()
235 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
240 /* Free's the command context allocated before executing the command */
242 void silc_server_command_free(SilcServerCommandContext ctx)
245 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
247 if (ctx->users < 1) {
249 silc_command_free_payload(ctx->payload);
251 silc_packet_context_free(ctx->packet);
253 silc_socket_free(ctx->sock); /* Decrease reference counter */
258 /* Duplicate Command Context by adding reference counter. The context won't
259 be free'd untill it hits zero. */
261 SilcServerCommandContext
262 silc_server_command_dup(SilcServerCommandContext ctx)
265 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
270 /* Add new pending command to be executed when reply to a command has been
271 received. The `reply_cmd' is the command that will call the `callback'
272 with `context' when reply has been received. If `ident' is non-zero
273 the `callback' will be executed when received reply with command
274 identifier `ident'. */
276 void silc_server_command_pending(SilcServer server,
277 SilcCommand reply_cmd,
278 unsigned short ident,
279 SilcServerPendingDestructor destructor,
280 SilcCommandCb callback,
283 SilcServerCommandPending *reply;
285 reply = silc_calloc(1, sizeof(*reply));
286 reply->reply_cmd = reply_cmd;
287 reply->ident = ident;
288 reply->context = context;
289 reply->callback = callback;
290 reply->destructor = destructor;
291 silc_dlist_add(server->pending_commands, reply);
294 /* Deletes pending command by reply command type. */
296 void silc_server_command_pending_del(SilcServer server,
297 SilcCommand reply_cmd,
298 unsigned short ident)
300 SilcServerCommandPending *r;
302 silc_dlist_start(server->pending_commands);
303 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
304 if (r->reply_cmd == reply_cmd && r->ident == ident) {
305 silc_dlist_del(server->pending_commands, r);
311 /* Checks for pending commands and marks callbacks to be called from
312 the command reply function. Returns TRUE if there were pending command. */
314 int silc_server_command_pending_check(SilcServer server,
315 SilcServerCommandReplyContext ctx,
317 unsigned short ident)
319 SilcServerCommandPending *r;
321 silc_dlist_start(server->pending_commands);
322 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
323 if (r->reply_cmd == command && r->ident == ident) {
324 ctx->context = r->context;
325 ctx->callback = r->callback;
326 ctx->destructor = r->destructor;
335 /* Destructor function for pending callbacks. This is called when using
336 pending commands to free the context given for the pending command. */
338 static void silc_server_command_destructor(void *context)
340 silc_server_command_free((SilcServerCommandContext)context);
343 /* Sends simple status message as command reply packet */
346 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
348 SilcCommandStatus status)
352 SILC_LOG_DEBUG(("Sending command status %d", status));
354 buffer = silc_command_reply_payload_encode_va(command, status, 0, 0);
355 silc_server_packet_send(cmd->server, cmd->sock,
356 SILC_PACKET_COMMAND_REPLY, 0,
357 buffer->data, buffer->len, FALSE);
358 silc_buffer_free(buffer);
361 /* Sends command status reply with one extra argument. The argument
362 type must be sent as argument. */
365 silc_server_command_send_status_data(SilcServerCommandContext cmd,
367 SilcCommandStatus status,
368 unsigned int arg_type,
370 unsigned int arg_len)
374 SILC_LOG_DEBUG(("Sending command status %d", status));
376 buffer = silc_command_reply_payload_encode_va(command, status, 0, 1,
377 arg_type, arg, arg_len);
378 silc_server_packet_send(cmd->server, cmd->sock,
379 SILC_PACKET_COMMAND_REPLY, 0,
380 buffer->data, buffer->len, FALSE);
381 silc_buffer_free(buffer);
384 /******************************************************************************
388 ******************************************************************************/
391 silc_server_command_whois_parse(SilcServerCommandContext cmd,
392 SilcClientID ***client_id,
393 unsigned int *client_id_count,
401 unsigned int argc = silc_argument_get_arg_num(cmd->args);
404 /* If client ID is in the command it must be used instead of nickname */
405 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
407 /* No ID, get the nickname@server string and parse it. */
408 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
410 if (strchr(tmp, '@')) {
411 len = strcspn(tmp, "@");
412 *nickname = silc_calloc(len + 1, sizeof(char));
413 memcpy(*nickname, tmp, len);
414 *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
415 memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
417 *nickname = strdup(tmp);
420 silc_server_command_send_status_reply(cmd, command,
421 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
425 /* Command includes ID, we must use that. Also check whether the command
426 has more than one ID set - take them all. */
428 *client_id = silc_calloc(1, sizeof(**client_id));
429 (*client_id)[0] = silc_id_payload_parse_id(tmp, len);
430 if ((*client_id)[0] == NULL) {
431 silc_free(*client_id);
434 *client_id_count = 1;
436 /* Take all ID's from the command packet */
438 for (k = 1, i = 1; i < argc; i++) {
439 tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
441 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
442 (*client_id_count + 1));
443 (*client_id)[k] = silc_id_payload_parse_id(tmp, len);
444 if ((*client_id)[k] == NULL) {
445 /* Cleanup all and fail */
446 for (i = 0; i < *client_id_count; i++)
447 silc_free((*client_id)[i]);
448 silc_free(*client_id);
451 (*client_id_count)++;
457 /* Command includes ID, use that */
460 /* Get the max count of reply messages allowed */
461 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
471 silc_server_command_whois_check(SilcServerCommandContext cmd,
472 SilcClientEntry *clients,
473 unsigned int clients_count)
475 SilcServer server = cmd->server;
477 SilcClientEntry entry;
479 for (i = 0; i < clients_count; i++) {
482 if (!entry->nickname || !entry->username) {
484 unsigned short old_ident;
489 old_ident = silc_command_get_ident(cmd->payload);
490 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
491 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
493 /* Send WHOIS command */
494 silc_server_packet_send(server, entry->router->connection,
495 SILC_PACKET_COMMAND, cmd->packet->flags,
496 tmpbuf->data, tmpbuf->len, TRUE);
498 /* Reprocess this packet after received reply */
499 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
500 silc_command_get_ident(cmd->payload),
501 silc_server_command_destructor,
502 silc_server_command_whois,
503 silc_server_command_dup(cmd));
506 silc_command_set_ident(cmd->payload, old_ident);
508 silc_buffer_free(tmpbuf);
517 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
518 SilcClientEntry *clients,
519 unsigned int clients_count)
521 SilcServer server = cmd->server;
523 int i, count = 0, len;
524 SilcBuffer packet, idp;
525 SilcClientEntry entry;
526 SilcCommandStatus status;
527 unsigned short ident = silc_command_get_ident(cmd->payload);
529 status = SILC_STATUS_OK;
530 if (clients_count > 1)
531 status = SILC_STATUS_LIST_START;
533 for (i = 0; i < clients_count; i++) {
536 if (entry->connection && entry->data.registered == FALSE) {
537 if (clients_count == 1)
538 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
539 SILC_STATUS_ERR_NO_SUCH_NICK,
541 strlen(entry->nickname));
545 if (count && i - 1 == count)
548 if (clients_count > 2)
549 status = SILC_STATUS_LIST_ITEM;
551 if (clients_count > 1 && i == clients_count - 1)
552 status = SILC_STATUS_LIST_END;
554 /* Sanity check, however these should never fail. However, as
555 this sanity check has been added here they have failed. */
556 if (!entry->nickname || !entry->username)
559 /* Send WHOIS reply */
560 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
561 tmp = silc_argument_get_first_arg(cmd->args, NULL);
564 char nh[256], uh[256];
565 unsigned char idle[4];
566 SilcSocketConnection hsock;
568 memset(uh, 0, sizeof(uh));
569 memset(nh, 0, sizeof(nh));
571 strncat(nh, entry->nickname, strlen(entry->nickname));
572 if (!strchr(entry->nickname, '@')) {
574 len = entry->router ? strlen(entry->router->server_name) :
575 strlen(server->server_name);
576 strncat(nh, entry->router ? entry->router->server_name :
577 server->server_name, len);
580 strncat(uh, entry->username, strlen(entry->username));
581 if (!strchr(entry->username, '@')) {
583 hsock = (SilcSocketConnection)entry->connection;
584 len = strlen(hsock->hostname);
585 strncat(uh, hsock->hostname, len);
588 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
591 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
593 2, idp->data, idp->len,
597 strlen(entry->userinfo),
601 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
602 0, packet->data, packet->len, FALSE);
604 silc_buffer_free(packet);
605 silc_buffer_free(idp);
610 silc_server_command_whois_from_client(SilcServerCommandContext cmd)
612 SilcServer server = cmd->server;
613 char *nick = NULL, *server_name = NULL;
614 int count = 0, clients_count = 0;
615 SilcClientEntry *clients = NULL, entry;
616 SilcClientID **client_id = NULL;
617 unsigned int client_id_count = 0;
620 /* Protocol dictates that we must always send the received WHOIS request
621 to our router if we are normal server, so let's do it now unless we
622 are standalone. We will not send any replies to the client until we
623 have received reply from the router. */
624 if (server->server_type == SILC_SERVER &&
625 !cmd->pending && !server->standalone) {
627 unsigned short old_ident;
629 old_ident = silc_command_get_ident(cmd->payload);
630 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
631 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
633 /* Send WHOIS command to our router */
634 silc_server_packet_send(server, (SilcSocketConnection)
635 server->router->connection,
636 SILC_PACKET_COMMAND, cmd->packet->flags,
637 tmpbuf->data, tmpbuf->len, TRUE);
639 /* Reprocess this packet after received reply from router */
640 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
641 silc_command_get_ident(cmd->payload),
642 silc_server_command_destructor,
643 silc_server_command_whois,
644 silc_server_command_dup(cmd));
647 silc_command_set_ident(cmd->payload, old_ident);
649 silc_buffer_free(tmpbuf);
654 /* We are ready to process the command request. Let's search for the
655 requested client and send reply to the requesting client. */
657 /* Parse the whois request */
658 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
659 &nick, &server_name, &count,
663 /* Get all clients matching that ID or nickname from local list */
664 if (client_id_count) {
665 /* Check all Client ID's received in the command packet */
666 for (i = 0; i < client_id_count; i++) {
667 entry = silc_idlist_find_client_by_id(server->local_list,
670 clients = silc_realloc(clients, sizeof(*clients) *
671 (clients_count + 1));
672 clients[clients_count++] = entry;
676 clients = silc_idlist_get_clients_by_nickname(server->local_list,
680 clients = silc_idlist_get_clients_by_hash(server->local_list,
681 nick, server->md5hash,
685 /* Check global list as well */
687 if (client_id_count) {
688 /* Check all Client ID's received in the command packet */
689 for (i = 0; i < client_id_count; i++) {
690 entry = silc_idlist_find_client_by_id(server->global_list,
693 clients = silc_realloc(clients, sizeof(*clients) *
694 (clients_count + 1));
695 clients[clients_count++] = entry;
699 clients = silc_idlist_get_clients_by_nickname(server->global_list,
703 clients = silc_idlist_get_clients_by_hash(server->global_list,
704 nick, server->md5hash,
710 /* Such client(s) really does not exist in the SILC network. */
711 if (!client_id_count) {
712 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
713 SILC_STATUS_ERR_NO_SUCH_NICK,
714 3, nick, strlen(nick));
716 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
717 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
718 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
719 2, idp->data, idp->len);
720 silc_buffer_free(idp);
725 /* Router always finds the client entry if it exists in the SILC network.
726 However, it might be incomplete entry and does not include all the
727 mandatory fields that WHOIS command reply requires. Check for these and
728 make query from the server who owns the client if some fields are
730 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
735 /* Send the command reply to the client */
736 silc_server_command_whois_send_reply(cmd, clients, clients_count);
739 if (client_id_count) {
740 for (i = 0; i < client_id_count; i++)
741 silc_free(client_id[i]);
742 silc_free(client_id);
749 silc_free(server_name);
755 silc_server_command_whois_from_server(SilcServerCommandContext cmd)
757 SilcServer server = cmd->server;
758 char *nick = NULL, *server_name = NULL;
759 int count = 0, clients_count = 0;
760 SilcClientEntry *clients = NULL, entry;
761 SilcClientID **client_id = NULL;
762 unsigned int client_id_count = 0;
765 /* Parse the whois request */
766 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
767 &nick, &server_name, &count,
771 /* Process the command request. Let's search for the requested client and
772 send reply to the requesting server. */
774 if (client_id_count) {
775 /* Check all Client ID's received in the command packet */
776 for (i = 0; i < client_id_count; i++) {
777 entry = silc_idlist_find_client_by_id(server->local_list,
780 clients = silc_realloc(clients, sizeof(*clients) *
781 (clients_count + 1));
782 clients[clients_count++] = entry;
786 clients = silc_idlist_get_clients_by_nickname(server->local_list,
790 clients = silc_idlist_get_clients_by_hash(server->local_list,
791 nick, server->md5hash,
795 /* If we are router we will check our global list as well. */
796 if (!clients && server->server_type == SILC_ROUTER) {
797 if (client_id_count) {
798 /* Check all Client ID's received in the command packet */
799 for (i = 0; i < client_id_count; i++) {
800 entry = silc_idlist_find_client_by_id(server->global_list,
803 clients = silc_realloc(clients, sizeof(*clients) *
804 (clients_count + 1));
805 clients[clients_count++] = entry;
809 clients = silc_idlist_get_clients_by_nickname(server->global_list,
813 clients = silc_idlist_get_clients_by_hash(server->global_list,
814 nick, server->md5hash,
820 /* Such a client really does not exist in the SILC network. */
821 if (!client_id_count) {
822 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
823 SILC_STATUS_ERR_NO_SUCH_NICK,
824 3, nick, strlen(nick));
826 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
827 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
828 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
829 2, idp->data, idp->len);
830 silc_buffer_free(idp);
835 /* Router always finds the client entry if it exists in the SILC network.
836 However, it might be incomplete entry and does not include all the
837 mandatory fields that WHOIS command reply requires. Check for these and
838 make query from the server who owns the client if some fields are
840 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
845 /* Send the command reply to the client */
846 silc_server_command_whois_send_reply(cmd, clients, clients_count);
849 if (client_id_count) {
850 for (i = 0; i < client_id_count; i++)
851 silc_free(client_id[i]);
852 silc_free(client_id);
859 silc_free(server_name);
864 /* Server side of command WHOIS. Processes user's query and sends found
865 results as command replies back to the client. */
867 SILC_SERVER_CMD_FUNC(whois)
869 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
872 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOIS, cmd, 1, 3328);
874 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
875 ret = silc_server_command_whois_from_client(cmd);
876 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
877 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
878 ret = silc_server_command_whois_from_server(cmd);
881 silc_server_command_free(cmd);
884 /******************************************************************************
888 ******************************************************************************/
891 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
899 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
901 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
902 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
906 /* Get the nickname@server string and parse it. */
907 if (strchr(tmp, '@')) {
908 len = strcspn(tmp, "@");
909 *nickname = silc_calloc(len + 1, sizeof(char));
910 memcpy(*nickname, tmp, len);
911 *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
912 memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
914 *nickname = strdup(tmp);
916 /* Get the max count of reply messages allowed */
917 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
927 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
928 SilcClientEntry *clients,
929 unsigned int clients_count)
931 SilcServer server = cmd->server;
933 int i, count = 0, len;
934 SilcBuffer packet, idp;
935 SilcClientEntry entry = NULL;
936 SilcCommandStatus status;
937 unsigned short ident = silc_command_get_ident(cmd->payload);
940 status = SILC_STATUS_OK;
941 if (clients_count > 1)
942 status = SILC_STATUS_LIST_START;
944 for (i = 0; i < clients_count; i++) {
947 /* We will take only clients that are not valid anymore. They are the
948 ones that are not registered anymore but still have a ID. They
949 have disconnected us, and thus valid for WHOWAS. */
950 if (entry->data.registered == TRUE)
952 if (entry->id == NULL)
955 if (count && i - 1 == count)
960 if (clients_count > 2)
961 status = SILC_STATUS_LIST_ITEM;
963 if (clients_count > 1 && i == clients_count - 1)
964 status = SILC_STATUS_LIST_END;
966 /* Sanity check, however these should never fail. However, as
967 this sanity check has been added here they have failed. */
968 if (!entry->nickname || !entry->username)
971 /* Send WHOWAS reply */
972 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
973 tmp = silc_argument_get_first_arg(cmd->args, NULL);
976 char nh[256], uh[256];
978 memset(uh, 0, sizeof(uh));
979 memset(nh, 0, sizeof(nh));
981 strncat(nh, entry->nickname, strlen(entry->nickname));
982 if (!strchr(entry->nickname, '@')) {
984 len = entry->router ? strlen(entry->router->server_name) :
985 strlen(server->server_name);
986 strncat(nh, entry->router ? entry->router->server_name :
987 server->server_name, len);
990 strncat(uh, entry->username, strlen(entry->username));
991 if (!strchr(entry->username, '@')) {
993 strcat(uh, "*private*");
997 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
999 2, idp->data, idp->len,
1003 strlen(entry->userinfo));
1006 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1007 0, packet->data, packet->len, FALSE);
1009 silc_buffer_free(packet);
1010 silc_buffer_free(idp);
1013 if (found == FALSE && entry)
1014 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1015 SILC_STATUS_ERR_NO_SUCH_NICK,
1017 strlen(entry->nickname));
1021 silc_server_command_whowas_from_client(SilcServerCommandContext cmd)
1023 SilcServer server = cmd->server;
1024 char *nick = NULL, *server_name = NULL;
1025 int count = 0, clients_count = 0;
1026 SilcClientEntry *clients = NULL;
1029 /* Protocol dictates that we must always send the received WHOWAS request
1030 to our router if we are normal server, so let's do it now unless we
1031 are standalone. We will not send any replies to the client until we
1032 have received reply from the router. */
1033 if (server->server_type == SILC_SERVER &&
1034 !cmd->pending && !server->standalone) {
1036 unsigned short old_ident;
1038 old_ident = silc_command_get_ident(cmd->payload);
1039 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1040 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1042 /* Send WHOWAS command to our router */
1043 silc_server_packet_send(server, (SilcSocketConnection)
1044 server->router->connection,
1045 SILC_PACKET_COMMAND, cmd->packet->flags,
1046 tmpbuf->data, tmpbuf->len, TRUE);
1048 /* Reprocess this packet after received reply from router */
1049 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1050 silc_command_get_ident(cmd->payload),
1051 silc_server_command_destructor,
1052 silc_server_command_whois,
1053 silc_server_command_dup(cmd));
1054 cmd->pending = TRUE;
1056 silc_command_set_ident(cmd->payload, old_ident);
1058 silc_buffer_free(tmpbuf);
1063 /* We are ready to process the command request. Let's search for the
1064 requested client and send reply to the requesting client. */
1066 /* Parse the whowas request */
1067 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1070 /* Get all clients matching that nickname from local list */
1071 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1075 clients = silc_idlist_get_clients_by_hash(server->local_list,
1076 nick, server->md5hash,
1079 /* Check global list as well */
1081 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1085 clients = silc_idlist_get_clients_by_hash(server->global_list,
1086 nick, server->md5hash,
1091 /* Such client(s) really does not exist in the SILC network. */
1092 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1093 SILC_STATUS_ERR_NO_SUCH_NICK,
1094 3, nick, strlen(nick));
1098 /* Send the command reply to the client */
1099 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1107 silc_free(server_name);
1113 silc_server_command_whowas_from_server(SilcServerCommandContext cmd)
1115 SilcServer server = cmd->server;
1116 char *nick = NULL, *server_name = NULL;
1117 int count = 0, clients_count = 0;
1118 SilcClientEntry *clients = NULL;
1121 /* Parse the whowas request */
1122 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1125 /* Process the command request. Let's search for the requested client and
1126 send reply to the requesting server. */
1128 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1132 clients = silc_idlist_get_clients_by_hash(server->local_list,
1133 nick, server->md5hash,
1136 /* If we are router we will check our global list as well. */
1137 if (!clients && server->server_type == SILC_ROUTER) {
1138 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1142 clients = silc_idlist_get_clients_by_hash(server->global_list,
1143 nick, server->md5hash,
1148 /* Such a client really does not exist in the SILC network. */
1149 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1150 SILC_STATUS_ERR_NO_SUCH_NICK,
1151 3, nick, strlen(nick));
1155 /* Send the command reply to the client */
1156 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1164 silc_free(server_name);
1169 /* Server side of command WHOWAS. */
1171 SILC_SERVER_CMD_FUNC(whowas)
1173 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1176 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1178 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1179 ret = silc_server_command_whowas_from_client(cmd);
1180 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
1181 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1182 ret = silc_server_command_whowas_from_server(cmd);
1185 silc_server_command_free(cmd);
1188 /******************************************************************************
1192 ******************************************************************************/
1194 /* Checks that all mandatory fields are present. If not then send WHOIS
1195 request to the server who owns the client. We use WHOIS because we want
1196 to get as much information as possible at once. */
1199 silc_server_command_identify_check(SilcServerCommandContext cmd,
1200 SilcClientEntry *clients,
1201 unsigned int clients_count)
1203 SilcServer server = cmd->server;
1205 SilcClientEntry entry;
1207 for (i = 0; i < clients_count; i++) {
1210 if (!entry->nickname) {
1212 unsigned short old_ident;
1217 old_ident = silc_command_get_ident(cmd->payload);
1218 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1219 silc_command_set_command(cmd->payload, SILC_COMMAND_WHOIS);
1220 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1222 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1223 now anyway so make it a good one. */
1224 silc_server_packet_send(server, entry->router->connection,
1225 SILC_PACKET_COMMAND, cmd->packet->flags,
1226 tmpbuf->data, tmpbuf->len, TRUE);
1228 /* Reprocess this packet after received reply */
1229 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1230 silc_command_get_ident(cmd->payload),
1231 silc_server_command_destructor,
1232 silc_server_command_identify,
1233 silc_server_command_dup(cmd));
1235 cmd->pending = TRUE;
1237 /* Put old data back to the Command Payload we just changed */
1238 silc_command_set_ident(cmd->payload, old_ident);
1239 silc_command_set_command(cmd->payload, SILC_COMMAND_IDENTIFY);
1241 silc_buffer_free(tmpbuf);
1250 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1251 SilcClientEntry *clients,
1252 unsigned int clients_count)
1254 SilcServer server = cmd->server;
1256 int i, count = 0, len;
1257 SilcBuffer packet, idp;
1258 SilcClientEntry entry;
1259 SilcCommandStatus status;
1260 unsigned short ident = silc_command_get_ident(cmd->payload);
1262 status = SILC_STATUS_OK;
1263 if (clients_count > 1)
1264 status = SILC_STATUS_LIST_START;
1266 for (i = 0; i < clients_count; i++) {
1269 if (entry->connection && entry->data.registered == FALSE) {
1270 if (clients_count == 1)
1271 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1272 SILC_STATUS_ERR_NO_SUCH_NICK,
1274 strlen(entry->nickname));
1278 if (count && i - 1 == count)
1281 if (clients_count > 2)
1282 status = SILC_STATUS_LIST_ITEM;
1284 if (clients_count > 1 && i == clients_count - 1)
1285 status = SILC_STATUS_LIST_END;
1287 /* Send IDENTIFY reply */
1288 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1289 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1293 char nh[256], uh[256];
1294 SilcSocketConnection hsock;
1296 memset(uh, 0, sizeof(uh));
1297 memset(nh, 0, sizeof(nh));
1299 strncat(nh, entry->nickname, strlen(entry->nickname));
1300 if (!strchr(entry->nickname, '@')) {
1301 strncat(nh, "@", 1);
1302 len = entry->router ? strlen(entry->router->server_name) :
1303 strlen(server->server_name);
1304 strncat(nh, entry->router ? entry->router->server_name :
1305 server->server_name, len);
1308 if (!entry->username) {
1309 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1311 2, idp->data, idp->len,
1314 strncat(uh, entry->username, strlen(entry->username));
1315 if (!strchr(entry->username, '@')) {
1316 strncat(uh, "@", 1);
1317 hsock = (SilcSocketConnection)entry->connection;
1318 len = strlen(hsock->hostname);
1319 strncat(uh, hsock->hostname, len);
1322 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1324 2, idp->data, idp->len,
1329 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1330 0, packet->data, packet->len, FALSE);
1332 silc_buffer_free(packet);
1333 silc_buffer_free(idp);
1339 silc_server_command_identify_from_client(SilcServerCommandContext cmd)
1341 SilcServer server = cmd->server;
1342 char *nick = NULL, *server_name = NULL;
1343 int count = 0, clients_count = 0;
1344 SilcClientEntry *clients = NULL, entry;
1345 SilcClientID **client_id = NULL;
1346 unsigned int client_id_count = 0;
1349 /* Protocol dictates that we must always send the received IDENTIFY request
1350 to our router if we are normal server, so let's do it now unless we
1351 are standalone. We will not send any replies to the client until we
1352 have received reply from the router. */
1353 if (server->server_type == SILC_SERVER &&
1354 !cmd->pending && !server->standalone) {
1356 unsigned short old_ident;
1358 old_ident = silc_command_get_ident(cmd->payload);
1359 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1360 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1362 /* Send IDENTIFY command to our router */
1363 silc_server_packet_send(server, (SilcSocketConnection)
1364 server->router->connection,
1365 SILC_PACKET_COMMAND, cmd->packet->flags,
1366 tmpbuf->data, tmpbuf->len, TRUE);
1368 /* Reprocess this packet after received reply from router */
1369 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1370 silc_command_get_ident(cmd->payload),
1371 silc_server_command_destructor,
1372 silc_server_command_identify,
1373 silc_server_command_dup(cmd));
1374 cmd->pending = TRUE;
1376 silc_command_set_ident(cmd->payload, old_ident);
1378 silc_buffer_free(tmpbuf);
1383 /* We are ready to process the command request. Let's search for the
1384 requested client and send reply to the requesting client. */
1386 /* Parse the IDENTIFY request */
1387 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1388 &nick, &server_name, &count,
1389 SILC_COMMAND_IDENTIFY))
1392 /* Get all clients matching that ID or nickname from local list */
1393 if (client_id_count) {
1394 /* Check all Client ID's received in the command packet */
1395 for (i = 0; i < client_id_count; i++) {
1396 entry = silc_idlist_find_client_by_id(server->local_list,
1397 client_id[i], NULL);
1399 clients = silc_realloc(clients, sizeof(*clients) *
1400 (clients_count + 1));
1401 clients[clients_count++] = entry;
1405 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1409 clients = silc_idlist_get_clients_by_hash(server->local_list,
1410 nick, server->md5hash,
1414 /* Check global list as well */
1416 if (client_id_count) {
1417 /* Check all Client ID's received in the command packet */
1418 for (i = 0; i < client_id_count; i++) {
1419 entry = silc_idlist_find_client_by_id(server->global_list,
1420 client_id[i], NULL);
1422 clients = silc_realloc(clients, sizeof(*clients) *
1423 (clients_count + 1));
1424 clients[clients_count++] = entry;
1428 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1432 clients = silc_idlist_get_clients_by_hash(server->global_list,
1433 nick, server->md5hash,
1439 /* Such a client really does not exist in the SILC network. */
1440 if (!client_id_count) {
1441 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1442 SILC_STATUS_ERR_NO_SUCH_NICK,
1443 3, nick, strlen(nick));
1445 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1446 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1447 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1448 2, idp->data, idp->len);
1449 silc_buffer_free(idp);
1454 /* Check that all mandatory fields are present and request those data
1455 from the server who owns the client if necessary. */
1456 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1461 /* Send the command reply to the client */
1462 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1465 if (client_id_count) {
1466 for (i = 0; i < client_id_count; i++)
1467 silc_free(client_id[i]);
1468 silc_free(client_id);
1475 silc_free(server_name);
1481 silc_server_command_identify_from_server(SilcServerCommandContext cmd)
1483 SilcServer server = cmd->server;
1484 char *nick = NULL, *server_name = NULL;
1485 int count = 0, clients_count = 0;
1486 SilcClientEntry *clients = NULL, entry;
1487 SilcClientID **client_id = NULL;
1488 unsigned int client_id_count = 0;
1491 /* Parse the IDENTIFY request */
1492 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1493 &nick, &server_name, &count,
1494 SILC_COMMAND_IDENTIFY))
1497 /* Process the command request. Let's search for the requested client and
1498 send reply to the requesting server. */
1500 if (client_id_count) {
1501 /* Check all Client ID's received in the command packet */
1502 for (i = 0; i < client_id_count; i++) {
1503 entry = silc_idlist_find_client_by_id(server->local_list,
1504 client_id[i], NULL);
1506 clients = silc_realloc(clients, sizeof(*clients) *
1507 (clients_count + 1));
1508 clients[clients_count++] = entry;
1512 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1516 clients = silc_idlist_get_clients_by_hash(server->local_list,
1517 nick, server->md5hash,
1521 /* If we are router we will check our global list as well. */
1522 if (!clients && server->server_type == SILC_ROUTER) {
1523 if (client_id_count) {
1524 /* Check all Client ID's received in the command packet */
1525 for (i = 0; i < client_id_count; i++) {
1526 entry = silc_idlist_find_client_by_id(server->global_list,
1527 client_id[i], NULL);
1529 clients = silc_realloc(clients, sizeof(*clients) *
1530 (clients_count + 1));
1531 clients[clients_count++] = entry;
1535 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1539 clients = silc_idlist_get_clients_by_hash(server->global_list,
1540 nick, server->md5hash,
1546 /* Such a client really does not exist in the SILC network. */
1547 if (!client_id_count) {
1548 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1549 SILC_STATUS_ERR_NO_SUCH_NICK,
1550 3, nick, strlen(nick));
1552 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1553 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1554 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1555 2, idp->data, idp->len);
1556 silc_buffer_free(idp);
1561 /* Check that all mandatory fields are present and request those data
1562 from the server who owns the client if necessary. */
1563 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1568 /* Send the command reply */
1569 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1572 if (client_id_count) {
1573 for (i = 0; i < client_id_count; i++)
1574 silc_free(client_id[i]);
1575 silc_free(client_id);
1582 silc_free(server_name);
1587 SILC_SERVER_CMD_FUNC(identify)
1589 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1592 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1594 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1595 ret = silc_server_command_identify_from_client(cmd);
1596 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) |
1597 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1598 ret = silc_server_command_identify_from_server(cmd);
1601 silc_server_command_free(cmd);
1604 /* Checks string for bad characters and returns TRUE if they are found. */
1606 static int silc_server_command_bad_chars(char *nick)
1608 if (strchr(nick, '\\')) return TRUE;
1609 if (strchr(nick, '\"')) return TRUE;
1610 if (strchr(nick, '´')) return TRUE;
1611 if (strchr(nick, '`')) return TRUE;
1612 if (strchr(nick, '\'')) return TRUE;
1613 if (strchr(nick, '*')) return TRUE;
1614 if (strchr(nick, '/')) return TRUE;
1615 if (strchr(nick, '@')) return TRUE;
1620 /* Server side of command NICK. Sets nickname for user. Setting
1621 nickname causes generation of a new client ID for the client. The
1622 new client ID is sent to the client after changing the nickname. */
1624 SILC_SERVER_CMD_FUNC(nick)
1626 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1627 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1628 SilcServer server = cmd->server;
1629 SilcBuffer packet, nidp, oidp;
1630 SilcClientID *new_id;
1633 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1636 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NICK, cmd, 1, 1);
1638 /* Check nickname */
1639 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1640 if (silc_server_command_bad_chars(nick) == TRUE) {
1641 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1642 SILC_STATUS_ERR_BAD_NICKNAME);
1646 if (strlen(nick) > 128)
1649 /* Create new Client ID */
1650 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
1651 cmd->server->md5hash, nick,
1654 /* Send notify about nickname change to our router. We send the new
1655 ID and ask to replace it with the old one. If we are router the
1656 packet is broadcasted. Send NICK_CHANGE notify. */
1657 if (!server->standalone)
1658 silc_server_send_notify_nick_change(server, server->router->connection,
1659 server->server_type == SILC_SERVER ?
1660 FALSE : TRUE, client->id,
1661 new_id, SILC_ID_CLIENT_LEN);
1663 /* Remove old cache entry */
1664 silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
1667 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1671 memset(client->id, 0, SILC_ID_CLIENT_LEN);
1672 silc_free(client->id);
1675 /* Save the nickname as this client is our local client */
1676 if (client->nickname)
1677 silc_free(client->nickname);
1679 client->nickname = strdup(nick);
1680 client->id = new_id;
1682 /* Update client cache */
1683 silc_idcache_add(server->local_list->clients, client->nickname,
1684 SILC_ID_CLIENT, client->id, (void *)client, TRUE, FALSE);
1686 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1688 /* Send NICK_CHANGE notify to the client's channels */
1689 silc_server_send_notify_on_channels(server, client,
1690 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1691 oidp->data, oidp->len,
1692 nidp->data, nidp->len);
1694 /* Send the new Client ID as reply command back to client */
1695 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
1696 SILC_STATUS_OK, 0, 1,
1697 2, nidp->data, nidp->len);
1698 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1699 0, packet->data, packet->len, FALSE);
1701 silc_buffer_free(packet);
1702 silc_buffer_free(nidp);
1703 silc_buffer_free(oidp);
1706 silc_server_command_free(cmd);
1709 SILC_SERVER_CMD_FUNC(list)
1713 /* Server side of TOPIC command. Sets topic for channel and/or returns
1714 current topic to client. */
1716 SILC_SERVER_CMD_FUNC(topic)
1718 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1719 SilcServer server = cmd->server;
1720 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1721 SilcChannelID *channel_id;
1722 SilcChannelEntry channel;
1723 SilcChannelClientEntry chl;
1724 SilcBuffer packet, idp;
1726 unsigned int argc, tmp_len;
1728 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
1730 argc = silc_argument_get_arg_num(cmd->args);
1732 /* Get Channel ID */
1733 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1735 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1736 SILC_STATUS_ERR_NO_CHANNEL_ID);
1739 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1741 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1742 SILC_STATUS_ERR_NO_CHANNEL_ID);
1746 /* Check whether the channel exists */
1747 channel = silc_idlist_find_channel_by_id(server->local_list,
1750 channel = silc_idlist_find_channel_by_id(server->global_list,
1753 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1754 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1761 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1763 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1764 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1768 if (strlen(tmp) > 256) {
1769 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1770 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1774 /* See whether has rights to change topic */
1775 silc_list_start(channel->user_list);
1776 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1777 if (chl->client == client)
1780 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1781 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
1782 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1783 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1788 /* Set the topic for channel */
1790 silc_free(channel->topic);
1791 channel->topic = strdup(tmp);
1793 /* Send TOPIC_SET notify type to the network */
1794 if (!server->standalone)
1795 silc_server_send_notify_topic_set(server, server->router->connection,
1796 server->server_type == SILC_ROUTER ?
1797 TRUE : FALSE, channel, client->id,
1798 SILC_ID_CLIENT_LEN, channel->topic);
1800 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1802 /* Send notify about topic change to all clients on the channel */
1803 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
1804 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
1805 idp->data, idp->len,
1806 channel->topic, strlen(channel->topic));
1807 silc_buffer_free(idp);
1810 /* Send the topic to client as reply packet */
1811 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1813 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1814 SILC_STATUS_OK, 0, 2,
1815 2, idp->data, idp->len,
1817 strlen(channel->topic));
1819 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1820 SILC_STATUS_OK, 0, 1,
1821 2, idp->data, idp->len);
1822 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1823 0, packet->data, packet->len, FALSE);
1825 silc_buffer_free(packet);
1826 silc_buffer_free(idp);
1827 silc_free(channel_id);
1830 silc_server_command_free(cmd);
1833 /* Server side of INVITE command. Invites some client to join some channel. */
1835 SILC_SERVER_CMD_FUNC(invite)
1837 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1838 SilcServer server = cmd->server;
1839 SilcSocketConnection sock = cmd->sock, dest_sock;
1840 SilcClientEntry sender, dest;
1841 SilcClientID *dest_id;
1842 SilcChannelEntry channel;
1843 SilcChannelID *channel_id;
1848 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 2);
1850 /* Get destination ID */
1851 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1853 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1854 SILC_STATUS_ERR_NO_CLIENT_ID);
1857 dest_id = silc_id_payload_parse_id(tmp, len);
1859 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1860 SILC_STATUS_ERR_NO_CLIENT_ID);
1864 /* Get Channel ID */
1865 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1867 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1868 SILC_STATUS_ERR_NO_CHANNEL_ID);
1871 channel_id = silc_id_payload_parse_id(tmp, len);
1873 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1874 SILC_STATUS_ERR_NO_CHANNEL_ID);
1878 /* Check whether the channel exists */
1879 channel = silc_idlist_find_channel_by_id(server->local_list,
1882 channel = silc_idlist_find_channel_by_id(server->global_list,
1885 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1886 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1891 /* Check whether the sender of this command is on the channel. */
1892 sender = (SilcClientEntry)sock->user_data;
1893 if (!silc_server_client_on_channel(sender, channel)) {
1894 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1895 SILC_STATUS_ERR_NOT_ON_CHANNEL);
1899 /* Check whether the channel is invite-only channel. If yes then the
1900 sender of this command must be at least channel operator. */
1901 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1902 SilcChannelClientEntry chl;
1904 silc_list_start(channel->user_list);
1905 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1906 if (chl->client == sender) {
1907 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1908 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1909 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1916 /* Find the connection data for the destination. If it is local we will
1917 send it directly otherwise we will send it to router for routing. */
1918 dest = silc_idlist_find_client_by_id(server->local_list, dest_id, NULL);
1920 dest_sock = (SilcSocketConnection)dest->connection;
1922 dest_sock = silc_server_route_get(server, dest_id, SILC_ID_CLIENT);
1924 /* Check whether the requested client is already on the channel. */
1925 /* XXX if we are normal server we don't know about global clients on
1926 the channel thus we must request it (USERS command), check from
1927 local cache as well. */
1928 if (silc_server_client_on_channel(dest, channel)) {
1929 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1930 SILC_STATUS_ERR_USER_ON_CHANNEL);
1934 sidp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1936 /* Send notify to the client that is invited to the channel */
1937 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
1939 SILC_NOTIFY_TYPE_INVITE, 2,
1940 sidp->data, sidp->len, tmp, len);
1942 /* Send command reply */
1943 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1946 silc_buffer_free(sidp);
1949 silc_server_command_free(cmd);
1954 SilcSocketConnection sock;
1958 /* Quits connection to client. This gets called if client won't
1959 close the connection even when it has issued QUIT command. */
1961 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
1963 QuitInternal q = (QuitInternal)context;
1965 /* Free all client specific data, such as client entry and entires
1966 on channels this client may be on. */
1967 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
1969 q->sock->user_data = NULL;
1971 /* Close the connection on our side */
1972 silc_server_close_connection(q->server, q->sock);
1974 silc_free(q->signoff);
1978 /* Quits SILC session. This is the normal way to disconnect client. */
1980 SILC_SERVER_CMD_FUNC(quit)
1982 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1983 SilcServer server = cmd->server;
1984 SilcSocketConnection sock = cmd->sock;
1986 unsigned char *tmp = NULL;
1987 unsigned int len = 0;
1989 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_QUIT, cmd, 0, 1);
1991 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1994 /* Get destination ID */
1995 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1999 q = silc_calloc(1, sizeof(*q));
2002 q->signoff = tmp ? strdup(tmp) : NULL;
2004 /* We quit the connection with little timeout */
2005 silc_task_register(server->timeout_queue, sock->sock,
2006 silc_server_command_quit_cb, (void *)q,
2007 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2010 silc_server_command_free(cmd);
2013 SILC_SERVER_CMD_FUNC(kill)
2017 /* Server side of command INFO. This sends information about us to
2018 the client. If client requested specific server we will send the
2019 command to that server. */
2021 SILC_SERVER_CMD_FUNC(info)
2023 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2024 SilcServer server = cmd->server;
2025 SilcBuffer packet, idp;
2026 char info_string[256], *dest_server;
2028 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 1);
2030 /* Get server name */
2031 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2033 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2034 SILC_STATUS_ERR_NO_SUCH_SERVER);
2038 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
2039 /* Send our reply */
2040 memset(info_string, 0, sizeof(info_string));
2041 snprintf(info_string, sizeof(info_string),
2042 "location: %s server: %s admin: %s <%s>",
2043 server->config->admin_info->location,
2044 server->config->admin_info->server_type,
2045 server->config->admin_info->admin_name,
2046 server->config->admin_info->admin_email);
2048 idp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
2050 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2051 SILC_STATUS_OK, 0, 2,
2052 2, idp->data, idp->len,
2054 strlen(info_string));
2055 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2056 packet->data, packet->len, FALSE);
2058 silc_buffer_free(packet);
2059 silc_buffer_free(idp);
2061 /* Send this command to the requested server */
2063 if (server->server_type == SILC_SERVER && !server->standalone) {
2067 if (server->server_type == SILC_ROUTER) {
2073 silc_server_command_free(cmd);
2076 /* Server side of command PING. This just replies to the ping. */
2078 SILC_SERVER_CMD_FUNC(ping)
2080 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2081 SilcServer server = cmd->server;
2086 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
2089 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2091 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2092 SILC_STATUS_ERR_NO_SERVER_ID);
2095 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2099 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
2100 /* Send our reply */
2101 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2104 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2105 SILC_STATUS_ERR_NO_SUCH_SERVER);
2112 silc_server_command_free(cmd);
2115 /* Internal routine to join channel. The channel sent to this function
2116 has been either created or resolved from ID lists. This joins the sent
2117 client to the channel. */
2119 static void silc_server_command_join_channel(SilcServer server,
2120 SilcServerCommandContext cmd,
2121 SilcChannelEntry channel,
2122 SilcClientID *client_id,
2126 SilcSocketConnection sock = cmd->sock;
2128 unsigned int tmp_len, user_count;
2129 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
2130 SilcClientEntry client;
2131 SilcChannelClientEntry chl;
2132 SilcBuffer reply, chidp, clidp, keyp, user_list, mode_list;
2133 unsigned short ident = silc_command_get_ident(cmd->payload);
2135 SILC_LOG_DEBUG(("Start"));
2140 /* Get passphrase */
2141 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2143 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
2144 memcpy(passphrase, tmp, tmp_len);
2148 * Check channel modes
2151 /* Check invite list if channel is invite-only channel */
2152 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2153 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
2154 /* Invite list is specified. Check whether client is invited in the
2155 list. If not, then check whether it has been invited otherwise. */
2158 /* XXX client must be invited to be able to join the channel */
2162 /* Check ban list if set */
2163 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2167 /* Check the channel passphrase if set. */
2168 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2169 if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
2170 strlen(channel->mode_data.passphrase))) {
2171 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2172 SILC_STATUS_ERR_BAD_PASSWORD);
2177 /* Check user count limit if set. */
2178 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
2179 if (silc_list_count(channel->user_list) + 1 >
2180 channel->mode_data.user_limit) {
2181 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2182 SILC_STATUS_ERR_CHANNEL_IS_FULL);
2188 * Client is allowed to join to the channel. Make it happen.
2191 /* Get the client entry */
2192 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2193 client = (SilcClientEntry)sock->user_data;
2195 client = silc_idlist_find_client_by_id(server->local_list, client_id,
2198 /* XXX actually this is useless since router finds always cell's
2199 local clients from its local lists. */
2200 client = silc_idlist_find_client_by_id(server->global_list, client_id,
2207 /* Check whether the client already is on the channel */
2208 if (silc_server_client_on_channel(client, channel)) {
2209 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2210 SILC_STATUS_ERR_USER_ON_CHANNEL);
2214 /* Generate new channel key as protocol dictates */
2215 if ((!created && silc_list_count(channel->user_list) > 0) ||
2216 !channel->channel_key)
2217 silc_server_create_channel_key(server, channel, 0);
2219 /* Send the channel key. This is broadcasted to the channel but is not
2220 sent to the client who is joining to the channel. */
2221 silc_server_send_channel_key(server, NULL, channel,
2222 server->server_type == SILC_ROUTER ?
2223 FALSE : !server->standalone);
2225 /* Join the client to the channel by adding it to channel's user list.
2226 Add also the channel to client entry's channels list for fast cross-
2228 chl = silc_calloc(1, sizeof(*chl));
2230 chl->client = client;
2231 chl->channel = channel;
2232 silc_list_add(channel->user_list, chl);
2233 silc_list_add(client->channels, chl);
2235 /* Get users on the channel */
2236 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
2239 /* Encode Client ID Payload of the original client who wants to join */
2240 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2242 /* Encode command reply packet */
2243 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2244 SILC_PUT32_MSB(channel->mode, mode);
2245 SILC_PUT32_MSB(created, tmp2);
2246 SILC_PUT32_MSB(user_count, tmp3);
2247 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
2248 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
2249 strlen(channel->channel_key->
2251 channel->channel_key->cipher->name,
2252 channel->key_len / 8, channel->key);
2254 if (!channel->topic) {
2256 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2257 SILC_STATUS_OK, ident, 9,
2258 2, channel->channel_name,
2259 strlen(channel->channel_name),
2260 3, chidp->data, chidp->len,
2261 4, clidp->data, clidp->len,
2264 7, keyp->data, keyp->len,
2266 13, user_list->data, user_list->len,
2267 14, mode_list->data,
2271 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2272 SILC_STATUS_OK, ident, 10,
2273 2, channel->channel_name,
2274 strlen(channel->channel_name),
2275 3, chidp->data, chidp->len,
2276 4, clidp->data, clidp->len,
2279 7, keyp->data, keyp->len,
2281 strlen(channel->topic),
2283 13, user_list->data, user_list->len,
2284 14, mode_list->data,
2288 /* Send command reply */
2289 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
2290 reply->data, reply->len, FALSE);
2292 if (!cmd->pending) {
2293 /* Send JOIN notify to locally connected clients on the channel */
2294 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2295 SILC_NOTIFY_TYPE_JOIN, 2,
2296 clidp->data, clidp->len,
2297 chidp->data, chidp->len);
2299 /* Send JOIN notify packet to our primary router */
2300 if (!server->standalone)
2301 silc_server_send_notify_join(server, server->router->connection,
2302 server->server_type == SILC_ROUTER ?
2303 TRUE : FALSE, channel, client->id,
2304 SILC_ID_CLIENT_LEN);
2307 silc_buffer_free(reply);
2308 silc_buffer_free(clidp);
2309 silc_buffer_free(chidp);
2310 silc_buffer_free(keyp);
2311 silc_buffer_free(user_list);
2312 silc_buffer_free(mode_list);
2316 silc_free(passphrase);
2319 /* Server side of command JOIN. Joins client into requested channel. If
2320 the channel does not exist it will be created. */
2322 SILC_SERVER_CMD_FUNC(join)
2324 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2325 SilcServer server = cmd->server;
2327 char *tmp, *channel_name = NULL, *cipher, *hmac;
2328 SilcChannelEntry channel;
2329 unsigned int umode = 0;
2330 int created = FALSE;
2331 SilcClientID *client_id;
2333 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
2335 /* Get channel name */
2336 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2338 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2339 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2344 if (strlen(channel_name) > 256)
2345 channel_name[255] = '\0';
2347 if (silc_server_command_bad_chars(channel_name) == TRUE) {
2348 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2349 SILC_STATUS_ERR_BAD_CHANNEL);
2350 silc_free(channel_name);
2354 /* Get Client ID of the client who is joining to the channel */
2355 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2357 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2358 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2361 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2363 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2364 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2368 /* Get cipher and hmac name */
2369 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2370 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2372 /* See if the channel exists */
2373 channel = silc_idlist_find_channel_by_name(server->local_list,
2374 channel_name, NULL);
2376 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2377 /* If this is coming from client the Client ID in the command packet must
2378 be same as the client's ID. */
2379 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2380 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2381 if (SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
2382 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2383 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2389 /* Channel not found */
2391 /* If we are standalone server we don't have a router, we just create
2392 the channel by ourselves. */
2393 if (server->standalone) {
2394 channel = silc_server_create_new_channel(server, server->id, cipher,
2395 hmac, channel_name, TRUE);
2396 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2401 /* The channel does not exist on our server. If we are normal server
2402 we will send JOIN command to our router which will handle the
2403 joining procedure (either creates the channel if it doesn't exist
2404 or joins the client to it). */
2405 if (server->server_type == SILC_SERVER) {
2407 unsigned short old_ident;
2409 old_ident = silc_command_get_ident(cmd->payload);
2410 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2411 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2413 /* Send JOIN command to our router */
2414 silc_server_packet_send(server, (SilcSocketConnection)
2415 server->router->connection,
2416 SILC_PACKET_COMMAND, cmd->packet->flags,
2417 tmpbuf->data, tmpbuf->len, TRUE);
2419 /* Reprocess this packet after received reply from router */
2420 silc_server_command_pending(server, SILC_COMMAND_JOIN,
2421 silc_command_get_ident(cmd->payload),
2422 silc_server_command_destructor,
2423 silc_server_command_join,
2424 silc_server_command_dup(cmd));
2425 cmd->pending = TRUE;
2429 /* We are router and the channel does not seem exist so we will check
2430 our global list as well for the channel. */
2431 channel = silc_idlist_find_channel_by_name(server->global_list,
2432 channel_name, NULL);
2434 /* Channel really does not exist, create it */
2435 channel = silc_server_create_new_channel(server, server->id, cipher,
2436 hmac, channel_name, TRUE);
2437 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2444 /* Channel not found */
2446 /* If the command came from router and/or we are normal server then
2447 something went wrong with the joining as the channel was not found.
2448 We can't do anything else but ignore this. */
2449 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
2450 server->server_type == SILC_SERVER)
2453 /* We are router and the channel does not seem exist so we will check
2454 our global list as well for the channel. */
2455 channel = silc_idlist_find_channel_by_name(server->global_list,
2456 channel_name, NULL);
2458 /* Channel really does not exist, create it */
2459 channel = silc_server_create_new_channel(server, server->id, cipher,
2460 hmac, channel_name, TRUE);
2461 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2467 /* If the channel does not have global users and is also empty it means the
2468 channel was created globally (by our router) and the client will be the
2469 channel founder and operator. */
2470 if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
2471 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2472 created = TRUE; /* Created globally by our router */
2475 /* Join to the channel */
2476 silc_server_command_join_channel(server, cmd, channel, client_id,
2479 silc_free(client_id);
2482 silc_server_command_free(cmd);
2485 /* Server side of command MOTD. Sends server's current "message of the
2486 day" to the client. */
2488 SILC_SERVER_CMD_FUNC(motd)
2490 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2491 SilcServer server = cmd->server;
2495 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 2);
2497 /* XXX show currently only our motd */
2499 if (server->config && server->config->motd &&
2500 server->config->motd->motd_file) {
2503 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
2508 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2514 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2519 silc_server_command_free(cmd);
2522 SILC_SERVER_CMD_FUNC(umode)
2526 /* Checks that client has rights to add or remove channel modes. If any
2527 of the checks fails FALSE is returned. */
2529 int silc_server_check_cmode_rights(SilcChannelEntry channel,
2530 SilcChannelClientEntry client,
2533 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
2534 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
2536 /* Check whether has rights to change anything */
2537 if (!is_op && !is_fo)
2540 /* Check whether has rights to change everything */
2544 /* We know that client is channel operator, check that they are not
2545 changing anything that requires channel founder rights. Rest of the
2546 modes are available automatically for channel operator. */
2548 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
2549 if (is_op && !is_fo)
2552 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2553 if (is_op && !is_fo)
2558 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2559 if (is_op && !is_fo)
2562 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2563 if (is_op && !is_fo)
2568 if (mode & SILC_CHANNEL_MODE_CIPHER) {
2569 if (is_op && !is_fo)
2572 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2573 if (is_op && !is_fo)
2581 /* Server side command of CMODE. Changes channel mode */
2583 SILC_SERVER_CMD_FUNC(cmode)
2585 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2586 SilcServer server = cmd->server;
2587 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2588 SilcChannelID *channel_id;
2589 SilcChannelEntry channel;
2590 SilcChannelClientEntry chl;
2591 SilcBuffer packet, cidp;
2592 unsigned char *tmp, *tmp_id, *tmp_mask;
2593 unsigned int argc, mode_mask, tmp_len, tmp_len2;
2595 SILC_LOG_DEBUG(("Start"));
2597 argc = silc_argument_get_arg_num(cmd->args);
2599 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2600 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2604 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2605 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2609 /* Get Channel ID */
2610 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2612 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2613 SILC_STATUS_ERR_NO_CHANNEL_ID);
2616 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
2618 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2619 SILC_STATUS_ERR_NO_CHANNEL_ID);
2623 /* Get the channel mode mask */
2624 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2626 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2627 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2630 SILC_GET32_MSB(mode_mask, tmp_mask);
2632 /* Get channel entry */
2633 channel = silc_idlist_find_channel_by_id(server->local_list,
2636 channel = silc_idlist_find_channel_by_id(server->global_list,
2639 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2640 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2645 /* Check whether this client is on the channel */
2646 if (!silc_server_client_on_channel(client, channel)) {
2647 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2648 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2652 /* Get entry to the channel user list */
2653 silc_list_start(channel->user_list);
2654 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2655 if (chl->client == client)
2658 /* Check that client has rights to change any requested channel modes */
2659 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
2660 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2661 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2666 * Check the modes. Modes that requires nothing special operation are
2670 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2671 /* Channel uses private keys to protect traffic. Client(s) has set the
2672 key locally they want to use, server does not know that key. */
2673 /* Nothing interesting to do here now */
2675 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2676 /* The mode is removed and we need to generate and distribute
2677 new channel key. Clients are not using private channel keys
2678 anymore after this. */
2680 /* XXX Duplicated code, make own function for this!! LEAVE uses this
2683 /* Re-generate channel key */
2684 silc_server_create_channel_key(server, channel, 0);
2686 /* Encode channel key payload to be distributed on the channel */
2688 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2689 strlen(channel->channel_key->
2691 channel->channel_key->cipher->name,
2692 channel->key_len / 8, channel->key);
2694 /* If we are normal server then we will send it to our router. If we
2695 are router we will send it to all local servers that has clients on
2697 if (server->server_type == SILC_SERVER) {
2698 if (!server->standalone)
2699 silc_server_packet_send(server,
2700 cmd->server->router->connection,
2701 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2707 /* Send to locally connected clients on the channel */
2708 silc_server_packet_send_local_channel(server, channel,
2709 SILC_PACKET_CHANNEL_KEY, 0,
2710 packet->data, packet->len, FALSE);
2711 silc_buffer_free(packet);
2715 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2716 /* User limit is set on channel */
2717 unsigned int user_limit;
2719 /* Get user limit */
2720 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2722 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2723 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2724 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2728 SILC_GET32_MSB(user_limit, tmp);
2729 channel->mode_data.user_limit = user_limit;
2732 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2733 /* User limit mode is unset. Remove user limit */
2734 channel->mode_data.user_limit = 0;
2737 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
2738 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
2739 /* Passphrase has been set to channel */
2741 /* Get the passphrase */
2742 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
2744 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2745 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2749 /* Save the passphrase */
2750 channel->mode_data.passphrase = strdup(tmp);
2753 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2754 /* Passphrase mode is unset. remove the passphrase */
2755 if (channel->mode_data.passphrase) {
2756 silc_free(channel->mode_data.passphrase);
2757 channel->mode_data.passphrase = NULL;
2762 if (mode_mask & SILC_CHANNEL_MODE_BAN) {
2763 if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
2764 /* Ban list is specified for channel */
2767 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
2769 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2770 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2774 /* XXX check that channel founder is not banned */
2776 /* Save the ban list */
2777 channel->mode_data.ban_list = strdup(tmp);
2780 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2781 /* Ban mode is unset. Remove the entire ban list */
2782 if (channel->mode_data.ban_list) {
2783 silc_free(channel->mode_data.ban_list);
2784 channel->mode_data.ban_list = NULL;
2789 if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
2790 if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
2791 /* Invite list is specified for channel */
2793 /* Get invite list */
2794 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
2796 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2797 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2801 /* Save the invite linst */
2802 channel->mode_data.invite_list = strdup(tmp);
2805 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
2806 /* Invite list mode is unset. Remove the entire invite list */
2807 if (channel->mode_data.invite_list) {
2808 silc_free(channel->mode_data.invite_list);
2809 channel->mode_data.invite_list = NULL;
2814 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
2815 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
2816 /* Cipher to use protect the traffic */
2817 unsigned int key_len;
2820 tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
2822 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2823 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2827 /* XXX Duplicated code, make own function for this!! */
2829 /* Delete old cipher and allocate the new one */
2830 silc_cipher_free(channel->channel_key);
2831 if (!silc_cipher_alloc(tmp, &channel->channel_key)) {
2832 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2833 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
2836 key_len = silc_cipher_get_key_len(channel->channel_key) / 8;
2838 /* Re-generate channel key */
2839 silc_server_create_channel_key(server, channel, key_len);
2841 /* Encode channel key payload to be distributed on the channel */
2843 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2844 strlen(channel->channel_key->
2846 channel->channel_key->cipher->name,
2847 channel->key_len / 8, channel->key);
2849 /* If we are normal server then we will send it to our router. If we
2850 are router we will send it to all local servers that has clients on
2852 if (server->server_type == SILC_SERVER) {
2853 if (!server->standalone)
2854 silc_server_packet_send(server,
2855 cmd->server->router->connection,
2856 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2862 /* Send to locally connected clients on the channel */
2863 silc_server_packet_send_local_channel(server, channel,
2864 SILC_PACKET_CHANNEL_KEY, 0,
2865 packet->data, packet->len, FALSE);
2866 silc_buffer_free(packet);
2869 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2870 /* Cipher mode is unset. Remove the cipher and revert back to
2873 if (channel->mode_data.cipher) {
2874 silc_free(channel->mode_data.cipher);
2875 channel->mode_data.cipher = NULL;
2876 channel->mode_data.key_len = 0;
2879 /* Generate new cipher and key for the channel */
2881 /* XXX Duplicated code, make own function for this!! */
2883 /* Delete old cipher and allocate default one */
2884 silc_cipher_free(channel->channel_key);
2885 if (!channel->cipher)
2886 silc_cipher_alloc("aes-256-cbc", &channel->channel_key);
2888 if (!silc_cipher_alloc(channel->cipher, &channel->channel_key)) {
2889 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2890 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
2895 /* Re-generate channel key */
2896 silc_server_create_channel_key(server, channel, 0);
2898 /* Encode channel key payload to be distributed on the channel */
2900 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2901 strlen(channel->channel_key->
2903 channel->channel_key->cipher->name,
2904 channel->key_len / 8, channel->key);
2906 /* If we are normal server then we will send it to our router. If we
2907 are router we will send it to all local servers that has clients on
2909 if (server->server_type == SILC_SERVER) {
2910 if (!server->standalone)
2911 silc_server_packet_send(server,
2912 cmd->server->router->connection,
2913 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2919 /* Send to locally connected clients on the channel */
2920 silc_server_packet_send_local_channel(server, channel,
2921 SILC_PACKET_CHANNEL_KEY, 0,
2922 packet->data, packet->len, FALSE);
2923 silc_buffer_free(packet);
2927 /* Finally, set the mode */
2928 channel->mode = mode_mask;
2930 /* Send CMODE_CHANGE notify */
2931 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2932 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2933 SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
2934 cidp->data, cidp->len,
2937 /* Set CMODE notify type to network */
2938 if (!server->standalone)
2939 silc_server_send_notify_cmode(server, server->router->connection,
2940 server->server_type == SILC_ROUTER ?
2941 TRUE : FALSE, channel,
2942 mode_mask, client->id, SILC_ID_CLIENT_LEN);
2944 /* Send command reply to sender */
2945 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2946 SILC_STATUS_OK, 0, 1,
2948 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2949 packet->data, packet->len, FALSE);
2951 silc_buffer_free(packet);
2952 silc_free(channel_id);
2956 silc_server_command_free(cmd);
2959 /* Server side of CUMODE command. Changes client's mode on a channel. */
2961 SILC_SERVER_CMD_FUNC(cumode)
2963 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2964 SilcServer server = cmd->server;
2965 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2966 SilcChannelID *channel_id;
2967 SilcClientID *client_id;
2968 SilcChannelEntry channel;
2969 SilcClientEntry target_client;
2970 SilcChannelClientEntry chl;
2971 SilcBuffer packet, idp;
2972 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
2973 unsigned int target_mask, sender_mask, tmp_len, tmp_ch_len;
2976 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 3);
2978 /* Get Channel ID */
2979 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
2981 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2982 SILC_STATUS_ERR_NO_CHANNEL_ID);
2985 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
2987 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2988 SILC_STATUS_ERR_NO_CHANNEL_ID);
2992 /* Get channel entry */
2993 channel = silc_idlist_find_channel_by_id(server->local_list,
2996 channel = silc_idlist_find_channel_by_id(server->global_list,
2999 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3000 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3005 /* Check whether sender is on the channel */
3006 if (!silc_server_client_on_channel(client, channel)) {
3007 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3008 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3012 /* Check that client has rights to change other's rights */
3013 silc_list_start(channel->user_list);
3014 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3015 if (chl->client == client) {
3016 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
3017 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3018 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3019 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3023 sender_mask = chl->mode;
3028 /* Get the target client's channel mode mask */
3029 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3031 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3032 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3035 SILC_GET32_MSB(target_mask, tmp_mask);
3037 /* Get target Client ID */
3038 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3040 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3041 SILC_STATUS_ERR_NO_CLIENT_ID);
3044 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
3046 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3047 SILC_STATUS_ERR_NO_CLIENT_ID);
3051 /* Get target client's entry */
3052 target_client = silc_idlist_find_client_by_id(server->local_list,
3054 if (!target_client) {
3055 target_client = silc_idlist_find_client_by_id(server->global_list,
3059 /* Check whether target client is on the channel */
3060 if (!silc_server_client_on_channel(target_client, channel)) {
3061 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3062 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
3066 /* Get entry to the channel user list */
3067 silc_list_start(channel->user_list);
3068 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
3069 if (chl->client == target_client)
3076 /* If the target client is founder, no one else can change their mode
3078 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
3079 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3080 SILC_STATUS_ERR_NOT_YOU);
3084 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
3085 /* Cannot promote anyone to channel founder */
3086 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3087 SILC_STATUS_ERR_NOT_YOU);
3090 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3091 if (target_client == client) {
3092 /* Remove channel founder rights from itself */
3093 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3096 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3097 SILC_STATUS_ERR_NOT_YOU);
3103 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
3104 /* Promote to operator */
3105 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3106 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
3110 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
3111 /* Demote to normal user */
3112 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
3117 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3119 /* Send notify to channel, notify only if mode was actually changed. */
3121 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3122 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3123 idp->data, idp->len,
3127 /* Set CUMODE notify type to network */
3128 if (!server->standalone)
3129 silc_server_send_notify_cumode(server, server->router->connection,
3130 server->server_type == SILC_ROUTER ?
3131 TRUE : FALSE, channel,
3132 target_mask, client->id,
3135 SILC_ID_CLIENT_LEN);
3138 /* Send command reply to sender */
3139 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
3140 SILC_STATUS_OK, 0, 2,
3142 3, tmp_id, tmp_len);
3143 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3144 packet->data, packet->len, FALSE);
3146 silc_buffer_free(packet);
3147 silc_free(channel_id);
3148 silc_free(client_id);
3149 silc_buffer_free(idp);
3152 silc_server_command_free(cmd);
3155 /* Server side of KICK command. Kicks client out of channel. */
3157 SILC_SERVER_CMD_FUNC(kick)
3159 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3160 SilcServer server = cmd->server;
3161 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3162 SilcClientEntry target_client;
3163 SilcChannelID *channel_id;
3164 SilcClientID *client_id;
3165 SilcChannelEntry channel;
3166 SilcChannelClientEntry chl;
3168 unsigned int tmp_len;
3169 unsigned char *tmp, *comment;
3171 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 3);
3173 /* Get Channel ID */
3174 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3176 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3177 SILC_STATUS_ERR_NO_CHANNEL_ID);
3180 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
3182 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3183 SILC_STATUS_ERR_NO_CHANNEL_ID);
3187 /* Get channel entry */
3188 channel = silc_idlist_find_channel_by_id(server->local_list,
3191 channel = silc_idlist_find_channel_by_id(server->local_list,
3194 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3195 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3200 /* Check whether sender is on the channel */
3201 if (!silc_server_client_on_channel(client, channel)) {
3202 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3203 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3207 /* Check that the kicker is channel operator or channel founder */
3208 silc_list_start(channel->user_list);
3209 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3210 if (chl->client == client) {
3211 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
3212 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3213 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3220 /* Get target Client ID */
3221 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3223 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3224 SILC_STATUS_ERR_NO_CLIENT_ID);
3227 client_id = silc_id_payload_parse_id(tmp, tmp_len);
3229 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3230 SILC_STATUS_ERR_NO_CLIENT_ID);
3234 /* Get target client's entry */
3235 target_client = silc_idlist_find_client_by_id(server->local_list,
3237 if (!target_client) {
3238 target_client = silc_idlist_find_client_by_id(server->global_list,
3242 /* Check that the target client is not channel founder. Channel founder
3243 cannot be kicked from the channel. */
3244 silc_list_start(channel->user_list);
3245 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3246 if (chl->client == target_client) {
3247 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3248 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3249 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
3256 /* Check whether target client is on the channel */
3257 if (!silc_server_client_on_channel(target_client, channel)) {
3258 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3259 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
3265 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3269 /* Send command reply to sender */
3270 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3273 /* Send KICKED notify to local clients on the channel */
3274 idp = silc_id_payload_encode(target_client->id, SILC_ID_CLIENT);
3275 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3276 SILC_NOTIFY_TYPE_KICKED,
3278 idp->data, idp->len,
3279 comment, comment ? strlen(comment) : 0);
3280 silc_buffer_free(idp);
3282 /* Remove the client from the channel. If the channel does not exist
3283 after removing the client then the client kicked itself off the channel
3284 and we don't have to send anything after that. */
3285 if (!silc_server_remove_from_one_channel(server, NULL, channel,
3286 target_client, FALSE))
3289 /* Send KICKED notify to primary route */
3290 if (!server->standalone)
3291 silc_server_send_notify_kicked(server, server->router->connection,
3292 server->server_type == SILC_ROUTER ?
3293 TRUE : FALSE, channel,
3294 target_client->id, SILC_ID_CLIENT_LEN,
3297 /* Re-generate channel key */
3298 silc_server_create_channel_key(server, channel, 0);
3300 /* Send the channel key to the channel. The key of course is not sent
3301 to the client who was kicked off the channel. */
3302 silc_server_send_channel_key(server, target_client->connection, channel,
3303 server->server_type == SILC_ROUTER ?
3304 FALSE : !server->standalone);
3307 silc_server_command_free(cmd);
3310 /* Server side of OPER command. Client uses this comand to obtain server
3311 operator privileges to this server/router. */
3313 SILC_SERVER_CMD_FUNC(oper)
3315 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3316 SilcServer server = cmd->server;
3317 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3318 unsigned char *username, *auth;
3319 unsigned int tmp_len;
3320 SilcServerConfigSectionAdminConnection *admin;
3321 SilcIDListData idata = (SilcIDListData)client;
3323 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_OPER, cmd, 1, 2);
3325 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3328 /* Get the username */
3329 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3331 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3332 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3336 /* Get the admin configuration */
3337 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
3338 username, client->nickname);
3340 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
3341 username, client->nickname);
3343 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3344 SILC_STATUS_ERR_AUTH_FAILED);
3349 /* Get the authentication payload */
3350 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3352 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3353 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3357 /* Verify the authentication data */
3358 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
3359 admin->auth_data, admin->auth_data_len,
3360 idata->hash, client->id, SILC_ID_CLIENT)) {
3361 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3362 SILC_STATUS_ERR_AUTH_FAILED);
3366 /* Client is now server operator */
3367 client->mode |= SILC_UMODE_SERVER_OPERATOR;
3369 /* Send reply to the sender */
3370 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3374 silc_server_command_free(cmd);
3377 /* Server side of SILCOPER command. Client uses this comand to obtain router
3378 operator privileges to this router. */
3380 SILC_SERVER_CMD_FUNC(silcoper)
3382 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3383 SilcServer server = cmd->server;
3384 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3385 unsigned char *username, *auth;
3386 unsigned int tmp_len;
3387 SilcServerConfigSectionAdminConnection *admin;
3388 SilcIDListData idata = (SilcIDListData)client;
3390 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SILCOPER, cmd, 1, 2);
3392 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3395 /* Get the username */
3396 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3398 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3399 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3403 /* Get the admin configuration */
3404 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
3405 username, client->nickname);
3407 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
3408 username, client->nickname);
3410 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3411 SILC_STATUS_ERR_AUTH_FAILED);
3416 /* Get the authentication payload */
3417 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3419 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3420 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3424 /* Verify the authentication data */
3425 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
3426 admin->auth_data, admin->auth_data_len,
3427 idata->hash, client->id, SILC_ID_CLIENT)) {
3428 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3429 SILC_STATUS_ERR_AUTH_FAILED);
3433 /* Client is now router operator */
3434 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
3436 /* Send reply to the sender */
3437 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3441 silc_server_command_free(cmd);
3444 /* Server side command of CONNECT. Connects us to the specified remote
3445 server or router. */
3447 SILC_SERVER_CMD_FUNC(connect)
3449 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3450 SilcServer server = cmd->server;
3451 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3452 unsigned char *tmp, *host;
3453 unsigned int tmp_len;
3454 unsigned int port = SILC_PORT;
3456 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CONNECT, cmd, 1, 2);
3458 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3461 /* Check whether client has the permissions. */
3462 if (client->mode == SILC_UMODE_NONE) {
3463 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3464 SILC_STATUS_ERR_NO_SERVER_PRIV);
3468 if (server->server_type == SILC_ROUTER &&
3469 client->mode & SILC_UMODE_SERVER_OPERATOR) {
3470 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3471 SILC_STATUS_ERR_NO_ROUTER_PRIV);
3475 /* Get the remote server */
3476 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3478 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3479 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3484 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3486 SILC_GET32_MSB(port, tmp);
3488 /* Create the connection. It is done with timeout and is async. */
3489 silc_server_create_connection(server, host, port);
3491 /* Send reply to the sender */
3492 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3496 silc_server_command_free(cmd);
3499 SILC_SERVER_CMD_FUNC(restart)
3503 /* Server side command of CLOSE. Closes connection to a specified server. */
3505 SILC_SERVER_CMD_FUNC(close)
3507 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3508 SilcServer server = cmd->server;
3509 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3510 SilcServerEntry server_entry;
3511 SilcSocketConnection sock;
3513 unsigned int tmp_len;
3514 unsigned char *name;
3515 unsigned int port = SILC_PORT;
3517 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CLOSE, cmd, 1, 2);
3519 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3522 /* Check whether client has the permissions. */
3523 if (client->mode == SILC_UMODE_NONE) {
3524 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3525 SILC_STATUS_ERR_NO_SERVER_PRIV);
3529 /* Get the remote server */
3530 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3532 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3533 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3538 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3540 SILC_GET32_MSB(port, tmp);
3542 server_entry = silc_idlist_find_server_by_conn(server->local_list,
3544 if (!server_entry) {
3545 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3546 SILC_STATUS_ERR_NO_SERVER_ID);
3550 /* Send reply to the sender */
3551 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3554 /* Close the connection to the server */
3555 sock = (SilcSocketConnection)server_entry->connection;
3556 silc_server_free_sock_user_data(server, sock);
3557 silc_server_close_connection(server, sock);
3560 silc_server_command_free(cmd);
3563 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
3564 active connections. */
3566 SILC_SERVER_CMD_FUNC(shutdown)
3568 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3569 SilcServer server = cmd->server;
3570 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3572 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
3574 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3577 /* Check whether client has the permission. */
3578 if (client->mode == SILC_UMODE_NONE) {
3579 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
3580 SILC_STATUS_ERR_NO_SERVER_PRIV);
3584 /* Send reply to the sender */
3585 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
3588 /* Then, gracefully, or not, bring the server down. */
3589 silc_server_stop(server);
3593 silc_server_command_free(cmd);
3596 /* Server side command of LEAVE. Removes client from a channel. */
3598 SILC_SERVER_CMD_FUNC(leave)
3600 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3601 SilcServer server = cmd->server;
3602 SilcSocketConnection sock = cmd->sock;
3603 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
3605 SilcChannelEntry channel;
3607 unsigned int i, len;
3610 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
3612 /* Get Channel ID */
3613 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
3615 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3616 SILC_STATUS_ERR_NO_CHANNEL_ID);
3619 id = silc_id_payload_parse_id(tmp, len);
3621 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3622 SILC_STATUS_ERR_NO_CHANNEL_ID);
3626 /* Get channel entry */
3627 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
3629 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
3631 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3632 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3637 /* Check whether this client is on the channel */
3638 if (!silc_server_client_on_channel(id_entry, channel)) {
3639 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3640 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3644 /* Notify routers that they should remove this client from their list
3645 of clients on the channel. Send LEAVE notify type. */
3646 if (!server->standalone)
3647 silc_server_send_notify_leave(server, server->router->connection,
3648 server->server_type == SILC_ROUTER ?
3649 TRUE : FALSE, channel, id_entry->id,
3650 SILC_ID_CLIENT_LEN);
3652 /* Remove client from channel */
3653 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
3655 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3658 /* If the channel does not exist anymore we won't send anything */
3662 /* Re-generate channel key */
3663 silc_server_create_channel_key(server, channel, 0);
3665 /* Encode channel key payload to be distributed on the channel */
3667 silc_channel_key_payload_encode(len, tmp,
3668 strlen(channel->channel_key->cipher->name),
3669 channel->channel_key->cipher->name,
3670 channel->key_len / 8, channel->key);
3672 /* If we are normal server then we will send it to our router. If we
3673 are router we will send it to all local servers that has clients on
3675 if (server->server_type == SILC_SERVER) {
3676 if (!server->standalone)
3677 silc_server_packet_send(server,
3678 cmd->server->router->connection,
3679 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
3680 packet->len, FALSE);
3685 /* Send to locally connected clients on the channel */
3686 silc_server_packet_send_local_channel(server, channel,
3687 SILC_PACKET_CHANNEL_KEY, 0,
3688 packet->data, packet->len, FALSE);
3690 silc_buffer_free(packet);
3694 silc_server_command_free(cmd);
3697 /* Server side of command USERS. Resolves clients and their USERS currently
3698 joined on the requested channel. The list of Client ID's and their modes
3699 on the channel is sent back. */
3701 SILC_SERVER_CMD_FUNC(users)
3703 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3704 SilcServer server = cmd->server;
3705 SilcChannelEntry channel;
3708 unsigned char *channel_id;
3709 unsigned int channel_id_len;
3710 SilcBuffer client_id_list;
3711 SilcBuffer client_mode_list;
3712 unsigned char lc[4];
3713 unsigned int list_count = 0;
3714 unsigned short ident = silc_command_get_ident(cmd->payload);
3716 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
3718 /* Get Channel ID */
3719 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
3721 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3722 SILC_STATUS_ERR_NO_CHANNEL_ID);
3725 id = silc_id_payload_parse_id(channel_id, channel_id_len);
3727 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3728 SILC_STATUS_ERR_NO_CHANNEL_ID);
3732 /* If we are server and we don't know about this channel we will send
3733 the command to our router. If we know about the channel then we also
3734 have the list of users already. */
3735 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
3737 if (server->server_type == SILC_SERVER && !server->standalone &&
3741 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3742 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3744 /* Send USERS command */
3745 silc_server_packet_send(server, server->router->connection,
3746 SILC_PACKET_COMMAND, cmd->packet->flags,
3747 tmpbuf->data, tmpbuf->len, TRUE);
3749 /* Reprocess this packet after received reply */
3750 silc_server_command_pending(server, SILC_COMMAND_USERS,
3751 silc_command_get_ident(cmd->payload),
3752 silc_server_command_destructor,
3753 silc_server_command_users,
3754 silc_server_command_dup(cmd));
3755 cmd->pending = TRUE;
3756 silc_command_set_ident(cmd->payload, ident);
3758 silc_buffer_free(tmpbuf);
3763 /* We are router and we will check the global list as well. */
3764 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
3766 /* Channel really does not exist */
3767 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3768 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3773 /* Get the users list */
3774 silc_server_get_users_on_channel(server, channel, &client_id_list,
3775 &client_mode_list, &list_count);
3778 SILC_PUT32_MSB(list_count, lc);
3781 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
3782 SILC_STATUS_OK, 0, 4,
3783 2, channel_id, channel_id_len,
3785 4, client_id_list->data,
3786 client_id_list->len,
3787 5, client_mode_list->data,
3788 client_mode_list->len);
3789 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3790 packet->data, packet->len, FALSE);
3792 silc_buffer_free(packet);
3793 silc_buffer_free(client_id_list);
3794 silc_buffer_free(client_mode_list);
3798 silc_server_command_free(cmd);