5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2002 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,
35 silc_server_command_send_status_data(SilcServerCommandContext cmd,
40 const unsigned char *arg,
43 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
44 SilcServerCommandReplyContext cmdr,
46 SILC_TASK_CALLBACK(silc_server_command_process_timeout);
48 /* Server command list. */
49 SilcServerCommand silc_command_list[] =
51 SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
52 SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
53 SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
54 SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
55 SILC_SERVER_CMD(list, LIST, SILC_CF_LAG_STRICT | SILC_CF_REG),
56 SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
57 SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
58 SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
59 SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG_STRICT | SILC_CF_REG | SILC_CF_OPER),
60 SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
61 SILC_SERVER_CMD(stats, STATS, SILC_CF_LAG | SILC_CF_REG),
62 SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
63 SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
64 SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG_STRICT | SILC_CF_REG),
65 SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
66 SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
67 SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG_STRICT | SILC_CF_REG),
68 SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
69 SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
70 SILC_SERVER_CMD(ban, BAN, SILC_CF_LAG_STRICT | SILC_CF_REG),
71 SILC_SERVER_CMD(detach, DETACH, SILC_CF_LAG_STRICT | SILC_CF_REG),
72 SILC_SERVER_CMD(watch, WATCH, SILC_CF_LAG | SILC_CF_REG),
73 SILC_SERVER_CMD(silcoper, SILCOPER,
74 SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
75 SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
76 SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
77 SILC_SERVER_CMD(getkey, GETKEY, SILC_CF_LAG | SILC_CF_REG),
79 SILC_SERVER_CMD(connect, PRIV_CONNECT,
80 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
81 SILC_SERVER_CMD(close, PRIV_CLOSE,
82 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
83 SILC_SERVER_CMD(shutdown, PRIV_SHUTDOWN, SILC_CF_LAG | SILC_CF_REG |
89 /* Performs several checks to the command. It first checks whether this
90 command was called as pending command callback. If it was then it checks
91 whether error occurred in the command reply where the pending command
94 It also checks that the requested command includes correct amount
96 #define SILC_SERVER_COMMAND_CHECK(command, context, min, max) \
100 if (silc_server_command_pending_error_check(cmd, context2, command)) { \
101 SILC_LOG_DEBUG(("Error occurred in command reply, command not called")); \
102 silc_server_command_free(cmd); \
106 _argc = silc_argument_get_arg_num(cmd->args); \
108 SILC_LOG_DEBUG(("Not enough parameters in command")); \
109 silc_server_command_send_status_reply(cmd, command, \
110 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, \
112 silc_server_command_free(cmd); \
116 SILC_LOG_DEBUG(("Too many parameters in command")); \
117 silc_server_command_send_status_reply(cmd, command, \
118 SILC_STATUS_ERR_TOO_MANY_PARAMS, \
120 silc_server_command_free(cmd); \
125 /* Returns TRUE if the connection is registered. Unregistered connections
126 usually cannot send commands hence the check. */
128 static int silc_server_is_registered(SilcServer server,
129 SilcSocketConnection sock,
130 SilcServerCommandContext cmd,
133 SilcIDListData idata = (SilcIDListData)sock->user_data;
138 if (idata->status & SILC_IDLIST_STATUS_REGISTERED)
141 silc_server_command_send_status_reply(cmd, command,
142 SILC_STATUS_ERR_NOT_REGISTERED, 0);
146 /* Internal context to hold data when executed command with timeout. */
148 SilcServerCommandContext ctx;
149 SilcServerCommand *cmd;
150 } *SilcServerCommandTimeout;
152 /* Timeout callback to process commands with timeout for client. Client's
153 commands are always executed with timeout. */
155 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
157 SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
158 SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data;
161 SILC_LOG_DEBUG(("Client entry is invalid"));
162 silc_server_command_free(timeout->ctx);
166 /* Update access time */
167 client->last_command = time(NULL);
169 if (!(timeout->cmd->flags & SILC_CF_REG)) {
170 SILC_LOG_DEBUG(("Calling %s command",
171 silc_get_command_name(timeout->cmd->cmd)));
172 timeout->cmd->cb(timeout->ctx, NULL);
173 } else if (silc_server_is_registered(timeout->ctx->server,
176 timeout->cmd->cmd)) {
177 SILC_LOG_DEBUG(("Calling %s command",
178 silc_get_command_name(timeout->cmd->cmd)));
179 timeout->cmd->cb(timeout->ctx, NULL);
181 SILC_LOG_DEBUG(("Client is not registered"));
182 silc_server_command_free(timeout->ctx);
188 /* Processes received command packet. */
190 void silc_server_command_process(SilcServer server,
191 SilcSocketConnection sock,
192 SilcPacketContext *packet)
194 SilcServerCommandContext ctx;
195 SilcServerCommand *cmd;
198 /* Allocate command context. This must be free'd by the
199 command routine receiving it. */
200 ctx = silc_server_command_alloc();
201 ctx->server = server;
202 ctx->sock = silc_socket_dup(sock);
203 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
205 /* Parse the command payload in the packet */
206 ctx->payload = silc_command_payload_parse(packet->buffer->data,
207 packet->buffer->len);
209 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
210 silc_packet_context_free(packet);
211 silc_socket_free(ctx->sock);
215 ctx->args = silc_command_get_args(ctx->payload);
217 /* Get the command */
218 command = silc_command_get(ctx->payload);
219 for (cmd = silc_command_list; cmd->cb; cmd++)
220 if (cmd->cmd == command)
223 if (!cmd || !cmd->cb) {
224 SILC_LOG_DEBUG(("Unknown command %d", command));
225 silc_server_command_send_status_reply(ctx, command,
226 SILC_STATUS_ERR_UNKNOWN_COMMAND, 0);
227 silc_server_command_free(ctx);
231 /* Execute client's commands always with timeout. Normally they are
232 executed with zero (0) timeout but if client is sending command more
233 frequently than once in 2 seconds, then the timeout may be 0 to 2
235 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
236 SilcClientEntry client = (SilcClientEntry)sock->user_data;
237 SilcServerCommandTimeout timeout;
241 SILC_LOG_DEBUG(("Client entry is invalid"));
242 silc_server_command_free(ctx);
245 timeout = silc_calloc(1, sizeof(*timeout));
249 if (client->last_command && (time(NULL) - client->last_command) < 2) {
250 client->fast_command++;
253 if (client->fast_command - 2 <= 0)
254 client->fast_command = 0;
256 client->fast_command -= 2;
260 if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
261 (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
262 silc_schedule_task_add(server->schedule, sock->sock,
263 silc_server_command_process_timeout, timeout,
264 (client->fast_command < 3 ? 0 :
265 2 - (time(NULL) - client->last_command)),
266 (client->fast_command < 3 ? 200000 : 0),
267 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
269 silc_schedule_task_add(server->schedule, sock->sock,
270 silc_server_command_process_timeout, timeout,
271 0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
275 /* Execute for server */
277 if (!(cmd->flags & SILC_CF_REG)) {
278 SILC_LOG_DEBUG(("Calling %s command", silc_get_command_name(cmd->cmd)));
280 } else if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) {
281 SILC_LOG_DEBUG(("Calling %s command", silc_get_command_name(cmd->cmd)));
284 SILC_LOG_DEBUG(("Server is not registered"));
285 silc_server_command_free(ctx);
289 /* Allocate Command Context */
291 SilcServerCommandContext silc_server_command_alloc()
293 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
298 /* Free's the command context allocated before executing the command */
300 void silc_server_command_free(SilcServerCommandContext ctx)
303 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
305 if (ctx->users < 1) {
307 silc_command_payload_free(ctx->payload);
309 silc_packet_context_free(ctx->packet);
311 silc_socket_free(ctx->sock); /* Decrease reference counter */
316 /* Duplicate Command Context by adding reference counter. The context won't
317 be free'd untill it hits zero. */
319 SilcServerCommandContext
320 silc_server_command_dup(SilcServerCommandContext ctx)
323 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
328 /* Add new pending command to be executed when reply to a command has been
329 received. The `reply_cmd' is the command that will call the `callback'
330 with `context' when reply has been received. It can be SILC_COMMAND_NONE
331 to match any command with the `ident'. If `ident' is non-zero
332 the `callback' will be executed when received reply with command
333 identifier `ident'. If there already exists pending command for the
334 specified command, ident, callback and context this function has no
337 bool silc_server_command_pending(SilcServer server,
338 SilcCommand reply_cmd,
340 SilcCommandCb callback,
343 SilcServerCommandPending *reply;
345 /* Check whether identical pending already exists for same command,
346 ident, callback and callback context. If it does then it would be
347 error to register it again. */
348 silc_dlist_start(server->pending_commands);
349 while ((reply = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
350 if (reply->reply_cmd == reply_cmd && reply->ident == ident &&
351 reply->callback == callback && reply->context == context)
355 reply = silc_calloc(1, sizeof(*reply));
356 reply->reply_cmd = reply_cmd;
357 reply->ident = ident;
358 reply->context = context;
359 reply->callback = callback;
360 silc_dlist_add(server->pending_commands, reply);
365 /* Deletes pending command by reply command type. */
367 void silc_server_command_pending_del(SilcServer server,
368 SilcCommand reply_cmd,
371 SilcServerCommandPending *r;
373 silc_dlist_start(server->pending_commands);
374 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
375 if ((r->reply_cmd == reply_cmd || (r->reply_cmd == SILC_COMMAND_NONE &&
377 && r->ident == ident) {
378 silc_dlist_del(server->pending_commands, r);
384 /* Checks for pending commands and marks callbacks to be called from
385 the command reply function. Returns TRUE if there were pending command. */
387 SilcServerCommandPendingCallbacks
388 silc_server_command_pending_check(SilcServer server,
389 SilcServerCommandReplyContext ctx,
392 SilcUInt32 *callbacks_count)
394 SilcServerCommandPending *r;
395 SilcServerCommandPendingCallbacks callbacks = NULL;
398 silc_dlist_start(server->pending_commands);
399 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
400 if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE)
401 && r->ident == ident) {
402 callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
403 callbacks[i].context = r->context;
404 callbacks[i].callback = r->callback;
405 r->reply_check = TRUE;
411 *callbacks_count = i;
415 /* Sends simple status message as command reply packet */
418 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
425 SILC_LOG_DEBUG(("Sending command status %d", status));
428 silc_command_reply_payload_encode_va(command, status, error,
429 silc_command_get_ident(cmd->payload),
431 silc_server_packet_send(cmd->server, cmd->sock,
432 SILC_PACKET_COMMAND_REPLY, 0,
433 buffer->data, buffer->len, FALSE);
434 silc_buffer_free(buffer);
437 /* Sends command status reply with one extra argument. The argument
438 type must be sent as argument. */
441 silc_server_command_send_status_data(SilcServerCommandContext cmd,
446 const unsigned char *arg,
451 SILC_LOG_DEBUG(("Sending command status %d", status));
454 silc_command_reply_payload_encode_va(command, status, 0,
455 silc_command_get_ident(cmd->payload),
456 1, arg_type, arg, arg_len);
457 silc_server_packet_send(cmd->server, cmd->sock,
458 SILC_PACKET_COMMAND_REPLY, 0,
459 buffer->data, buffer->len, FALSE);
460 silc_buffer_free(buffer);
463 /* This function can be called to check whether in the command reply
464 an error occurred. This function has no effect if this is called
465 when the command function was not called as pending command callback.
466 This returns TRUE if error had occurred. */
469 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
470 SilcServerCommandReplyContext cmdr,
473 if (!cmd->pending || !cmdr)
476 if (!silc_command_get_status(cmdr->payload, NULL, NULL)) {
479 /* Send the same command reply payload */
480 silc_command_set_ident(cmdr->payload,
481 silc_command_get_ident(cmd->payload));
482 buffer = silc_command_payload_encode_payload(cmdr->payload);
483 silc_server_packet_send(cmd->server, cmd->sock,
484 SILC_PACKET_COMMAND_REPLY, 0,
485 buffer->data, buffer->len, FALSE);
486 silc_buffer_free(buffer);
493 /******************************************************************************
497 ******************************************************************************/
506 #define ADD_ERROR(errptr, errptr_count, _id, _id_type, _index, _status) \
508 errptr = silc_realloc(errptr, sizeof(*errptr) * (errptr_count + 1)); \
511 errptr[errptr_count].id = _id; \
512 errptr[errptr_count].id_type = _id_type; \
513 errptr[errptr_count].index = _index; \
514 errptr[errptr_count].error = _status; \
519 silc_server_command_whois_parse(SilcServerCommandContext cmd,
520 SilcClientID ***client_id,
521 SilcUInt32 *client_id_count,
525 ResolveError *error_client,
526 SilcUInt32 *error_client_count)
530 SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
534 /* If client ID is in the command it must be used instead of nickname */
535 tmp = silc_argument_get_arg_type(cmd->args, 4, &len);
537 /* No ID, get the nickname@server string and parse it. */
538 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
540 silc_parse_userfqdn(tmp, nickname, server_name);
542 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
543 SILC_STATUS_ERR_BAD_NICKNAME, 0);
547 /* Command includes ID, we must use that. Take all ID's from the
549 for (k = 0, i = 0; i < argc; i++) {
550 tmp = silc_argument_get_arg_type(cmd->args, i + 4, &len);
553 id = silc_id_payload_parse_id(tmp, len, NULL);
555 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
556 (*client_id_count + 1));
557 (*client_id)[k] = id;
558 (*client_id_count)++;
561 ADD_ERROR((*error_client), (*error_client_count), NULL, 0, i + 4,
562 SILC_STATUS_ERR_BAD_CLIENT_ID);
567 /* Get the max count of reply messages allowed */
568 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
570 SILC_GET32_MSB(*count, tmp);
577 /* Resolve context used by both WHOIS and IDENTIFY commands */
579 SilcServerEntry router;
581 unsigned char **res_argv;
582 SilcUInt32 *res_argv_lens;
583 SilcUInt32 *res_argv_types;
585 } *SilcServerResolveContext;
588 silc_server_command_whois_check(SilcServerCommandContext cmd,
589 SilcClientEntry *clients,
590 SilcUInt32 clients_count)
592 SilcServer server = cmd->server;
593 SilcClientEntry entry;
594 SilcServerResolveContext resolve = NULL, r = NULL;
595 SilcUInt32 resolve_count = 0;
599 SILC_LOG_DEBUG(("Start"));
601 for (i = 0; i < clients_count; i++) {
606 if ((entry->nickname && entry->username && entry->userinfo) ||
607 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
611 /* If we are normal server, and we've not resolved this client from
612 router and it is global client, we'll check whether it is on some
613 channel. If not then we cannot be sure about its validity, and
614 we'll resolve it from router. */
615 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
616 entry->connection || silc_hash_table_count(entry->channels))
620 /* We need to resolve this entry since it is not complete */
622 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
623 /* The entry is being resolved (and we are not the resolver) so attach
624 to the command reply and we're done with this one. */
625 silc_server_command_pending(server, SILC_COMMAND_NONE,
626 entry->resolve_cmd_ident,
627 silc_server_command_whois,
628 silc_server_command_dup(cmd));
631 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
632 /* We've resolved this and it still is not ready. We'll return
633 and are that this will be handled again after it is resolved. */
634 for (i = 0; i < resolve_count; i++) {
635 for (k = 0; k < r->res_argc; k++)
636 silc_free(r->res_argv[k]);
637 silc_free(r->res_argv);
638 silc_free(r->res_argv_lens);
639 silc_free(r->res_argv_types);
644 /* We'll resolve this client */
648 for (k = 0; k < resolve_count; k++) {
649 if (resolve[k].router == entry->router) {
656 resolve = silc_realloc(resolve, sizeof(*resolve) *
657 (resolve_count + 1));
658 r = &resolve[resolve_count];
659 memset(r, 0, sizeof(*r));
660 r->router = entry->router;
661 r->ident = ++server->cmd_ident;
665 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
667 r->res_argv_lens = silc_realloc(r->res_argv_lens,
668 sizeof(*r->res_argv_lens) *
670 r->res_argv_types = silc_realloc(r->res_argv_types,
671 sizeof(*r->res_argv_types) *
673 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
674 r->res_argv[r->res_argc] = silc_calloc(idp->len,
675 sizeof(**r->res_argv));
676 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
677 r->res_argv_lens[r->res_argc] = idp->len;
678 r->res_argv_types[r->res_argc] = r->res_argc + 4;
680 silc_buffer_free(idp);
682 entry->resolve_cmd_ident = r->ident;
683 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
684 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
689 /* Do the resolving */
690 for (i = 0; i < resolve_count; i++) {
695 /* Send WHOIS request. We send WHOIS since we're doing the requesting
696 now anyway so make it a good one. */
697 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
698 r->res_argc, r->res_argv,
702 silc_server_packet_send(server, r->router->connection,
703 SILC_PACKET_COMMAND, cmd->packet->flags,
704 res_cmd->data, res_cmd->len, FALSE);
706 /* Reprocess this packet after received reply */
707 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
709 silc_server_command_whois,
710 silc_server_command_dup(cmd));
713 silc_buffer_free(res_cmd);
714 for (k = 0; k < r->res_argc; k++)
715 silc_free(r->res_argv[k]);
716 silc_free(r->res_argv);
717 silc_free(r->res_argv_lens);
718 silc_free(r->res_argv_types);
727 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
728 SilcClientEntry *clients,
729 SilcUInt32 clients_count,
731 SilcUInt32 errors_count,
732 int count, const char *nickname,
733 SilcClientID **client_ids)
735 SilcServer server = cmd->server;
737 int i, k, valid_count = clients_count;
739 SilcBuffer packet, idp, channels, umode_list = NULL;
740 SilcClientEntry entry;
742 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
743 char nh[256], uh[256];
744 unsigned char idle[4], mode[4];
745 unsigned char *fingerprint;
746 SilcSocketConnection hsock;
749 /* Process only valid clients and ignore those that are not registered.
750 This is checked with nickname only because when resolved client IDs
751 we check that they are registered earlier. */
753 for (i = 0; i < clients_count; i++)
754 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
760 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
761 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
762 3, nickname, strlen(nickname));
767 /* Start processing found clients. */
768 status = SILC_STATUS_OK;
770 status = SILC_STATUS_LIST_START;
772 for (i = 0, k = 0; i < clients_count; i++) {
778 status = SILC_STATUS_LIST_ITEM;
779 if (valid_count > 1 && k == valid_count - 1 && !errors_count)
780 status = SILC_STATUS_LIST_END;
781 if (count && k - 1 == count)
782 status = SILC_STATUS_LIST_END;
784 /* Send WHOIS reply */
785 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
786 tmp = silc_argument_get_first_arg(cmd->args, NULL);
788 memset(uh, 0, sizeof(uh));
789 memset(nh, 0, sizeof(nh));
790 memset(idle, 0, sizeof(idle));
792 strncat(nh, entry->nickname, strlen(entry->nickname));
793 if (!strchr(entry->nickname, '@')) {
795 if (entry->servername) {
796 strncat(nh, entry->servername, strlen(entry->servername));
798 len = entry->router ? strlen(entry->router->server_name) :
799 strlen(server->server_name);
800 strncat(nh, entry->router ? entry->router->server_name :
801 server->server_name, len);
805 strncat(uh, entry->username, strlen(entry->username));
806 if (!strchr(entry->username, '@') && entry->connection) {
808 hsock = (SilcSocketConnection)entry->connection;
809 len = strlen(hsock->hostname);
810 strncat(uh, hsock->hostname, len);
813 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
814 channels = silc_server_get_client_channel_list(server, entry, FALSE,
817 channels = silc_server_get_client_channel_list(server, entry, TRUE,
820 if (entry->data.fingerprint[0] != 0 && entry->data.fingerprint[1] != 0)
821 fingerprint = entry->data.fingerprint;
825 SILC_PUT32_MSB(entry->mode, mode);
826 if (entry->connection)
827 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
830 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
832 2, idp->data, idp->len,
836 strlen(entry->userinfo),
837 6, channels ? channels->data : NULL,
838 channels ? channels->len : 0,
842 fingerprint ? 20 : 0,
843 10, umode_list ? umode_list->data :
844 NULL, umode_list ? umode_list->len :
847 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
848 0, packet->data, packet->len, FALSE);
850 silc_buffer_free(packet);
851 silc_buffer_free(idp);
853 silc_buffer_free(channels);
855 silc_buffer_free(umode_list);
859 if (status == SILC_STATUS_LIST_END)
864 /* Send error replies */
865 if (status == SILC_STATUS_OK && errors_count > 1)
866 status = SILC_STATUS_LIST_START;
869 for (i = 0, k = 0; i < errors_count; i++) {
871 idp = silc_id_payload_encode(errors[i].id, SILC_ID_CLIENT);
875 tmp = silc_argument_get_arg_type(cmd->args, errors[i].index, &len);
879 status = SILC_STATUS_LIST_ITEM;
880 if (errors_count > 1 && k == errors_count - 1)
881 status = SILC_STATUS_LIST_END;
882 if (count && k - 1 == count)
883 status = SILC_STATUS_LIST_END;
886 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
887 (status == SILC_STATUS_OK ?
888 errors[i].error : status),
889 (status == SILC_STATUS_OK ?
890 0 : errors[i].error),
892 silc_buffer_free(idp);
895 if (status == SILC_STATUS_LIST_END)
902 silc_server_command_whois_send_router(SilcServerCommandContext cmd)
904 SilcServer server = cmd->server;
906 SilcUInt16 old_ident;
908 old_ident = silc_command_get_ident(cmd->payload);
909 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
910 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
912 /* Send WHOIS command to our router */
913 silc_server_packet_send(server, (SilcSocketConnection)
914 SILC_PRIMARY_ROUTE(server),
915 SILC_PACKET_COMMAND, cmd->packet->flags,
916 tmpbuf->data, tmpbuf->len, TRUE);
918 /* Reprocess this packet after received reply from router */
919 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
920 silc_command_get_ident(cmd->payload),
921 silc_server_command_whois,
922 silc_server_command_dup(cmd));
924 silc_command_set_ident(cmd->payload, old_ident);
925 silc_buffer_free(tmpbuf);
929 silc_server_command_whois_process(SilcServerCommandContext cmd)
931 SilcServer server = cmd->server;
932 char *nick = NULL, *server_name = NULL;
934 SilcClientEntry *clients = NULL, entry;
935 SilcClientID **client_id = NULL;
936 SilcUInt32 client_id_count = 0, clients_count = 0, error_client_count = 0;
937 ResolveError error_client = NULL;
939 bool check_global = FALSE;
941 /* Parse the whois request */
942 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
943 &nick, &server_name, &count,
944 &error_client, &error_client_count))
947 /* Send the WHOIS request to the router only if it included nickname.
948 Since nicknames can be expanded into many clients we need to send it
949 to router. If the WHOIS included only client ID's we will check them
950 first locally since we just might have them. */
951 if (nick && !client_id_count && cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
952 server->server_type == SILC_SERVER && !cmd->pending &&
953 !server->standalone) {
954 silc_server_command_whois_send_router(cmd);
959 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
961 else if (server->server_type != SILC_SERVER)
964 /* Get all clients matching that ID or nickname from local list */
965 if (client_id_count) {
966 /* Check all Client ID's received in the command packet */
967 for (i = 0; i < client_id_count; i++) {
968 entry = silc_idlist_find_client_by_id(server->local_list,
969 client_id[i], TRUE, NULL);
970 if (!entry && check_global)
971 entry = silc_idlist_find_client_by_id(server->global_list,
972 client_id[i], TRUE, NULL);
974 clients = silc_realloc(clients, sizeof(*clients) *
975 (clients_count + 1));
976 clients[clients_count++] = entry;
978 /* If we are normal server and did not send the request first to router
979 do it now, since we do not have the Client ID information. */
980 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
981 server->server_type == SILC_SERVER && !cmd->pending &&
982 !server->standalone) {
983 silc_server_command_whois_send_router(cmd);
988 ADD_ERROR(error_client, error_client_count, client_id[i],
989 SILC_ID_CLIENT, 0, SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
993 /* Find by nickname */
994 if (!silc_idlist_get_clients_by_hash(server->local_list,
995 nick, server->md5hash,
996 &clients, &clients_count))
997 silc_idlist_get_clients_by_nickname(server->local_list,
999 &clients, &clients_count);
1001 if (!silc_idlist_get_clients_by_hash(server->global_list,
1002 nick, server->md5hash,
1003 &clients, &clients_count))
1004 silc_idlist_get_clients_by_nickname(server->global_list,
1006 &clients, &clients_count);
1010 if (!clients && (client_id_count || nick)) {
1011 /* If we are normal server and did not send the request first to router
1012 do it now, since we do not have the information. */
1013 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1014 server->server_type == SILC_SERVER && !cmd->pending &&
1015 !server->standalone) {
1016 silc_server_command_whois_send_router(cmd);
1021 /* Such client(s) really does not exist in the SILC network. */
1022 if (!client_id_count)
1023 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
1024 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1025 3, nick, strlen(nick));
1027 silc_server_command_whois_send_reply(cmd, NULL, 0,
1028 error_client, error_client_count,
1033 /* Router always finds the client entry if it exists in the SILC network.
1034 However, it might be incomplete entry and does not include all the
1035 mandatory fields that WHOIS command reply requires. Check for these and
1036 make query from the server who owns the client if some fields are
1038 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
1043 /* Send the command reply */
1044 silc_server_command_whois_send_reply(cmd, clients, clients_count,
1045 error_client, error_client_count,
1046 count, nick, client_id);
1049 if (client_id_count) {
1050 for (i = 0; i < client_id_count; i++)
1051 silc_free(client_id[i]);
1052 silc_free(client_id);
1055 silc_free(error_client);
1057 silc_free(server_name);
1062 /* Server side of command WHOIS. Processes user's query and sends found
1063 results as command replies back to the client. */
1065 SILC_SERVER_CMD_FUNC(whois)
1067 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1070 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 3328);
1072 ret = silc_server_command_whois_process(cmd);
1073 silc_server_command_free(cmd);
1076 /******************************************************************************
1080 ******************************************************************************/
1083 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
1091 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1093 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
1094 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1099 /* Get the nickname@server string and parse it. */
1100 silc_parse_userfqdn(tmp, nickname, server_name);
1102 /* Get the max count of reply messages allowed */
1103 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1105 SILC_GET32_MSB(*count, tmp);
1113 silc_server_command_whowas_check(SilcServerCommandContext cmd,
1114 SilcClientEntry *clients,
1115 SilcUInt32 clients_count)
1117 SilcServer server = cmd->server;
1119 SilcClientEntry entry;
1121 for (i = 0; i < clients_count; i++) {
1124 if (!entry->nickname || !entry->username) {
1126 SilcUInt16 old_ident;
1131 old_ident = silc_command_get_ident(cmd->payload);
1132 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1133 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1135 /* Send WHOWAS command */
1136 silc_server_packet_send(server, entry->router->connection,
1137 SILC_PACKET_COMMAND, cmd->packet->flags,
1138 tmpbuf->data, tmpbuf->len, TRUE);
1140 /* Reprocess this packet after received reply */
1141 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1142 silc_command_get_ident(cmd->payload),
1143 silc_server_command_whowas,
1144 silc_server_command_dup(cmd));
1145 cmd->pending = TRUE;
1146 silc_command_set_ident(cmd->payload, old_ident);
1148 silc_buffer_free(tmpbuf);
1157 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1158 SilcClientEntry *clients,
1159 SilcUInt32 clients_count)
1161 SilcServer server = cmd->server;
1163 int i, k, count = 0, len;
1164 SilcBuffer packet, idp;
1165 SilcClientEntry entry = NULL;
1167 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1168 char nh[256], uh[256];
1171 status = SILC_STATUS_OK;
1173 /* Process only entries that are not registered anymore. */
1175 for (i = 0; i < clients_count; i++) {
1176 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1183 /* No valid entries found at all, just send error */
1184 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1185 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1186 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1187 3, tmp, tmp ? strlen(tmp) : 0);
1191 if (valid_count > 1)
1192 status = SILC_STATUS_LIST_START;
1194 for (i = 0, k = 0; i < clients_count; i++) {
1200 status = SILC_STATUS_LIST_ITEM;
1201 if (valid_count > 1 && k == valid_count - 1)
1202 status = SILC_STATUS_LIST_END;
1203 if (count && k - 1 == count)
1204 status = SILC_STATUS_LIST_END;
1206 /* Send WHOWAS reply */
1207 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1208 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1209 memset(uh, 0, sizeof(uh));
1210 memset(nh, 0, sizeof(nh));
1212 strncat(nh, entry->nickname, strlen(entry->nickname));
1213 if (!strchr(entry->nickname, '@')) {
1214 strncat(nh, "@", 1);
1215 if (entry->servername) {
1216 strncat(nh, entry->servername, strlen(entry->servername));
1218 len = entry->router ? strlen(entry->router->server_name) :
1219 strlen(server->server_name);
1220 strncat(nh, entry->router ? entry->router->server_name :
1221 server->server_name, len);
1225 strncat(uh, entry->username, strlen(entry->username));
1226 if (!strchr(entry->username, '@')) {
1227 strncat(uh, "@", 1);
1228 strcat(uh, "*private*");
1232 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1233 status, 0, ident, 4,
1234 2, idp->data, idp->len,
1239 strlen(entry->userinfo) : 0);
1240 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1241 0, packet->data, packet->len, FALSE);
1243 silc_buffer_free(packet);
1244 silc_buffer_free(idp);
1246 if (status == SILC_STATUS_LIST_END)
1253 silc_server_command_whowas_process(SilcServerCommandContext cmd)
1255 SilcServer server = cmd->server;
1256 char *nick = NULL, *server_name = NULL;
1258 SilcClientEntry *clients = NULL;
1259 SilcUInt32 clients_count = 0;
1261 bool check_global = FALSE;
1263 /* Protocol dictates that we must always send the received WHOWAS request
1264 to our router if we are normal server, so let's do it now unless we
1265 are standalone. We will not send any replies to the client until we
1266 have received reply from the router. */
1267 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1268 server->server_type == SILC_SERVER && !cmd->pending &&
1269 !server->standalone) {
1271 SilcUInt16 old_ident;
1273 old_ident = silc_command_get_ident(cmd->payload);
1274 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1275 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1277 /* Send WHOWAS command to our router */
1278 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
1279 SILC_PACKET_COMMAND, cmd->packet->flags,
1280 tmpbuf->data, tmpbuf->len, TRUE);
1282 /* Reprocess this packet after received reply from router */
1283 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1284 silc_command_get_ident(cmd->payload),
1285 silc_server_command_whowas,
1286 silc_server_command_dup(cmd));
1287 cmd->pending = TRUE;
1288 silc_command_set_ident(cmd->payload, old_ident);
1290 silc_buffer_free(tmpbuf);
1295 /* We are ready to process the command request. Let's search for the
1296 requested client and send reply to the requesting client. */
1298 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1299 check_global = TRUE;
1300 else if (server->server_type != SILC_SERVER)
1301 check_global = TRUE;
1303 /* Parse the whowas request */
1304 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1307 /* Get all clients matching that nickname from local list */
1308 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1310 &clients, &clients_count))
1311 silc_idlist_get_clients_by_hash(server->local_list,
1312 nick, server->md5hash,
1313 &clients, &clients_count);
1315 /* Check global list as well */
1317 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1319 &clients, &clients_count))
1320 silc_idlist_get_clients_by_hash(server->global_list,
1321 nick, server->md5hash,
1322 &clients, &clients_count);
1326 /* Such a client really does not exist in the SILC network. */
1327 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1328 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1329 3, nick, strlen(nick));
1333 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1338 /* Send the command reply to the client */
1339 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1344 silc_free(server_name);
1348 /* Server side of command WHOWAS. */
1350 SILC_SERVER_CMD_FUNC(whowas)
1352 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1355 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1357 ret = silc_server_command_whowas_process(cmd);
1358 silc_server_command_free(cmd);
1361 /******************************************************************************
1365 ******************************************************************************/
1368 silc_server_command_identify_send_router(SilcServerCommandContext cmd)
1370 SilcServer server = cmd->server;
1372 SilcUInt16 old_ident;
1374 old_ident = silc_command_get_ident(cmd->payload);
1375 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1376 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1378 /* Send IDENTIFY command to our router */
1379 silc_server_packet_send(server, (SilcSocketConnection)
1380 SILC_PRIMARY_ROUTE(server),
1381 SILC_PACKET_COMMAND, cmd->packet->flags,
1382 tmpbuf->data, tmpbuf->len, TRUE);
1384 /* Reprocess this packet after received reply from router */
1385 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1386 silc_command_get_ident(cmd->payload),
1387 silc_server_command_identify,
1388 silc_server_command_dup(cmd));
1389 cmd->pending = TRUE;
1390 silc_command_set_ident(cmd->payload, old_ident);
1391 silc_buffer_free(tmpbuf);
1395 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1396 SilcClientEntry **clients,
1397 SilcUInt32 *clients_count,
1398 SilcServerEntry **servers,
1399 SilcUInt32 *servers_count,
1400 SilcChannelEntry **channels,
1401 SilcUInt32 *channels_count,
1403 ResolveError *error_id,
1404 SilcUInt32 *error_id_count)
1406 SilcServer server = cmd->server;
1409 SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
1411 bool check_global = FALSE;
1415 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1416 check_global = TRUE;
1417 else if (server->server_type != SILC_SERVER)
1418 check_global = TRUE;
1420 /* If ID Payload is in the command it must be used instead of names */
1421 tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1423 /* No ID, get the names. */
1425 /* If we are normal server and have not resolved information from
1426 router yet, do so now. */
1427 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1428 server->server_type == SILC_SERVER && !cmd->pending &&
1429 !server->standalone) {
1430 silc_server_command_identify_send_router(cmd);
1434 /* Try to get nickname@server. */
1435 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1438 char *nick_server = NULL;
1440 silc_parse_userfqdn(tmp, &nick, &nick_server);
1442 if (!silc_idlist_get_clients_by_hash(server->local_list,
1443 nick, server->md5hash,
1444 clients, clients_count))
1445 silc_idlist_get_clients_by_nickname(server->local_list,
1447 clients, clients_count);
1449 if (!silc_idlist_get_clients_by_hash(server->global_list,
1450 nick, server->md5hash,
1451 clients, clients_count))
1452 silc_idlist_get_clients_by_nickname(server->global_list,
1454 clients, clients_count);
1458 silc_free(nick_server);
1461 /* the nickname does not exist, send error reply */
1462 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1463 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1464 3, tmp, strlen(tmp));
1469 /* Try to get server name */
1470 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1472 entry = silc_idlist_find_server_by_name(server->local_list,
1474 if (!entry && check_global)
1475 entry = silc_idlist_find_server_by_name(server->global_list,
1478 *servers = silc_realloc(*servers, sizeof(**servers) *
1479 (*servers_count + 1));
1480 (*servers)[(*servers_count)++] = entry;
1484 /* the server does not exist, send error reply */
1485 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1486 SILC_STATUS_ERR_NO_SUCH_SERVER,
1487 0, 3, tmp, strlen(tmp));
1492 /* Try to get channel name */
1493 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1495 entry = silc_idlist_find_channel_by_name(server->local_list,
1497 if (!entry && check_global)
1498 entry = silc_idlist_find_channel_by_name(server->global_list,
1501 *channels = silc_realloc(*channels, sizeof(**channels) *
1502 (*channels_count + 1));
1503 (*channels)[(*channels_count)++] = entry;
1507 /* The channel does not exist, send error reply */
1508 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1509 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1510 0, 3, tmp, strlen(tmp));
1515 if (!(*clients) && !(*servers) && !(*channels)) {
1516 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1517 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1522 /* Command includes ID, we must use that. Also check whether the command
1523 has more than one ID set - take them all. */
1525 /* Take all ID's from the command packet */
1526 for (i = 0; i < argc; i++) {
1529 tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
1533 idp = silc_id_payload_parse(tmp, len);
1535 ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1536 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1538 id = silc_id_payload_get_id(idp);
1539 switch (silc_id_payload_get_type(idp)) {
1541 case SILC_ID_CLIENT:
1542 entry = silc_idlist_find_client_by_id(server->local_list,
1544 if (!entry && check_global)
1545 entry = silc_idlist_find_client_by_id(server->global_list,
1548 *clients = silc_realloc(*clients, sizeof(**clients) *
1549 (*clients_count + 1));
1550 (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
1552 /* If we are normal server and have not resolved information from
1553 router yet, do so now. */
1554 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1555 server->server_type == SILC_SERVER && !cmd->pending &&
1556 !server->standalone) {
1557 silc_server_command_identify_send_router(cmd);
1558 silc_free(*clients);
1559 silc_free(*servers);
1560 silc_free(*channels);
1561 silc_free(*error_id);
1565 ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1566 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
1571 case SILC_ID_SERVER:
1572 entry = silc_idlist_find_server_by_id(server->local_list,
1574 if (!entry && check_global)
1575 entry = silc_idlist_find_server_by_id(server->global_list,
1578 *servers = silc_realloc(*servers, sizeof(**servers) *
1579 (*servers_count + 1));
1580 (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
1582 /* If we are normal server and have not resolved information from
1583 router yet, do so now. */
1584 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1585 server->server_type == SILC_SERVER && !cmd->pending &&
1586 !server->standalone) {
1587 silc_server_command_identify_send_router(cmd);
1588 silc_free(*clients);
1589 silc_free(*servers);
1590 silc_free(*channels);
1591 silc_free(*error_id);
1595 ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1596 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
1600 case SILC_ID_CHANNEL:
1601 entry = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
1602 if (!entry && check_global)
1603 entry = silc_idlist_find_channel_by_id(server->global_list, id,
1606 *channels = silc_realloc(*channels, sizeof(**channels) *
1607 (*channels_count + 1));
1608 (*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
1610 /* If we are normal server and have not resolved information from
1611 router yet, do so now. */
1612 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1613 server->server_type == SILC_SERVER && !cmd->pending &&
1614 !server->standalone) {
1615 silc_server_command_identify_send_router(cmd);
1616 silc_free(*clients);
1617 silc_free(*servers);
1618 silc_free(*channels);
1619 silc_free(*error_id);
1623 ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1624 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID);
1629 silc_id_payload_free(idp);
1634 /* Get the max count of reply messages allowed */
1635 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1637 SILC_GET32_MSB(*count, tmp);
1644 /* Checks that all mandatory fields in client entry are present. If not
1645 then send WHOIS request to the server who owns the client. We use
1646 WHOIS because we want to get as much information as possible at once. */
1649 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1650 SilcClientEntry *clients,
1651 SilcUInt32 clients_count)
1653 SilcServer server = cmd->server;
1654 SilcClientEntry entry;
1655 SilcServerResolveContext resolve = NULL, r = NULL;
1656 SilcUInt32 resolve_count = 0;
1660 for (i = 0; i < clients_count; i++) {
1665 if (entry->nickname ||
1666 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1670 /* If we are normal server, and we've not resolved this client from
1671 router and it is global client, we'll check whether it is on some
1672 channel. If not then we cannot be sure about its validity, and
1673 we'll resolve it from router. */
1674 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
1675 entry->connection || silc_hash_table_count(entry->channels))
1679 /* We need to resolve this entry since it is not complete */
1681 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1682 /* The entry is being resolved (and we are not the resolver) so attach
1683 to the command reply and we're done with this one. */
1684 silc_server_command_pending(server, SILC_COMMAND_NONE,
1685 entry->resolve_cmd_ident,
1686 silc_server_command_identify,
1687 silc_server_command_dup(cmd));
1690 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1691 /* We've resolved this and it still is not ready. We'll return
1692 and are that this will be handled again after it is resolved. */
1693 for (i = 0; i < resolve_count; i++) {
1694 for (k = 0; k < r->res_argc; k++)
1695 silc_free(r->res_argv[k]);
1696 silc_free(r->res_argv);
1697 silc_free(r->res_argv_lens);
1698 silc_free(r->res_argv_types);
1703 /* We'll resolve this client */
1707 for (k = 0; k < resolve_count; k++) {
1708 if (resolve[k].router == entry->router) {
1715 resolve = silc_realloc(resolve, sizeof(*resolve) *
1716 (resolve_count + 1));
1717 r = &resolve[resolve_count];
1718 memset(r, 0, sizeof(*r));
1719 r->router = entry->router;
1720 r->ident = ++server->cmd_ident;
1724 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1726 r->res_argv_lens = silc_realloc(r->res_argv_lens,
1727 sizeof(*r->res_argv_lens) *
1729 r->res_argv_types = silc_realloc(r->res_argv_types,
1730 sizeof(*r->res_argv_types) *
1732 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1733 r->res_argv[r->res_argc] = silc_calloc(idp->len,
1734 sizeof(**r->res_argv));
1735 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1736 r->res_argv_lens[r->res_argc] = idp->len;
1737 r->res_argv_types[r->res_argc] = r->res_argc + 4;
1739 silc_buffer_free(idp);
1741 entry->resolve_cmd_ident = r->ident;
1742 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1743 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1748 /* Do the resolving */
1749 for (i = 0; i < resolve_count; i++) {
1754 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1755 now anyway so make it a good one. */
1756 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1757 r->res_argc, r->res_argv,
1761 silc_server_packet_send(server, r->router->connection,
1762 SILC_PACKET_COMMAND, cmd->packet->flags,
1763 res_cmd->data, res_cmd->len, FALSE);
1765 /* Reprocess this packet after received reply */
1766 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1768 silc_server_command_identify,
1769 silc_server_command_dup(cmd));
1770 cmd->pending = TRUE;
1772 silc_buffer_free(res_cmd);
1773 for (k = 0; k < r->res_argc; k++)
1774 silc_free(r->res_argv[k]);
1775 silc_free(r->res_argv);
1776 silc_free(r->res_argv_lens);
1777 silc_free(r->res_argv_types);
1786 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1787 SilcClientEntry *clients,
1788 SilcUInt32 clients_count,
1789 SilcServerEntry *servers,
1790 SilcUInt32 servers_count,
1791 SilcChannelEntry *channels,
1792 SilcUInt32 channels_count,
1793 ResolveError errors,
1794 SilcUInt32 errors_count,
1797 SilcServer server = cmd->server;
1798 int i, k, valid_count;
1800 SilcBuffer packet, idp;
1802 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1803 char nh[256], uh[256];
1804 SilcSocketConnection hsock;
1807 status = SILC_STATUS_OK;
1810 SilcClientEntry entry;
1811 valid_count = clients_count;
1813 if (silc_argument_get_arg_type(cmd->args, 1, NULL)) {
1814 /* Process only valid clients and ignore those that are not registered.
1815 This is checked with nickname only because when resolved client IDs
1816 we check that they are registered earlier. */
1818 for (i = 0; i < clients_count; i++) {
1819 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1826 /* No valid entries found at all, just send error */
1827 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1828 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1829 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1830 3, tmp, tmp ? strlen(tmp) : 0);
1835 /* Process all valid client entries and send command replies */
1837 if (valid_count > 1)
1838 status = SILC_STATUS_LIST_START;
1840 for (i = 0, k = 0; i < clients_count; i++) {
1846 status = SILC_STATUS_LIST_ITEM;
1847 if (valid_count > 1 && k == valid_count - 1
1848 && !servers_count && !channels_count && !errors_count)
1849 status = SILC_STATUS_LIST_END;
1850 if (count && k - 1 == count)
1851 status = SILC_STATUS_LIST_END;
1853 /* Send IDENTIFY reply */
1855 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1856 memset(uh, 0, sizeof(uh));
1857 memset(nh, 0, sizeof(nh));
1858 strncat(nh, entry->nickname, strlen(entry->nickname));
1859 if (!strchr(entry->nickname, '@')) {
1860 strncat(nh, "@", 1);
1861 if (entry->servername) {
1862 strncat(nh, entry->servername, strlen(entry->servername));
1864 len = entry->router ? strlen(entry->router->server_name) :
1865 strlen(server->server_name);
1866 strncat(nh, entry->router ? entry->router->server_name :
1867 server->server_name, len);
1871 if (!entry->username) {
1872 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1873 status, 0, ident, 2,
1874 2, idp->data, idp->len,
1877 strncat(uh, entry->username, strlen(entry->username));
1878 if (!strchr(entry->username, '@') && entry->connection) {
1879 strncat(uh, "@", 1);
1880 hsock = (SilcSocketConnection)entry->connection;
1881 len = strlen(hsock->hostname);
1882 strncat(uh, hsock->hostname, len);
1885 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1886 status, 0, ident, 3,
1887 2, idp->data, idp->len,
1892 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1893 0, packet->data, packet->len, FALSE);
1895 silc_buffer_free(packet);
1896 silc_buffer_free(idp);
1898 if (status == SILC_STATUS_LIST_END)
1905 SilcServerEntry entry;
1907 if (status == SILC_STATUS_OK && servers_count > 1)
1908 status = SILC_STATUS_LIST_START;
1910 for (i = 0, k = 0; i < servers_count; i++) {
1914 status = SILC_STATUS_LIST_ITEM;
1915 if (servers_count > 1 && k == servers_count - 1 && !channels_count &&
1917 status = SILC_STATUS_LIST_END;
1918 if (count && k - 1 == count)
1919 status = SILC_STATUS_LIST_END;
1921 /* Send IDENTIFY reply */
1922 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1924 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1925 status, 0, ident, 2,
1926 2, idp->data, idp->len,
1927 3, entry->server_name,
1928 entry->server_name ?
1929 strlen(entry->server_name) : 0);
1930 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1931 0, packet->data, packet->len, FALSE);
1933 silc_buffer_free(packet);
1934 silc_buffer_free(idp);
1936 if (status == SILC_STATUS_LIST_END)
1943 SilcChannelEntry entry;
1945 if (status == SILC_STATUS_OK && channels_count > 1)
1946 status = SILC_STATUS_LIST_START;
1948 for (i = 0, k = 0; i < channels_count; i++) {
1949 entry = channels[i];
1952 status = SILC_STATUS_LIST_ITEM;
1953 if (channels_count > 1 && k == channels_count - 1 && !errors_count)
1954 status = SILC_STATUS_LIST_END;
1955 if (count && k - 1 == count)
1956 status = SILC_STATUS_LIST_END;
1958 /* Send IDENTIFY reply */
1959 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1961 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1962 status, 0, ident, 2,
1963 2, idp->data, idp->len,
1964 3, entry->channel_name,
1965 entry->channel_name ?
1966 strlen(entry->channel_name): 0);
1967 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1968 0, packet->data, packet->len, FALSE);
1970 silc_buffer_free(packet);
1971 silc_buffer_free(idp);
1973 if (status == SILC_STATUS_LIST_END)
1979 /* Send error replies */
1981 if (status == SILC_STATUS_OK && errors_count > 1)
1982 status = SILC_STATUS_LIST_START;
1985 for (i = 0, k = 0; i < errors_count; i++) {
1987 idp = silc_id_payload_encode(errors[i].id, SILC_ID_CLIENT);
1991 tmp = silc_argument_get_arg_type(cmd->args, errors[i].index, &len);
1995 status = SILC_STATUS_LIST_ITEM;
1996 if (errors_count > 1 && k == errors_count - 1)
1997 status = SILC_STATUS_LIST_END;
1998 if (count && k - 1 == count)
1999 status = SILC_STATUS_LIST_END;
2002 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
2003 (status == SILC_STATUS_OK ?
2004 errors[i].error : status),
2005 (status == SILC_STATUS_OK ?
2006 0 : errors[i].error),
2008 silc_buffer_free(idp);
2011 if (status == SILC_STATUS_LIST_END)
2019 silc_server_command_identify_process(SilcServerCommandContext cmd)
2021 SilcUInt32 count = 0;
2023 SilcClientEntry *clients = NULL;
2024 SilcServerEntry *servers = NULL;
2025 SilcChannelEntry *channels = NULL;
2026 SilcUInt32 clients_count = 0, servers_count = 0, channels_count = 0;
2027 SilcUInt32 errors_count = 0;
2028 ResolveError errors = NULL;
2030 /* Parse the IDENTIFY request */
2031 ret = silc_server_command_identify_parse(cmd,
2032 &clients, &clients_count,
2033 &servers, &servers_count,
2034 &channels, &channels_count,
2035 &count, &errors, &errors_count);
2040 /* Check that all mandatory fields are present and request those data
2041 from the server who owns the client if necessary. */
2042 if (!silc_server_command_identify_check_client(cmd, clients,
2048 /* Send the command reply to the client */
2049 silc_server_command_identify_send_reply(cmd,
2050 clients, clients_count,
2051 servers, servers_count,
2052 channels, channels_count,
2053 errors, errors_count,
2059 silc_free(channels);
2064 SILC_SERVER_CMD_FUNC(identify)
2066 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2069 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
2071 ret = silc_server_command_identify_process(cmd);
2072 silc_server_command_free(cmd);
2075 /* Server side of command NICK. Sets nickname for user. Setting
2076 nickname causes generation of a new client ID for the client. The
2077 new client ID is sent to the client after changing the nickname. */
2079 SILC_SERVER_CMD_FUNC(nick)
2081 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2082 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2083 SilcServer server = cmd->server;
2084 SilcBuffer packet, nidp, oidp = NULL;
2085 SilcClientID *new_id;
2086 SilcUInt32 nick_len;
2088 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2091 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
2094 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
2096 /* Check nickname */
2097 nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
2100 if (silc_server_name_bad_chars(nick, nick_len) == TRUE) {
2101 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2102 SILC_STATUS_ERR_BAD_NICKNAME, 0);
2106 /* Check for same nickname */
2107 if (!strcmp(client->nickname, nick)) {
2108 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2112 /* Create new Client ID */
2113 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
2115 cmd->server->md5hash, nick,
2119 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2120 SILC_STATUS_ERR_BAD_NICKNAME, 0);
2123 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2126 /* Send notify about nickname change to our router. We send the new
2127 ID and ask to replace it with the old one. If we are router the
2128 packet is broadcasted. Send NICK_CHANGE notify. */
2129 silc_server_send_notify_nick_change(server, SILC_PRIMARY_ROUTE(server),
2130 SILC_BROADCAST(server), client->id,
2133 /* Check if anyone is watching the old nickname */
2134 if (server->server_type == SILC_ROUTER)
2135 silc_server_check_watcher_list(server, client, nick,
2136 SILC_NOTIFY_TYPE_NICK_CHANGE);
2138 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2140 /* Remove old cache entry */
2141 silc_idcache_del_by_context(server->local_list->clients, client);
2143 silc_free(client->id);
2144 client->id = new_id;
2146 silc_free(client->nickname);
2147 client->nickname = strdup(nick);
2149 /* Update client cache */
2150 silc_idcache_add(server->local_list->clients, client->nickname,
2151 client->id, (void *)client, 0, NULL);
2153 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2155 /* Send NICK_CHANGE notify to the client's channels */
2156 silc_server_send_notify_on_channels(server, NULL, client,
2157 SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
2158 oidp->data, oidp->len,
2159 nidp->data, nidp->len,
2161 strlen(client->nickname));
2163 /* Check if anyone is watching the new nickname */
2164 if (server->server_type == SILC_ROUTER)
2165 silc_server_check_watcher_list(server, client, NULL,
2166 SILC_NOTIFY_TYPE_NICK_CHANGE);
2169 /* Send the new Client ID as reply command back to client */
2170 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
2171 SILC_STATUS_OK, 0, ident, 2,
2172 2, nidp->data, nidp->len,
2173 3, nick, strlen(nick));
2174 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2175 0, packet->data, packet->len, FALSE);
2177 silc_buffer_free(packet);
2178 silc_buffer_free(nidp);
2180 silc_buffer_free(oidp);
2183 silc_server_command_free(cmd);
2186 /* Sends the LIST command reply */
2189 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2190 SilcChannelEntry *lch,
2191 SilcUInt32 lch_count,
2192 SilcChannelEntry *gch,
2193 SilcUInt32 gch_count)
2196 SilcBuffer packet, idp;
2197 SilcChannelEntry entry;
2199 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2201 unsigned char usercount[4];
2203 int valid_lcount = 0, valid_rcount = 0;
2205 for (i = 0; i < lch_count; i++) {
2206 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2211 for (i = 0; i < gch_count; i++) {
2212 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2218 status = SILC_STATUS_OK;
2219 if ((lch_count + gch_count) > 1)
2220 status = SILC_STATUS_LIST_START;
2223 for (i = 0, k = 0; i < lch_count; i++) {
2229 status = SILC_STATUS_LIST_ITEM;
2230 if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
2231 status = SILC_STATUS_LIST_END;
2233 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2235 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2236 topic = "*private*";
2237 memset(usercount, 0, sizeof(usercount));
2239 topic = entry->topic;
2240 users = silc_hash_table_count(entry->user_list);
2241 SILC_PUT32_MSB(users, usercount);
2244 /* Send the reply */
2246 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2247 status, 0, ident, 4,
2248 2, idp->data, idp->len,
2249 3, entry->channel_name,
2250 strlen(entry->channel_name),
2251 4, topic, topic ? strlen(topic) : 0,
2253 silc_server_packet_send(cmd->server, cmd->sock,
2254 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2255 packet->len, FALSE);
2256 silc_buffer_free(packet);
2257 silc_buffer_free(idp);
2262 for (i = 0, k = 0; i < gch_count; i++) {
2268 status = SILC_STATUS_LIST_ITEM;
2269 if (valid_rcount > 1 && k == valid_rcount - 1)
2270 status = SILC_STATUS_LIST_END;
2272 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2274 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2275 topic = "*private*";
2276 memset(usercount, 0, sizeof(usercount));
2278 topic = entry->topic;
2279 users = entry->user_count;
2280 SILC_PUT32_MSB(users, usercount);
2283 /* Send the reply */
2285 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2286 status, 0, ident, 4,
2287 2, idp->data, idp->len,
2288 3, entry->channel_name,
2289 strlen(entry->channel_name),
2290 4, topic, topic ? strlen(topic) : 0,
2292 silc_server_packet_send(cmd->server, cmd->sock,
2293 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2294 packet->len, FALSE);
2295 silc_buffer_free(packet);
2296 silc_buffer_free(idp);
2301 /* Server side of LIST command. This lists the channel of the requested
2302 server. Secret channels are not listed. */
2304 SILC_SERVER_CMD_FUNC(list)
2306 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2307 SilcServer server = cmd->server;
2308 SilcChannelID *channel_id = NULL;
2311 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2312 SilcUInt32 lch_count = 0, gch_count = 0;
2314 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2316 /* If we are normal server, send the command to router, since we
2317 want to know all channels in the network. */
2318 if (!cmd->pending && server->server_type == SILC_SERVER &&
2319 !server->standalone) {
2321 SilcUInt16 old_ident;
2323 old_ident = silc_command_get_ident(cmd->payload);
2324 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2325 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2326 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
2327 SILC_PACKET_COMMAND, cmd->packet->flags,
2328 tmpbuf->data, tmpbuf->len, TRUE);
2330 /* Reprocess this packet after received reply from router */
2331 silc_server_command_pending(server, SILC_COMMAND_LIST,
2332 silc_command_get_ident(cmd->payload),
2333 silc_server_command_list,
2334 silc_server_command_dup(cmd));
2335 cmd->pending = TRUE;
2336 silc_command_set_ident(cmd->payload, old_ident);
2337 silc_buffer_free(tmpbuf);
2341 /* Get Channel ID */
2342 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2344 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2346 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2347 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2352 /* Get the channels from local list */
2353 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2356 /* Get the channels from global list */
2357 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2360 /* Send the reply */
2361 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2362 gchannels, gch_count);
2364 silc_free(lchannels);
2365 silc_free(gchannels);
2368 silc_server_command_free(cmd);
2371 /* Server side of TOPIC command. Sets topic for channel and/or returns
2372 current topic to client. */
2374 SILC_SERVER_CMD_FUNC(topic)
2376 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2377 SilcServer server = cmd->server;
2378 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2379 SilcChannelID *channel_id;
2380 SilcChannelEntry channel;
2381 SilcChannelClientEntry chl;
2382 SilcBuffer packet, idp;
2384 SilcUInt32 argc, tmp_len;
2385 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2387 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
2390 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2392 argc = silc_argument_get_arg_num(cmd->args);
2394 /* Get Channel ID */
2395 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2397 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2398 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2401 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2403 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2404 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2408 /* Check whether the channel exists */
2409 channel = silc_idlist_find_channel_by_id(server->local_list,
2412 channel = silc_idlist_find_channel_by_id(server->global_list,
2415 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2416 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
2424 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2426 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2427 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2432 if (strlen(tmp) > 256) {
2433 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2434 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2439 /* See whether the client is on channel and has rights to change topic */
2440 if (!silc_server_client_on_channel(client, channel, &chl)) {
2441 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2442 SILC_STATUS_ERR_NOT_ON_CHANNEL,
2447 if (channel->mode & SILC_CHANNEL_MODE_TOPIC &&
2448 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
2449 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
2450 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2451 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
2456 if (!channel->topic || strcmp(channel->topic, tmp)) {
2457 /* Set the topic for channel */
2458 silc_free(channel->topic);
2459 channel->topic = strdup(tmp);
2461 /* Send TOPIC_SET notify type to the network */
2462 silc_server_send_notify_topic_set(server, SILC_PRIMARY_ROUTE(server),
2463 SILC_BROADCAST(server), channel,
2464 client->id, SILC_ID_CLIENT,
2467 /* Send notify about topic change to all clients on the channel */
2468 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2469 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2470 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2471 idp->data, idp->len,
2473 strlen(channel->topic));
2474 silc_buffer_free(idp);
2478 /* Send the topic to client as reply packet */
2479 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2480 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2481 SILC_STATUS_OK, 0, ident, 2,
2482 2, idp->data, idp->len,
2485 strlen(channel->topic) : 0);
2486 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2487 0, packet->data, packet->len, FALSE);
2489 silc_buffer_free(packet);
2490 silc_buffer_free(idp);
2491 silc_free(channel_id);
2494 silc_server_command_free(cmd);
2497 /* Server side of INVITE command. Invites some client to join some channel.
2498 This command is also used to manage the invite list of the channel. */
2500 SILC_SERVER_CMD_FUNC(invite)
2502 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2503 SilcServer server = cmd->server;
2504 SilcSocketConnection sock = cmd->sock, dest_sock;
2505 SilcChannelClientEntry chl;
2506 SilcClientEntry sender, dest;
2507 SilcClientID *dest_id = NULL;
2508 SilcChannelEntry channel;
2509 SilcChannelID *channel_id = NULL;
2510 SilcIDListData idata;
2511 SilcBuffer idp, idp2, packet;
2512 unsigned char *tmp, *add, *del;
2514 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2516 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2518 /* Get Channel ID */
2519 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2521 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2522 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2525 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
2527 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2528 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2532 /* Get the channel entry */
2533 channel = silc_idlist_find_channel_by_id(server->local_list,
2536 channel = silc_idlist_find_channel_by_id(server->global_list,
2539 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2540 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
2546 /* Check whether the sender of this command is on the channel. */
2547 sender = (SilcClientEntry)sock->user_data;
2548 if (!sender || !silc_server_client_on_channel(sender, channel, &chl)) {
2549 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2550 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
2554 /* Check whether the channel is invite-only channel. If yes then the
2555 sender of this command must be at least channel operator. */
2556 if (channel->mode & SILC_CHANNEL_MODE_INVITE &&
2557 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
2558 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
2559 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2560 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
2565 /* Get destination client ID */
2566 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2571 dest_id = silc_id_payload_parse_id(tmp, len, NULL);
2573 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2574 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
2578 /* Get the client entry */
2579 dest = silc_server_get_client_resolve(server, dest_id, FALSE, &resolve);
2581 if (server->server_type != SILC_SERVER || !resolve) {
2582 silc_server_command_send_status_reply(
2583 cmd, SILC_COMMAND_INVITE,
2584 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0);
2588 /* The client info is being resolved. Reprocess this packet after
2589 receiving the reply to the query. */
2590 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2592 silc_server_command_invite,
2593 silc_server_command_dup(cmd));
2594 cmd->pending = TRUE;
2595 silc_free(channel_id);
2600 /* Check whether the requested client is already on the channel. */
2601 if (silc_server_client_on_channel(dest, channel, NULL)) {
2602 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2603 SILC_STATUS_ERR_USER_ON_CHANNEL,
2608 /* Get route to the client */
2609 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id,
2612 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2613 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2618 memset(invite, 0, sizeof(invite));
2619 strncat(invite, dest->nickname, strlen(dest->nickname));
2620 strncat(invite, "!", 1);
2621 strncat(invite, dest->username, strlen(dest->username));
2622 if (!strchr(dest->username, '@')) {
2623 strncat(invite, "@", 1);
2624 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2627 len = strlen(invite);
2628 if (!channel->invite_list)
2629 channel->invite_list = silc_calloc(len + 2,
2630 sizeof(*channel->invite_list));
2632 channel->invite_list = silc_realloc(channel->invite_list,
2633 sizeof(*channel->invite_list) *
2635 strlen(channel->invite_list) + 2));
2636 strncat(channel->invite_list, invite, len);
2637 strncat(channel->invite_list, ",", 1);
2639 if (!(dest->mode & SILC_UMODE_BLOCK_INVITE)) {
2640 /* Send notify to the client that is invited to the channel */
2641 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2642 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2643 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2645 SILC_NOTIFY_TYPE_INVITE, 3,
2646 idp->data, idp->len,
2647 channel->channel_name,
2648 strlen(channel->channel_name),
2649 idp2->data, idp2->len);
2650 silc_buffer_free(idp);
2651 silc_buffer_free(idp2);
2655 /* Add the client to the invite list of the channel */
2656 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2658 if (!channel->invite_list)
2659 channel->invite_list = silc_calloc(len + 2,
2660 sizeof(*channel->invite_list));
2662 channel->invite_list = silc_realloc(channel->invite_list,
2663 sizeof(*channel->invite_list) *
2665 strlen(channel->invite_list) + 2));
2666 if (add[len - 1] == ',')
2667 add[len - 1] = '\0';
2669 strncat(channel->invite_list, add, len);
2670 strncat(channel->invite_list, ",", 1);
2673 /* Get the invite to be removed and remove it from the list */
2674 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2675 if (del && channel->invite_list) {
2676 char *start, *end, *n;
2678 if (!strncmp(channel->invite_list, del,
2679 strlen(channel->invite_list) - 1)) {
2680 silc_free(channel->invite_list);
2681 channel->invite_list = NULL;
2683 start = strstr(channel->invite_list, del);
2684 if (start && strlen(start) >= len) {
2686 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2687 strncat(n, channel->invite_list, start - channel->invite_list);
2688 strncat(n, end + 1, ((channel->invite_list +
2689 strlen(channel->invite_list)) - end) - 1);
2690 silc_free(channel->invite_list);
2691 channel->invite_list = n;
2696 /* Send notify to the primary router */
2697 silc_server_send_notify_invite(server, SILC_PRIMARY_ROUTE(server),
2698 SILC_BROADCAST(server), channel,
2699 sender->id, add, del);
2701 /* Send command reply */
2702 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2706 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2707 SILC_STATUS_OK, 0, ident, 2,
2709 3, channel->invite_list,
2710 channel->invite_list ?
2711 strlen(channel->invite_list) : 0);
2714 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2715 SILC_STATUS_OK, 0, ident, 1,
2717 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2718 packet->data, packet->len, FALSE);
2719 silc_buffer_free(packet);
2723 silc_free(channel_id);
2724 silc_server_command_free(cmd);
2729 SilcSocketConnection sock;
2733 /* Quits connection to client. This gets called if client won't
2734 close the connection even when it has issued QUIT command. */
2736 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2738 QuitInternal q = (QuitInternal)context;
2740 /* Free all client specific data, such as client entry and entires
2741 on channels this client may be on. */
2742 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2744 q->sock->user_data = NULL;
2746 /* Close the connection on our side */
2747 silc_server_close_connection(q->server, q->sock);
2749 silc_free(q->signoff);
2753 /* Quits SILC session. This is the normal way to disconnect client. */
2755 SILC_SERVER_CMD_FUNC(quit)
2757 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2758 SilcServer server = cmd->server;
2759 SilcSocketConnection sock = cmd->sock;
2761 unsigned char *tmp = NULL;
2764 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2766 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2770 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2774 q = silc_calloc(1, sizeof(*q));
2777 q->signoff = tmp ? strdup(tmp) : NULL;
2779 /* We quit the connection with little timeout */
2780 silc_schedule_task_add(server->schedule, sock->sock,
2781 silc_server_command_quit_cb, (void *)q,
2782 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2785 silc_server_command_free(cmd);
2788 /* Server side of command KILL. This command is used by router operator
2789 to remove an client from the SILC Network temporarily. */
2791 SILC_SERVER_CMD_FUNC(kill)
2793 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2794 SilcServer server = cmd->server;
2795 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2796 SilcClientEntry remote_client;
2797 SilcClientID *client_id;
2798 unsigned char *tmp, *comment;
2799 SilcUInt32 tmp_len, tmp_len2;
2802 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2804 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
2807 /* KILL command works only on router */
2808 if (server->server_type != SILC_ROUTER) {
2809 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2810 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
2814 /* Check whether client has the permissions. */
2815 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2816 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2817 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
2821 /* Get the client ID */
2822 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2824 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2825 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2829 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2831 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2832 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2837 /* Get the client entry */
2838 remote_client = silc_idlist_find_client_by_id(server->local_list,
2839 client_id, TRUE, NULL);
2841 if (!remote_client) {
2842 remote_client = silc_idlist_find_client_by_id(server->global_list,
2843 client_id, TRUE, NULL);
2845 if (!remote_client) {
2846 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2847 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2854 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2858 /* Send reply to the sender */
2859 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2862 /* Check if anyone is watching this nickname */
2863 if (server->server_type == SILC_ROUTER)
2864 silc_server_check_watcher_list(server, client, NULL,
2865 SILC_NOTIFY_TYPE_KILLED);
2867 /* Now do the killing */
2868 silc_server_kill_client(server, remote_client, comment, client->id,
2872 silc_server_command_free(cmd);
2875 /* Server side of command INFO. This sends information about us to
2876 the client. If client requested specific server we will send the
2877 command to that server. */
2879 SILC_SERVER_CMD_FUNC(info)
2881 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2882 SilcServer server = cmd->server;
2883 SilcBuffer packet, idp;
2886 char *dest_server, *server_info = NULL, *server_name;
2887 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2888 SilcServerEntry entry = NULL;
2889 SilcServerID *server_id = NULL;
2891 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2893 /* Get server name */
2894 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2897 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2899 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2901 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2902 SILC_STATUS_ERR_NO_SERVER_ID, 0);
2908 /* Check whether we have this server cached */
2909 entry = silc_idlist_find_server_by_id(server->local_list,
2910 server_id, TRUE, NULL);
2912 entry = silc_idlist_find_server_by_id(server->global_list,
2913 server_id, TRUE, NULL);
2914 if (!entry && server->server_type != SILC_SERVER) {
2915 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2916 SILC_STATUS_ERR_NO_SUCH_SERVER,
2923 /* Some buggy servers has sent request to router about themselves. */
2924 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2927 if ((!dest_server && !server_id && !entry) || (entry &&
2928 entry == server->id_entry) ||
2929 (dest_server && !cmd->pending &&
2930 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2931 /* Send our reply */
2932 char info_string[256];
2934 memset(info_string, 0, sizeof(info_string));
2935 snprintf(info_string, sizeof(info_string),
2936 "location: %s server: %s admin: %s <%s>",
2937 server->config->server_info->location,
2938 server->config->server_info->server_type,
2939 server->config->server_info->admin,
2940 server->config->server_info->email);
2942 server_info = info_string;
2943 entry = server->id_entry;
2945 /* Check whether we have this server cached */
2946 if (!entry && dest_server) {
2947 entry = silc_idlist_find_server_by_name(server->global_list,
2948 dest_server, TRUE, NULL);
2950 entry = silc_idlist_find_server_by_name(server->local_list,
2951 dest_server, TRUE, NULL);
2955 if (!cmd->pending &&
2956 server->server_type != SILC_SERVER && entry && !entry->server_info) {
2957 /* Send to the server */
2959 SilcUInt16 old_ident;
2961 old_ident = silc_command_get_ident(cmd->payload);
2962 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2963 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2965 silc_server_packet_send(server, entry->connection,
2966 SILC_PACKET_COMMAND, cmd->packet->flags,
2967 tmpbuf->data, tmpbuf->len, TRUE);
2969 /* Reprocess this packet after received reply from router */
2970 silc_server_command_pending(server, SILC_COMMAND_INFO,
2971 silc_command_get_ident(cmd->payload),
2972 silc_server_command_info,
2973 silc_server_command_dup(cmd));
2974 cmd->pending = TRUE;
2975 silc_command_set_ident(cmd->payload, old_ident);
2976 silc_buffer_free(tmpbuf);
2980 if (!entry && !cmd->pending && !server->standalone) {
2981 /* Send to the primary router */
2983 SilcUInt16 old_ident;
2985 old_ident = silc_command_get_ident(cmd->payload);
2986 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2987 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2989 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
2990 SILC_PACKET_COMMAND, cmd->packet->flags,
2991 tmpbuf->data, tmpbuf->len, TRUE);
2993 /* Reprocess this packet after received reply from router */
2994 silc_server_command_pending(server, SILC_COMMAND_INFO,
2995 silc_command_get_ident(cmd->payload),
2996 silc_server_command_info,
2997 silc_server_command_dup(cmd));
2998 cmd->pending = TRUE;
2999 silc_command_set_ident(cmd->payload, old_ident);
3000 silc_buffer_free(tmpbuf);
3005 silc_free(server_id);
3008 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3009 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3013 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
3015 server_info = entry->server_info;
3016 server_name = entry->server_name;
3018 /* Send the reply */
3019 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
3020 SILC_STATUS_OK, 0, ident, 3,
3021 2, idp->data, idp->len,
3023 strlen(server_name),
3026 strlen(server_info) : 0);
3027 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3028 packet->data, packet->len, FALSE);
3030 silc_buffer_free(packet);
3031 silc_buffer_free(idp);
3034 silc_server_command_free(cmd);
3037 /* Server side of command PING. This just replies to the ping. */
3039 SILC_SERVER_CMD_FUNC(ping)
3041 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3042 SilcServer server = cmd->server;
3047 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
3050 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
3052 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3053 SILC_STATUS_ERR_NO_SERVER_ID, 0);
3056 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
3060 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
3061 /* Send our reply */
3062 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3065 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3066 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3073 silc_server_command_free(cmd);
3076 /* Server side of command STATS. */
3078 SILC_SERVER_CMD_FUNC(stats)
3080 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3081 SilcServer server = cmd->server;
3082 SilcServerID *server_id;
3085 SilcBuffer packet, stats;
3086 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3089 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1);
3092 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3094 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3095 SILC_STATUS_ERR_NO_SERVER_ID, 0);
3098 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3102 /* The ID must be ours */
3103 if (!SILC_ID_SERVER_COMPARE(server->id, server_id)) {
3104 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3105 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3106 silc_free(server_id);
3109 silc_free(server_id);
3111 /* If we are router then just send everything we got. If we are normal
3112 server then we'll send this to our router to get all the latest
3113 statistical information. */
3114 if (!cmd->pending && server->server_type != SILC_ROUTER &&
3115 !server->standalone) {
3116 /* Send request to our router */
3117 SilcBuffer idp = silc_id_payload_encode(server->router->id,
3119 packet = silc_command_payload_encode_va(SILC_COMMAND_STATS,
3120 ++server->cmd_ident, 1,
3121 1, idp->data, idp->len);
3122 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
3123 SILC_PACKET_COMMAND, 0, packet->data,
3124 packet->len, FALSE);
3126 /* Reprocess this packet after received reply from router */
3127 silc_server_command_pending(server, SILC_COMMAND_STATS,
3129 silc_server_command_stats,
3130 silc_server_command_dup(cmd));
3131 cmd->pending = TRUE;
3132 silc_buffer_free(packet);
3133 silc_buffer_free(idp);
3137 /* Send our reply to sender */
3138 uptime = time(NULL) - server->starttime;
3140 stats = silc_buffer_alloc_size(60);
3141 silc_buffer_format(stats,
3142 SILC_STR_UI_INT(server->starttime),
3143 SILC_STR_UI_INT(uptime),
3144 SILC_STR_UI_INT(server->stat.my_clients),
3145 SILC_STR_UI_INT(server->stat.my_channels),
3146 SILC_STR_UI_INT(server->stat.my_server_ops),
3147 SILC_STR_UI_INT(server->stat.my_router_ops),
3148 SILC_STR_UI_INT(server->stat.cell_clients),
3149 SILC_STR_UI_INT(server->stat.cell_channels),
3150 SILC_STR_UI_INT(server->stat.cell_servers),
3151 SILC_STR_UI_INT(server->stat.clients),
3152 SILC_STR_UI_INT(server->stat.channels),
3153 SILC_STR_UI_INT(server->stat.servers),
3154 SILC_STR_UI_INT(server->stat.routers),
3155 SILC_STR_UI_INT(server->stat.server_ops),
3156 SILC_STR_UI_INT(server->stat.router_ops),
3159 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_STATS,
3160 SILC_STATUS_OK, 0, ident, 2,
3162 3, stats->data, stats->len);
3163 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
3164 0, packet->data, packet->len, FALSE);
3165 silc_buffer_free(packet);
3166 silc_buffer_free(stats);
3169 silc_server_command_free(cmd);
3172 /* Internal routine to join channel. The channel sent to this function
3173 has been either created or resolved from ID lists. This joins the sent
3174 client to the channel. */
3176 static void silc_server_command_join_channel(SilcServer server,
3177 SilcServerCommandContext cmd,
3178 SilcChannelEntry channel,
3179 SilcClientID *client_id,
3183 const unsigned char *auth,
3184 SilcUInt32 auth_len)
3186 SilcSocketConnection sock = cmd->sock;
3188 SilcUInt32 tmp_len, user_count;
3189 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
3190 SilcClientEntry client;
3191 SilcChannelClientEntry chl;
3192 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
3193 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3194 char check[512], check2[512];
3195 bool founder = FALSE;
3197 unsigned char *fkey = NULL;
3198 SilcUInt32 fkey_len = 0;
3200 SILC_LOG_DEBUG(("Joining client to channel"));
3205 /* Get the client entry */
3206 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3207 client = (SilcClientEntry)sock->user_data;
3211 client = silc_server_get_client_resolve(server, client_id, FALSE,
3218 silc_server_command_send_status_reply(
3219 cmd, SILC_COMMAND_JOIN,
3220 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3224 /* The client info is being resolved. Reprocess this packet after
3225 receiving the reply to the query. */
3226 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
3228 silc_server_command_join,
3229 silc_server_command_dup(cmd));
3230 cmd->pending = TRUE;
3234 cmd->pending = FALSE;
3238 * Check founder auth payload if provided. If client can gain founder
3239 * privileges it can override various conditions on joining the channel,
3240 * and can have directly the founder mode set on the channel.
3242 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3243 SilcIDListData idata = (SilcIDListData)client;
3244 SilcChannelClientEntry chl2;
3245 SilcHashTableList htl;
3247 if (channel->founder_key && idata->public_key &&
3248 silc_pkcs_public_key_compare(channel->founder_key,
3249 idata->public_key)) {
3250 /* Check whether the client is to become founder */
3251 if (silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
3252 channel->founder_key, 0, server->sha1hash,
3253 client->id, SILC_ID_CLIENT)) {
3255 /* There cannot be anyone else as founder on the channel now. This
3256 client is definitely the founder due to this authentication */
3257 silc_hash_table_list(channel->user_list, &htl);
3258 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
3259 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
3260 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3261 silc_server_force_cumode_change(server, NULL, channel, chl2,
3265 silc_hash_table_list_reset(&htl);
3267 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3274 * Check channel modes
3278 memset(check, 0, sizeof(check));
3279 memset(check2, 0, sizeof(check2));
3280 strncat(check, client->nickname, strlen(client->nickname));
3281 strncat(check, "!", 1);
3282 strncat(check, client->username, strlen(client->username));
3283 if (!strchr(client->username, '@')) {
3284 strncat(check, "@", 1);
3285 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3288 strncat(check2, client->nickname, strlen(client->nickname));
3289 if (!strchr(client->nickname, '@')) {
3290 strncat(check2, "@", 1);
3291 strncat(check2, server->server_name, strlen(server->server_name));
3293 strncat(check2, "!", 1);
3294 strncat(check2, client->username, strlen(client->username));
3295 if (!strchr(client->username, '@')) {
3296 strncat(check2, "@", 1);
3297 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3300 /* Check invite list if channel is invite-only channel */
3301 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3302 if (!channel->invite_list ||
3303 (!silc_string_match(channel->invite_list, check) &&
3304 !silc_string_match(channel->invite_list, check2))) {
3305 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3306 SILC_STATUS_ERR_NOT_INVITED, 0);
3311 /* Check ban list if it exists. If the client's nickname, server,
3312 username and/or hostname is in the ban list the access to the
3313 channel is denied. */
3314 if (channel->ban_list) {
3315 if (silc_string_match(channel->ban_list, check) ||
3316 silc_string_match(channel->ban_list, check2)) {
3317 silc_server_command_send_status_reply(
3318 cmd, SILC_COMMAND_JOIN,
3319 SILC_STATUS_ERR_BANNED_FROM_CHANNEL, 0);
3324 /* Check user count limit if set. */
3325 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3326 if (silc_hash_table_count(channel->user_list) + 1 >
3327 channel->user_limit) {
3328 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3329 SILC_STATUS_ERR_CHANNEL_IS_FULL,
3336 /* Check the channel passphrase if set. */
3337 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3338 /* Get passphrase */
3339 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3341 passphrase = silc_memdup(tmp, tmp_len);
3343 if (!passphrase || !channel->passphrase ||
3344 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3345 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3346 SILC_STATUS_ERR_BAD_PASSWORD, 0);
3352 * Client is allowed to join to the channel. Make it happen.
3355 /* Check whether the client already is on the channel */
3356 if (silc_server_client_on_channel(client, channel, NULL)) {
3357 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3358 SILC_STATUS_ERR_USER_ON_CHANNEL, 0);
3362 /* Generate new channel key as protocol dictates */
3364 if (!silc_server_create_channel_key(server, channel, 0))
3367 /* Send the channel key. This is broadcasted to the channel but is not
3368 sent to the client who is joining to the channel. */
3369 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3370 silc_server_send_channel_key(server, NULL, channel,
3371 server->server_type == SILC_ROUTER ?
3372 FALSE : !server->standalone);
3375 /* Join the client to the channel by adding it to channel's user list.
3376 Add also the channel to client entry's channels list for fast cross-
3378 chl = silc_calloc(1, sizeof(*chl));
3380 chl->client = client;
3381 chl->channel = channel;
3382 silc_hash_table_add(channel->user_list, client, chl);
3383 silc_hash_table_add(client->channels, channel, chl);
3384 channel->user_count++;
3385 channel->disabled = FALSE;
3387 /* Get users on the channel */
3388 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3391 /* Encode Client ID Payload of the original client who wants to join */
3392 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3394 /* Encode command reply packet */
3395 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3396 SILC_PUT32_MSB(channel->mode, mode);
3397 SILC_PUT32_MSB(created, tmp2);
3398 SILC_PUT32_MSB(user_count, tmp3);
3400 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3401 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3402 keyp = silc_channel_key_payload_encode(silc_id_get_len(channel->id,
3405 strlen(channel->channel_key->
3407 channel->channel_key->cipher->name,
3408 channel->key_len / 8, channel->key);
3412 if (channel->founder_key)
3413 fkey = silc_pkcs_public_key_encode(channel->founder_key, &fkey_len);
3416 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3417 SILC_STATUS_OK, 0, ident, 14,
3418 2, channel->channel_name,
3419 strlen(channel->channel_name),
3420 3, chidp->data, chidp->len,
3421 4, clidp->data, clidp->len,
3424 7, keyp ? keyp->data : NULL,
3425 keyp ? keyp->len : 0,
3426 8, channel->ban_list,
3428 strlen(channel->ban_list) : 0,
3429 9, channel->invite_list,
3430 channel->invite_list ?
3431 strlen(channel->invite_list) : 0,
3434 strlen(channel->topic) : 0,
3435 11, silc_hmac_get_name(channel->hmac),
3436 strlen(silc_hmac_get_name(channel->
3439 13, user_list->data, user_list->len,
3440 14, mode_list->data,
3442 15, fkey, fkey_len);
3444 /* Send command reply */
3445 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3446 reply->data, reply->len, FALSE);
3448 /* Send JOIN notify to locally connected clients on the channel. If
3449 we are normal server then router will send or have sent JOIN notify
3450 already. However since we've added the client already to our channel
3451 we'll ignore it (in packet_receive.c) so we must send it here. If
3452 we are router then this will send it to local clients and local
3454 SILC_LOG_DEBUG(("Send JOIN notify to channel"));
3455 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3456 SILC_NOTIFY_TYPE_JOIN, 2,
3457 clidp->data, clidp->len,
3458 chidp->data, chidp->len);
3460 /* Update statistics */
3461 server->stat.my_chanclients++;
3462 if (server->server_type == SILC_ROUTER) {
3463 server->stat.cell_chanclients++;
3464 server->stat.chanclients++;
3467 if (!cmd->pending) {
3468 /* Send JOIN notify packet to our primary router */
3469 silc_server_send_notify_join(server, SILC_PRIMARY_ROUTE(server),
3470 SILC_BROADCAST(server), channel, client->id);
3473 /* Distribute the channel key to all backup routers. */
3474 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3475 keyp->data, keyp->len, FALSE, TRUE);
3477 /* If client became founder by providing correct founder auth data
3478 notify the mode change to the channel. */
3480 SILC_PUT32_MSB(chl->mode, mode);
3481 SILC_LOG_DEBUG(("Send CUMODE_CHANGE notify to channel"));
3482 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3483 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
3484 clidp->data, clidp->len,
3485 mode, 4, clidp->data, clidp->len,
3490 /* Set CUMODE notify type to network */
3492 silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
3493 SILC_BROADCAST(server), channel,
3494 chl->mode, client->id, SILC_ID_CLIENT,
3495 client->id, channel->founder_key);
3497 silc_buffer_free(reply);
3498 silc_buffer_free(clidp);
3499 silc_buffer_free(chidp);
3500 silc_buffer_free(keyp);
3501 silc_buffer_free(user_list);
3502 silc_buffer_free(mode_list);
3506 silc_free(passphrase);
3509 /* Server side of command JOIN. Joins client into requested channel. If
3510 the channel does not exist it will be created. */
3512 SILC_SERVER_CMD_FUNC(join)
3514 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3515 SilcServer server = cmd->server;
3516 unsigned char *auth;
3517 SilcUInt32 tmp_len, auth_len;
3518 char *tmp, *channel_name = NULL, *cipher, *hmac;
3519 SilcChannelEntry channel;
3520 SilcUInt32 umode = 0;
3521 bool created = FALSE, create_key = TRUE;
3522 SilcClientID *client_id;
3524 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3526 /* Get channel name */
3527 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3529 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3530 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3537 channel_name[255] = '\0';
3539 if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
3540 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3541 SILC_STATUS_ERR_BAD_CHANNEL, 0);
3545 /* Get Client ID of the client who is joining to the channel */
3546 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3548 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3549 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3553 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3555 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3556 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3561 /* Get cipher, hmac name and auth payload */
3562 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3563 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3564 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3566 /* See if the channel exists */
3567 channel = silc_idlist_find_channel_by_name(server->local_list,
3568 channel_name, NULL);
3570 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3571 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3573 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3574 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3579 silc_free(client_id);
3580 client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
3583 (channel->disabled && server->server_type != SILC_ROUTER)) {
3584 /* Channel not found */
3586 /* If we are standalone server we don't have a router, we just create
3587 the channel by ourselves. */
3588 if (server->standalone) {
3589 channel = silc_server_create_new_channel(server, server->id, cipher,
3590 hmac, channel_name, TRUE);
3592 silc_server_command_send_status_reply(
3593 cmd, SILC_COMMAND_JOIN,
3594 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
3596 silc_free(client_id);
3600 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3606 /* The channel does not exist on our server. If we are normal server
3607 we will send JOIN command to our router which will handle the
3608 joining procedure (either creates the channel if it doesn't exist
3609 or joins the client to it). */
3610 if (server->server_type != SILC_ROUTER) {
3612 SilcUInt16 old_ident;
3614 /* If this is pending command callback then we've resolved
3615 it and it didn't work, return since we've notified the
3616 client already in the command reply callback. */
3618 silc_free(client_id);
3622 old_ident = silc_command_get_ident(cmd->payload);
3623 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3624 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3626 /* Send JOIN command to our router */
3627 silc_server_packet_send(server, (SilcSocketConnection)
3628 SILC_PRIMARY_ROUTE(server),
3629 SILC_PACKET_COMMAND, cmd->packet->flags,
3630 tmpbuf->data, tmpbuf->len, TRUE);
3632 /* Reprocess this packet after received reply from router */
3633 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3634 silc_command_get_ident(cmd->payload),
3635 silc_server_command_join,
3636 silc_server_command_dup(cmd));
3637 cmd->pending = TRUE;
3638 silc_command_set_ident(cmd->payload, old_ident);
3639 silc_buffer_free(tmpbuf);
3640 silc_free(client_id);
3644 /* We are router and the channel does not seem exist so we will check
3645 our global list as well for the channel. */
3646 channel = silc_idlist_find_channel_by_name(server->global_list,
3647 channel_name, NULL);
3649 /* Channel really does not exist, create it */
3650 channel = silc_server_create_new_channel(server, server->id, cipher,
3651 hmac, channel_name, TRUE);
3653 silc_server_command_send_status_reply(
3654 cmd, SILC_COMMAND_JOIN,
3655 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
3656 silc_free(client_id);
3660 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3668 /* Channel not found */
3670 /* If the command came from router and we are normal server then
3671 something went wrong with the joining as the channel was not found.
3672 We can't do anything else but ignore this. */
3673 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3674 server->server_type != SILC_ROUTER) {
3675 silc_free(client_id);
3679 /* We are router and the channel does not seem exist so we will check
3680 our global list as well for the channel. */
3681 channel = silc_idlist_find_channel_by_name(server->global_list,
3682 channel_name, NULL);
3684 /* Channel really does not exist, create it */
3685 channel = silc_server_create_new_channel(server, server->id, cipher,
3686 hmac, channel_name, TRUE);
3688 silc_server_command_send_status_reply(
3689 cmd, SILC_COMMAND_JOIN,
3690 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
3691 silc_free(client_id);
3695 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3702 /* Check whether the channel was created by our router */
3703 if (cmd->pending && context2) {
3704 SilcServerCommandReplyContext reply = context2;
3706 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3707 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3708 SILC_GET32_MSB(created, tmp);
3709 if (silc_argument_get_arg_type(reply->args, 7, NULL))
3710 create_key = FALSE; /* Router returned the key already */
3712 if (silc_command_get_status(reply->payload, NULL, NULL) &&
3713 channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3714 /* Save channel passphrase, if user provided it successfully */
3717 pa = silc_argument_get_arg_type(cmd->args, 3, &pa_len);
3719 silc_free(channel->passphrase);
3720 channel->passphrase = silc_memdup(pa, pa_len);
3725 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
3726 !channel->disabled && !silc_hash_table_count(channel->user_list))
3730 /* If the channel does not have global users and is also empty the client
3731 will be the channel founder and operator. */
3732 if (!channel->disabled &&
3733 !channel->global_users && !silc_hash_table_count(channel->user_list))
3734 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3736 /* Join to the channel */
3737 silc_server_command_join_channel(server, cmd, channel, client_id,
3738 created, create_key, umode,
3741 silc_free(client_id);
3744 silc_server_command_free(cmd);
3747 /* Server side of command MOTD. Sends server's current "message of the
3748 day" to the client. */
3750 SILC_SERVER_CMD_FUNC(motd)
3752 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3753 SilcServer server = cmd->server;
3754 SilcBuffer packet, idp;
3755 char *motd, *dest_server;
3756 SilcUInt32 motd_len;
3757 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3759 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3761 /* Get server name */
3762 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3764 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3765 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3769 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3772 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3774 if (server->config && server->config->server_info &&
3775 server->config->server_info->motd_file) {
3777 motd = silc_file_readfile(server->config->server_info->motd_file,
3783 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3790 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3796 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3797 packet->data, packet->len, FALSE);
3798 silc_buffer_free(packet);
3799 silc_buffer_free(idp);
3801 SilcServerEntry entry;
3803 /* Check whether we have this server cached */
3804 entry = silc_idlist_find_server_by_name(server->global_list,
3805 dest_server, TRUE, NULL);
3807 entry = silc_idlist_find_server_by_name(server->local_list,
3808 dest_server, TRUE, NULL);
3811 if (server->server_type != SILC_SERVER && !cmd->pending &&
3812 entry && !entry->motd) {
3813 /* Send to the server */
3815 SilcUInt16 old_ident;
3817 old_ident = silc_command_get_ident(cmd->payload);
3818 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3819 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3821 silc_server_packet_send(server, entry->connection,
3822 SILC_PACKET_COMMAND, cmd->packet->flags,
3823 tmpbuf->data, tmpbuf->len, TRUE);
3825 /* Reprocess this packet after received reply from router */
3826 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3827 silc_command_get_ident(cmd->payload),
3828 silc_server_command_motd,
3829 silc_server_command_dup(cmd));
3830 cmd->pending = TRUE;
3831 silc_command_set_ident(cmd->payload, old_ident);
3832 silc_buffer_free(tmpbuf);
3836 if (!entry && !cmd->pending && !server->standalone) {
3837 /* Send to the primary router */
3839 SilcUInt16 old_ident;
3841 old_ident = silc_command_get_ident(cmd->payload);
3842 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3843 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3845 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
3846 SILC_PACKET_COMMAND, cmd->packet->flags,
3847 tmpbuf->data, tmpbuf->len, TRUE);
3849 /* Reprocess this packet after received reply from router */
3850 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3851 silc_command_get_ident(cmd->payload),
3852 silc_server_command_motd,
3853 silc_server_command_dup(cmd));
3854 cmd->pending = TRUE;
3855 silc_command_set_ident(cmd->payload, old_ident);
3856 silc_buffer_free(tmpbuf);
3861 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3862 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3866 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3867 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3868 SILC_STATUS_OK, 0, ident, 2,
3872 strlen(entry->motd) : 0);
3873 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3874 packet->data, packet->len, FALSE);
3875 silc_buffer_free(packet);
3876 silc_buffer_free(idp);
3880 silc_server_command_free(cmd);
3883 /* Server side of command UMODE. Client can use this command to set/unset
3884 user mode. Client actually cannot set itself to be as server/router
3885 operator so this can be used only to unset the modes. */
3887 SILC_SERVER_CMD_FUNC(umode)
3889 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3890 SilcServer server = cmd->server;
3891 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3893 unsigned char *tmp_mask, m[4];
3894 SilcUInt32 mask = 0;
3895 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3896 bool set_mask = FALSE;
3898 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
3901 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2);
3903 /* Get the client's mode mask */
3904 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3906 SILC_GET32_MSB(mask, tmp_mask);
3911 /* Check that mode changing is allowed. */
3912 if (!silc_server_check_umode_rights(server, client, mask)) {
3913 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3914 SILC_STATUS_ERR_PERM_DENIED, 0);
3918 /* Anonymous mode cannot be set by client */
3919 if (mask & SILC_UMODE_ANONYMOUS) {
3920 if (!(client->mode & SILC_UMODE_ANONYMOUS)) {
3921 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3922 SILC_STATUS_ERR_PERM_DENIED, 0);
3926 if (client->mode & SILC_UMODE_ANONYMOUS) {
3927 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3928 SILC_STATUS_ERR_PERM_DENIED, 0);
3933 /* Update statistics */
3934 if (mask & SILC_UMODE_GONE) {
3935 if (!(client->mode & SILC_UMODE_GONE))
3936 server->stat.my_aways++;
3938 if (client->mode & SILC_UMODE_GONE)
3939 server->stat.my_aways--;
3942 /* Change the mode */
3943 client->mode = mask;
3945 /* Send UMODE change to primary router */
3946 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
3947 SILC_BROADCAST(server), client->id,
3950 /* Check if anyone is watching this nickname */
3951 if (server->server_type == SILC_ROUTER)
3952 silc_server_check_watcher_list(server, client, NULL,
3953 SILC_NOTIFY_TYPE_UMODE_CHANGE);
3956 /* Send command reply to sender */
3957 SILC_PUT32_MSB(client->mode, m);
3958 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3959 SILC_STATUS_OK, 0, ident, 1,
3961 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3962 packet->data, packet->len, FALSE);
3963 silc_buffer_free(packet);
3966 silc_server_command_free(cmd);
3969 /* Server side command of CMODE. Changes channel mode */
3971 SILC_SERVER_CMD_FUNC(cmode)
3973 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3974 SilcServer server = cmd->server;
3975 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3976 SilcIDListData idata = (SilcIDListData)client;
3977 SilcChannelID *channel_id = NULL;
3978 SilcChannelEntry channel;
3979 SilcChannelClientEntry chl;
3980 SilcBuffer packet, cidp;
3981 unsigned char *tmp, *tmp_id, *tmp_mask;
3982 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3983 SilcUInt32 mode_mask = 0, old_mask = 0, tmp_len, tmp_len2;
3984 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3985 bool set_mask = FALSE;
3986 SilcPublicKey founder_key = NULL;
3987 unsigned char *fkey = NULL;
3988 SilcUInt32 fkey_len = 0;
3991 silc_server_command_free(cmd);
3995 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 7);
3997 /* Get Channel ID */
3998 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
4000 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4001 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4002 silc_server_command_free(cmd);
4005 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
4007 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4008 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4009 silc_server_command_free(cmd);
4013 /* Get channel entry */
4014 channel = silc_idlist_find_channel_by_id(server->local_list,
4017 channel = silc_idlist_find_channel_by_id(server->global_list,
4020 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4021 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4023 silc_free(channel_id);
4024 silc_server_command_free(cmd);
4028 old_mask = channel->mode;
4030 /* Get the channel mode mask */
4031 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4033 SILC_GET32_MSB(mode_mask, tmp_mask);
4037 /* Check whether this client is on the channel */
4038 if (!silc_server_client_on_channel(client, channel, &chl)) {
4039 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4040 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4044 /* Check that client has rights to change any requested channel modes */
4045 if (set_mask && !silc_server_check_cmode_rights(server, channel, chl,
4047 SILC_LOG_DEBUG(("Client does not have rights to change mode"));
4048 silc_server_command_send_status_reply(
4049 cmd, SILC_COMMAND_CMODE,
4050 (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) ?
4051 SILC_STATUS_ERR_NO_CHANNEL_PRIV :
4052 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV), 0);
4056 /* If mode mask was not sent as argument then merely return the current
4057 mode mask to the sender. */
4060 SILC_PUT32_MSB(channel->mode, m);
4061 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4062 SILC_STATUS_OK, 0, ident, 2,
4063 2, tmp_id, tmp_len2,
4065 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4066 packet->data, packet->len, FALSE);
4067 silc_buffer_free(packet);
4072 * Check the modes. Modes that requires nothing special operation are
4076 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
4077 /* Channel uses private keys to protect traffic. Client(s) has set the
4078 key locally they want to use, server does not know that key. */
4079 /* Nothing interesting to do here */
4081 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
4082 /* The mode is removed and we need to generate and distribute
4083 new channel key. Clients are not using private channel keys
4084 anymore after this. */
4086 /* Re-generate channel key */
4087 if (!silc_server_create_channel_key(server, channel, 0))
4090 /* Send the channel key. This sends it to our local clients and if
4091 we are normal server to our router as well. */
4092 silc_server_send_channel_key(server, NULL, channel,
4093 server->server_type == SILC_ROUTER ?
4094 FALSE : !server->standalone);
4096 cipher = channel->channel_key->cipher->name;
4097 hmac = (char *)silc_hmac_get_name(channel->hmac);
4101 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
4102 /* User limit is set on channel */
4103 SilcUInt32 user_limit;
4105 /* Get user limit */
4106 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
4108 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
4109 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4110 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4114 SILC_GET32_MSB(user_limit, tmp);
4115 channel->user_limit = user_limit;
4118 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
4119 /* User limit mode is unset. Remove user limit */
4120 channel->user_limit = 0;
4123 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
4124 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
4125 /* Passphrase has been set to channel */
4127 /* Get the passphrase */
4128 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
4130 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4131 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4135 /* Save the passphrase */
4136 passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
4139 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
4140 /* Passphrase mode is unset. remove the passphrase */
4141 silc_free(channel->passphrase);
4142 channel->passphrase = NULL;
4146 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
4147 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
4148 /* Cipher to use protect the traffic */
4149 SilcCipher newkey, oldkey;
4152 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
4154 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4155 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4159 /* Delete old cipher and allocate the new one */
4160 if (!silc_cipher_alloc(cipher, &newkey)) {
4161 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4162 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4166 oldkey = channel->channel_key;
4167 channel->channel_key = newkey;
4169 /* Re-generate channel key */
4170 if (!silc_server_create_channel_key(server, channel, 0)) {
4171 /* We don't have new key, revert to old one */
4172 channel->channel_key = oldkey;
4176 /* Remove old channel key for good */
4177 silc_cipher_free(oldkey);
4179 /* Send the channel key. This sends it to our local clients and if
4180 we are normal server to our router as well. */
4181 silc_server_send_channel_key(server, NULL, channel,
4182 server->server_type == SILC_ROUTER ?
4183 FALSE : !server->standalone);
4186 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
4187 /* Cipher mode is unset. Remove the cipher and revert back to
4189 SilcCipher newkey, oldkey;
4190 cipher = channel->cipher;
4192 /* Delete old cipher and allocate default one */
4193 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
4194 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4195 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4199 oldkey = channel->channel_key;
4200 channel->channel_key = newkey;
4202 /* Re-generate channel key */
4203 if (!silc_server_create_channel_key(server, channel, 0)) {
4204 /* We don't have new key, revert to old one */
4205 channel->channel_key = oldkey;
4209 /* Remove old channel key for good */
4210 silc_cipher_free(oldkey);
4212 /* Send the channel key. This sends it to our local clients and if
4213 we are normal server to our router as well. */
4214 silc_server_send_channel_key(server, NULL, channel,
4215 server->server_type == SILC_ROUTER ?
4216 FALSE : !server->standalone);
4220 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
4221 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
4222 /* HMAC to use protect the traffic */
4223 unsigned char hash[32];
4227 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4229 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4230 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4234 /* Delete old hmac and allocate the new one */
4235 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4236 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4237 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4241 silc_hmac_free(channel->hmac);
4242 channel->hmac = newhmac;
4244 /* Set the HMAC key out of current channel key. The client must do
4246 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4247 channel->key_len / 8, hash);
4248 silc_hmac_set_key(channel->hmac, hash,
4249 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4250 memset(hash, 0, sizeof(hash));
4253 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4254 /* Hmac mode is unset. Remove the hmac and revert back to
4257 unsigned char hash[32];
4258 hmac = channel->hmac_name;
4260 /* Delete old hmac and allocate default one */
4261 silc_hmac_free(channel->hmac);
4262 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4263 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4264 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4268 silc_hmac_free(channel->hmac);
4269 channel->hmac = newhmac;
4271 /* Set the HMAC key out of current channel key. The client must do
4273 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4274 channel->key_len / 8,
4276 silc_hmac_set_key(channel->hmac, hash,
4277 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4278 memset(hash, 0, sizeof(hash));
4282 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4283 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4284 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4285 /* Set the founder authentication */
4286 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4288 silc_server_command_send_status_reply(
4289 cmd, SILC_COMMAND_CMODE,
4290 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4294 /* Verify the payload before setting the mode */
4295 if (!silc_auth_verify_data(tmp, tmp_len, SILC_AUTH_PUBLIC_KEY,
4296 idata->public_key, 0, server->sha1hash,
4297 client->id, SILC_ID_CLIENT)) {
4298 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4299 SILC_STATUS_ERR_AUTH_FAILED,
4304 /* Save the public key */
4305 channel->founder_key = silc_pkcs_public_key_copy(idata->public_key);
4306 if (!channel->founder_key) {
4307 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4308 SILC_STATUS_ERR_AUTH_FAILED,
4313 founder_key = channel->founder_key;
4314 fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
4316 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4317 SILC_STATUS_ERR_AUTH_FAILED,
4319 silc_pkcs_public_key_free(channel->founder_key);
4320 channel->founder_key = NULL;
4326 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4327 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4328 if (channel->founder_key)
4329 silc_pkcs_public_key_free(channel->founder_key);
4330 channel->founder_key = NULL;
4335 /* Finally, set the mode */
4336 old_mask = channel->mode = mode_mask;
4338 /* Send CMODE_CHANGE notify. */
4339 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4340 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4341 SILC_NOTIFY_TYPE_CMODE_CHANGE, 6,
4342 cidp->data, cidp->len,
4344 cipher, cipher ? strlen(cipher) : 0,
4345 hmac, hmac ? strlen(hmac) : 0,
4346 passphrase, passphrase ?
4347 strlen(passphrase) : 0,
4350 /* Set CMODE notify type to network */
4351 silc_server_send_notify_cmode(server, SILC_PRIMARY_ROUTE(server),
4352 SILC_BROADCAST(server), channel,
4353 mode_mask, client->id, SILC_ID_CLIENT,
4354 cipher, hmac, passphrase, founder_key);
4356 /* Send command reply to sender */
4357 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4358 SILC_STATUS_OK, 0, ident, 2,
4359 2, tmp_id, tmp_len2,
4361 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4362 packet->data, packet->len, FALSE);
4364 silc_buffer_free(packet);
4365 silc_buffer_free(cidp);
4368 channel->mode = old_mask;
4370 silc_free(channel_id);
4371 silc_server_command_free(cmd);
4374 /* Server side of CUMODE command. Changes client's mode on a channel. */
4376 SILC_SERVER_CMD_FUNC(cumode)
4378 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4379 SilcServer server = cmd->server;
4380 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4381 SilcIDListData idata = (SilcIDListData)client;
4382 SilcChannelID *channel_id;
4383 SilcClientID *client_id;
4384 SilcChannelEntry channel;
4385 SilcClientEntry target_client;
4386 SilcChannelClientEntry chl;
4387 SilcBuffer packet, idp;
4388 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4389 SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4391 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4392 SilcPublicKey founder_key = NULL;
4393 unsigned char *fkey = NULL;
4394 SilcUInt32 fkey_len = 0;
4399 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4401 /* Get Channel ID */
4402 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4404 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4405 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4408 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
4410 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4411 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4415 /* Get channel entry */
4416 channel = silc_idlist_find_channel_by_id(server->local_list,
4419 channel = silc_idlist_find_channel_by_id(server->global_list,
4422 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4423 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4429 /* Check whether sender is on the channel */
4430 if (!silc_server_client_on_channel(client, channel, &chl)) {
4431 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4432 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4435 sender_mask = chl->mode;
4437 /* Get the target client's channel mode mask */
4438 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4440 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4441 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4445 SILC_GET32_MSB(target_mask, tmp_mask);
4447 /* Get target Client ID */
4448 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4450 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4451 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4454 client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
4456 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4457 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4461 /* Get target client's entry */
4462 target_client = silc_idlist_find_client_by_id(server->local_list,
4463 client_id, TRUE, NULL);
4464 if (!target_client) {
4465 target_client = silc_idlist_find_client_by_id(server->global_list,
4466 client_id, TRUE, NULL);
4469 if (target_client != client &&
4470 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4471 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4472 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4473 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
4477 /* Check whether target client is on the channel */
4478 if (target_client != client) {
4479 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4480 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4481 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL, 0);
4490 /* If the target client is founder, no one else can change their mode
4492 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4493 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4494 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
4499 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4500 if (target_client != client) {
4501 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4502 SILC_STATUS_ERR_NOT_YOU, 0);
4506 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4507 /* The client tries to claim the founder rights. */
4508 unsigned char *tmp_auth;
4509 SilcUInt32 tmp_auth_len;
4510 SilcChannelClientEntry chl2;
4511 SilcHashTableList htl;
4513 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4514 !channel->founder_key || !idata->public_key ||
4515 !silc_pkcs_public_key_compare(channel->founder_key,
4516 idata->public_key)) {
4517 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4518 SILC_STATUS_ERR_AUTH_FAILED, 0);
4522 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4524 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4525 SILC_STATUS_ERR_AUTH_FAILED, 0);
4529 /* Verify the authentication payload */
4530 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len, SILC_AUTH_PUBLIC_KEY,
4531 channel->founder_key, 0, server->sha1hash,
4532 client->id, SILC_ID_CLIENT)) {
4533 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4534 SILC_STATUS_ERR_AUTH_FAILED, 0);
4539 founder_key = channel->founder_key;
4540 fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
4542 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4543 SILC_STATUS_ERR_AUTH_FAILED, 0);
4547 /* There cannot be anyone else as founder on the channel now. This
4548 client is definitely the founder due to this authentication */
4549 silc_hash_table_list(channel->user_list, &htl);
4550 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
4551 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
4552 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4553 silc_server_force_cumode_change(server, NULL, channel, chl2,
4557 silc_hash_table_list_reset(&htl);
4559 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4562 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4563 if (target_client == client) {
4564 /* Remove channel founder rights from itself */
4565 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4568 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4569 SILC_STATUS_ERR_NOT_YOU, 0);
4575 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4576 /* Promote to operator */
4577 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4578 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4579 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4580 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4581 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
4586 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4590 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4591 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4592 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4593 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4594 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
4599 /* Demote to normal user */
4600 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4605 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4606 if (target_client != client) {
4607 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4608 SILC_STATUS_ERR_NOT_YOU, 0);
4612 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
4613 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4617 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4618 if (target_client != client) {
4619 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4620 SILC_STATUS_ERR_NOT_YOU, 0);
4624 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4629 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4630 if (target_client != client) {
4631 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4632 SILC_STATUS_ERR_NOT_YOU, 0);
4636 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)) {
4637 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4641 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4642 if (target_client != client) {
4643 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4644 SILC_STATUS_ERR_NOT_YOU, 0);
4648 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4653 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4654 if (target_client != client) {
4655 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4656 SILC_STATUS_ERR_NOT_YOU, 0);
4660 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)) {
4661 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4665 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4666 if (target_client != client) {
4667 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4668 SILC_STATUS_ERR_NOT_YOU, 0);
4672 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4677 if (target_mask & SILC_CHANNEL_UMODE_QUIET) {
4678 if (!(chl->mode & SILC_CHANNEL_UMODE_QUIET)) {
4679 if (client == target_client) {
4680 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4681 SILC_STATUS_ERR_PERM_DENIED, 0);
4684 chl->mode |= SILC_CHANNEL_UMODE_QUIET;
4688 if (chl->mode & SILC_CHANNEL_UMODE_QUIET) {
4689 if (client == target_client) {
4690 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4691 SILC_STATUS_ERR_PERM_DENIED, 0);
4694 chl->mode &= ~SILC_CHANNEL_UMODE_QUIET;
4699 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4700 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4702 /* Send notify to channel, notify only if mode was actually changed. */
4704 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4705 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
4706 idp->data, idp->len,
4711 /* Set CUMODE notify type to network */
4712 silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
4713 SILC_BROADCAST(server), channel,
4714 target_mask, client->id, SILC_ID_CLIENT,
4715 target_client->id, founder_key);
4718 /* Send command reply to sender */
4719 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4720 SILC_STATUS_OK, 0, ident, 3,
4722 3, tmp_ch_id, tmp_ch_len,
4723 4, tmp_id, tmp_len);
4724 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4725 packet->data, packet->len, FALSE);
4727 silc_buffer_free(packet);
4728 silc_free(channel_id);
4729 silc_free(client_id);
4730 silc_buffer_free(idp);
4734 silc_server_command_free(cmd);
4737 /* Server side of KICK command. Kicks client out of channel. */
4739 SILC_SERVER_CMD_FUNC(kick)
4741 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4742 SilcServer server = cmd->server;
4743 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4744 SilcClientEntry target_client;
4745 SilcChannelID *channel_id;
4746 SilcClientID *client_id;
4747 SilcChannelEntry channel;
4748 SilcChannelClientEntry chl;
4750 SilcUInt32 tmp_len, target_idp_len;
4751 unsigned char *tmp, *comment, *target_idp;
4756 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4758 /* Get Channel ID */
4759 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4761 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4762 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4765 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4767 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4768 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4772 /* Get channel entry */
4773 channel = silc_idlist_find_channel_by_id(server->local_list,
4776 channel = silc_idlist_find_channel_by_id(server->local_list,
4779 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4780 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4786 /* Check whether sender is on the channel */
4787 if (!silc_server_client_on_channel(client, channel, &chl)) {
4788 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4789 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4793 /* Check that the kicker is channel operator or channel founder */
4794 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
4795 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4796 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4797 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
4801 /* Get target Client ID */
4802 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4804 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4805 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4808 client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
4810 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4811 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4815 /* Get target client's entry */
4816 target_client = silc_idlist_find_client_by_id(server->local_list,
4817 client_id, TRUE, NULL);
4818 if (!target_client) {
4819 target_client = silc_idlist_find_client_by_id(server->global_list,
4820 client_id, TRUE, NULL);
4823 /* Check whether target client is on the channel */
4824 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4825 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4826 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL,
4831 /* Check that the target client is not channel founder. Channel founder
4832 cannot be kicked from the channel. */
4833 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4834 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4835 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
4842 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4846 /* Send command reply to sender */
4847 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4850 /* Send KICKED notify to local clients on the channel */
4851 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4852 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4853 SILC_NOTIFY_TYPE_KICKED, 3,
4854 target_idp, target_idp_len,
4855 comment, comment ? strlen(comment) : 0,
4856 idp->data, idp->len);
4857 silc_buffer_free(idp);
4859 /* Send KICKED notify to primary route */
4860 silc_server_send_notify_kicked(server, SILC_PRIMARY_ROUTE(server),
4861 SILC_BROADCAST(server), channel,
4862 target_client->id, client->id, comment);
4864 /* Remove the client from the channel. If the channel does not exist
4865 after removing the client then the client kicked itself off the channel
4866 and we don't have to send anything after that. */
4867 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4868 target_client, FALSE))
4871 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4872 /* Re-generate channel key */
4873 if (!silc_server_create_channel_key(server, channel, 0))
4876 /* Send the channel key to the channel. The key of course is not sent
4877 to the client who was kicked off the channel. */
4878 silc_server_send_channel_key(server, target_client->connection, channel,
4879 server->server_type == SILC_ROUTER ?
4880 FALSE : !server->standalone);
4884 silc_server_command_free(cmd);
4887 /* Server side of OPER command. Client uses this comand to obtain server
4888 operator privileges to this server/router. */
4890 SILC_SERVER_CMD_FUNC(oper)
4892 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4893 SilcServer server = cmd->server;
4894 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4895 unsigned char *username, *auth;
4897 SilcServerConfigAdmin *admin;
4898 SilcIDListData idata = (SilcIDListData)client;
4899 bool result = FALSE;
4900 SilcPublicKey cached_key;
4902 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
4905 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4907 /* Get the username */
4908 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4910 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4911 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4916 /* Get the admin configuration */
4917 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4918 username, client->nickname);
4920 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4921 username, client->nickname);
4923 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4924 SILC_STATUS_ERR_AUTH_FAILED,
4930 /* Get the authentication payload */
4931 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4933 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4934 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4939 /* Verify the authentication data. If both passphrase and public key
4940 is set then try both of them. */
4941 if (admin->passphrase)
4942 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4943 admin->passphrase, admin->passphrase_len,
4944 idata->hash, client->id, SILC_ID_CLIENT);
4945 if (!result && admin->publickeys) {
4946 cached_key = silc_server_get_public_key(server, admin->publickeys);
4949 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4950 cached_key, 0, idata->hash,
4951 client->id, SILC_ID_CLIENT);
4954 /* Authentication failed */
4955 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4956 SILC_STATUS_ERR_AUTH_FAILED,
4961 /* Client is now server operator */
4962 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4964 /* Update statistics */
4965 if (SILC_IS_LOCAL(client))
4966 server->stat.my_server_ops++;
4967 if (server->server_type == SILC_ROUTER)
4968 server->stat.server_ops++;
4970 /* Send UMODE change to primary router */
4971 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
4972 SILC_BROADCAST(server), client->id,
4975 /* Check if anyone is watching this nickname */
4976 if (server->server_type == SILC_ROUTER)
4977 silc_server_check_watcher_list(server, client, NULL,
4978 SILC_NOTIFY_TYPE_UMODE_CHANGE);
4980 /* Send reply to the sender */
4981 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4985 silc_server_command_free(cmd);
4988 SILC_TASK_CALLBACK(silc_server_command_detach_cb)
4990 QuitInternal q = (QuitInternal)context;
4991 SilcClientID *client_id = (SilcClientID *)q->sock;
4992 SilcClientEntry client;
4993 SilcSocketConnection sock;
4995 client = silc_idlist_find_client_by_id(q->server->local_list, client_id,
4997 if (client && client->connection) {
4998 sock = client->connection;
5000 /* If there is pending outgoing data for the client then purge it
5001 to the network before closing connection. */
5002 silc_server_packet_queue_purge(q->server, sock);
5004 /* Close the connection on our side */
5005 client->router = NULL;
5006 client->connection = NULL;
5007 sock->user_data = NULL;
5008 silc_server_close_connection(q->server, sock);
5011 silc_free(client_id);
5015 SILC_TASK_CALLBACK(silc_server_command_detach_timeout)
5017 QuitInternal q = (QuitInternal)context;
5018 SilcClientID *client_id = (SilcClientID *)q->sock;
5019 SilcClientEntry client;
5021 client = silc_idlist_find_client_by_id(q->server->local_list, client_id,
5023 if (client && client->mode & SILC_UMODE_DETACHED) {
5024 SILC_LOG_DEBUG(("Detach timeout"));
5025 silc_server_free_client_data(q->server, NULL, client, TRUE,
5029 silc_free(client_id);
5033 /* Server side of DETACH command. Detached the client from the network
5034 by closing the connection but preserving the session. */
5036 SILC_SERVER_CMD_FUNC(detach)
5038 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5039 SilcServer server = cmd->server;
5040 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5043 if (server->config->detach_disabled) {
5044 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
5045 SILC_STATUS_ERR_UNKNOWN_COMMAND, 0);
5049 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
5052 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
5054 /* Remove operator privileges, since the client may resume in some
5055 other server which to it does not have operator privileges. */
5056 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
5057 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
5059 /* Send the user mode notify to notify that client is detached */
5060 client->mode |= SILC_UMODE_DETACHED;
5061 client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
5062 client->last_command = 0;
5063 client->fast_command = 0;
5064 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
5065 SILC_BROADCAST(server), client->id,
5067 server->stat.my_detached++;
5069 /* Check if anyone is watching this nickname */
5070 if (server->server_type == SILC_ROUTER)
5071 silc_server_check_watcher_list(server, client, NULL,
5072 SILC_NOTIFY_TYPE_UMODE_CHANGE);
5074 q = silc_calloc(1, sizeof(*q));
5076 q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
5077 silc_schedule_task_add(server->schedule, 0, silc_server_command_detach_cb,
5078 q, 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
5080 if (server->config->detach_timeout) {
5081 q = silc_calloc(1, sizeof(*q));
5083 q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
5084 silc_schedule_task_add(server->schedule, 0,
5085 silc_server_command_detach_timeout,
5086 q, server->config->detach_timeout * 60,
5087 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
5090 /* Send reply to the sender */
5091 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
5095 silc_server_command_free(cmd);
5098 /* Server side of WATCH command. */
5100 SILC_SERVER_CMD_FUNC(watch)
5102 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5103 SilcServer server = cmd->server;
5104 char *add_nick, *del_nick;
5105 SilcUInt32 add_nick_len, del_nick_len, tmp_len;
5107 unsigned char hash[16], *tmp;
5108 SilcClientEntry client;
5109 SilcClientID *client_id = NULL;
5111 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WATCH, cmd, 1, 3);
5113 if (server->server_type == SILC_SERVER && !server->standalone) {
5114 if (!cmd->pending) {
5115 /* Send the command to router */
5117 SilcUInt16 old_ident;
5119 old_ident = silc_command_get_ident(cmd->payload);
5120 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5121 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5123 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5124 SILC_PACKET_COMMAND, cmd->packet->flags,
5125 tmpbuf->data, tmpbuf->len, TRUE);
5127 /* Reprocess this packet after received reply from router */
5128 silc_server_command_pending(server, SILC_COMMAND_WATCH,
5129 silc_command_get_ident(cmd->payload),
5130 silc_server_command_watch,
5131 silc_server_command_dup(cmd));
5132 cmd->pending = TRUE;
5133 silc_command_set_ident(cmd->payload, old_ident);
5134 silc_buffer_free(tmpbuf);
5135 } else if (context2) {
5136 /* Received reply from router, just send same data to the client. */
5137 SilcServerCommandReplyContext reply = context2;
5139 silc_command_get_status(reply->payload, &status, NULL);
5140 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, status,
5147 /* We are router and keep the watch list for local cell */
5149 /* Get the client ID */
5150 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5152 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5153 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5157 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
5159 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5160 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5165 /* Get the client entry which must be in local list */
5166 client = silc_idlist_find_client_by_id(server->local_list,
5167 client_id, TRUE, NULL);
5169 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5170 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5176 add_nick = silc_argument_get_arg_type(cmd->args, 2, &add_nick_len);
5177 del_nick = silc_argument_get_arg_type(cmd->args, 3, &del_nick_len);
5178 if (!add_nick && !del_nick) {
5179 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5180 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5185 if (add_nick && add_nick_len > 128)
5186 add_nick[128] = '\0';
5187 if (del_nick && del_nick_len > 128)
5188 del_nick[128] = '\0';
5190 memset(nick, 0, sizeof(nick));
5192 /* Add new nickname to be watched in our cell */
5194 if (silc_server_name_bad_chars(add_nick, strlen(add_nick)) == TRUE) {
5195 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5196 SILC_STATUS_ERR_BAD_NICKNAME, 0);
5200 /* Hash the nick, we have the hash saved, not nicks because we can
5201 do one to one mapping to the nick from Client ID hash this way. */
5202 silc_to_lower(add_nick, nick, sizeof(nick) - 1);
5203 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
5205 /* Check whether this client is already watching this nickname */
5206 if (silc_hash_table_find_by_context(server->watcher_list, hash,
5208 /* Nickname is alredy being watched for this client */
5209 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5210 SILC_STATUS_ERR_NICKNAME_IN_USE,
5215 /* Get the nickname from the watcher list and use the same key in
5216 new entries as well. If key doesn't exist then create it. */
5217 if (!silc_hash_table_find(server->watcher_list, hash, (void **)&tmp, NULL))
5218 tmp = silc_memdup(hash, CLIENTID_HASH_LEN);
5220 /* Add the client to the watcher list with the specified nickname hash. */
5221 silc_hash_table_add(server->watcher_list, tmp, client);
5224 /* Delete nickname from watch list */
5226 if (silc_server_name_bad_chars(del_nick, strlen(del_nick)) == TRUE) {
5227 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5228 SILC_STATUS_ERR_BAD_NICKNAME, 0);
5232 /* Hash the nick, we have the hash saved, not nicks because we can
5233 do one to one mapping to the nick from Client ID hash this way. */
5234 silc_to_lower(del_nick, nick, sizeof(nick) - 1);
5235 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
5237 /* Check that this client is watching for this nickname */
5238 if (!silc_hash_table_find_by_context(server->watcher_list, hash,
5239 client, (void **)&tmp)) {
5240 /* Nickname is alredy being watched for this client */
5241 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5242 SILC_STATUS_ERR_NO_SUCH_NICK, 0);
5246 /* Delete the nickname from the watcher list. */
5247 silc_hash_table_del_by_context(server->watcher_list, hash, client);
5249 /* Now check whether there still exists entries with this key, if not
5250 then free the key to not leak memory. */
5251 if (!silc_hash_table_find(server->watcher_list, hash, NULL, NULL))
5255 /* Distribute the watch list to backup routers too */
5256 if (server->backup) {
5258 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5259 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5260 silc_server_backup_send(server, NULL, SILC_PACKET_COMMAND,
5261 cmd->packet->flags, tmpbuf->data, tmpbuf->len,
5263 silc_buffer_free(tmpbuf);
5266 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5270 silc_free(client_id);
5271 silc_server_command_free(cmd);
5274 /* Server side of SILCOPER command. Client uses this comand to obtain router
5275 operator privileges to this router. */
5277 SILC_SERVER_CMD_FUNC(silcoper)
5279 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5280 SilcServer server = cmd->server;
5281 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5282 unsigned char *username, *auth;
5284 SilcServerConfigAdmin *admin;
5285 SilcIDListData idata = (SilcIDListData)client;
5286 bool result = FALSE;
5287 SilcPublicKey cached_key;
5289 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
5292 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
5294 if (server->server_type != SILC_ROUTER) {
5295 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5296 SILC_STATUS_ERR_AUTH_FAILED, 0);
5300 /* Get the username */
5301 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5303 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5304 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5309 /* Get the admin configuration */
5310 admin = silc_server_config_find_admin(server, cmd->sock->ip,
5311 username, client->nickname);
5313 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
5314 username, client->nickname);
5316 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5317 SILC_STATUS_ERR_AUTH_FAILED, 0);
5322 /* Get the authentication payload */
5323 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5325 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5326 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5331 /* Verify the authentication data. If both passphrase and public key
5332 is set then try both of them. */
5333 if (admin->passphrase)
5334 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
5335 admin->passphrase, admin->passphrase_len,
5336 idata->hash, client->id, SILC_ID_CLIENT);
5337 if (!result && admin->publickeys) {
5338 cached_key = silc_server_get_public_key(server, admin->publickeys);
5341 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
5342 cached_key, 0, idata->hash,
5343 client->id, SILC_ID_CLIENT);
5346 /* Authentication failed */
5347 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
5348 SILC_STATUS_ERR_AUTH_FAILED, 0);
5352 /* Client is now router operator */
5353 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
5355 /* Update statistics */
5356 if (SILC_IS_LOCAL(client))
5357 server->stat.my_router_ops++;
5358 if (server->server_type == SILC_ROUTER)
5359 server->stat.router_ops++;
5361 /* Send UMODE change to primary router */
5362 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
5363 SILC_BROADCAST(server), client->id,
5366 /* Check if anyone is watching this nickname */
5367 if (server->server_type == SILC_ROUTER)
5368 silc_server_check_watcher_list(server, client, NULL,
5369 SILC_NOTIFY_TYPE_UMODE_CHANGE);
5371 /* Send reply to the sender */
5372 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5376 silc_server_command_free(cmd);
5379 /* Server side of command BAN. This is used to manage the ban list of the
5380 channel. To add clients and remove clients from the ban list. */
5382 SILC_SERVER_CMD_FUNC(ban)
5384 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5385 SilcServer server = cmd->server;
5386 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5388 SilcChannelEntry channel;
5389 SilcChannelClientEntry chl;
5390 SilcChannelID *channel_id = NULL;
5391 unsigned char *id, *add, *del;
5392 SilcUInt32 id_len, tmp_len;
5393 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5395 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
5398 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
5400 /* Get Channel ID */
5401 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
5403 channel_id = silc_id_payload_parse_id(id, id_len, NULL);
5405 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5406 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5411 /* Get channel entry. The server must know about the channel since the
5412 client is expected to be on the channel. */
5413 channel = silc_idlist_find_channel_by_id(server->local_list,
5416 channel = silc_idlist_find_channel_by_id(server->global_list,
5419 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5420 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5426 /* Check whether this client is on the channel */
5427 if (!silc_server_client_on_channel(client, channel, &chl)) {
5428 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5429 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5433 /* The client must be at least channel operator. */
5434 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
5435 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5436 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
5440 /* Get the new ban and add it to the ban list */
5441 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5443 if (!channel->ban_list)
5444 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
5446 channel->ban_list = silc_realloc(channel->ban_list,
5447 sizeof(*channel->ban_list) *
5449 strlen(channel->ban_list) + 2));
5450 if (add[tmp_len - 1] == ',')
5451 add[tmp_len - 1] = '\0';
5453 strncat(channel->ban_list, add, tmp_len);
5454 strncat(channel->ban_list, ",", 1);
5457 /* Get the ban to be removed and remove it from the list */
5458 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
5459 if (del && channel->ban_list) {
5460 char *start, *end, *n;
5462 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
5463 silc_free(channel->ban_list);
5464 channel->ban_list = NULL;
5466 start = strstr(channel->ban_list, del);
5467 if (start && strlen(start) >= tmp_len) {
5468 end = start + tmp_len;
5469 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
5470 strncat(n, channel->ban_list, start - channel->ban_list);
5471 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
5473 silc_free(channel->ban_list);
5474 channel->ban_list = n;
5479 /* Send the BAN notify type to our primary router. */
5481 silc_server_send_notify_ban(server, SILC_PRIMARY_ROUTE(server),
5482 SILC_BROADCAST(server), channel, add, del);
5484 /* Send the reply back to the client */
5486 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
5487 SILC_STATUS_OK, 0, ident, 2,
5489 3, channel->ban_list,
5491 strlen(channel->ban_list) -1 : 0);
5492 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5493 packet->data, packet->len, FALSE);
5495 silc_buffer_free(packet);
5498 silc_free(channel_id);
5499 silc_server_command_free(cmd);
5502 /* Server side command of LEAVE. Removes client from a channel. */
5504 SILC_SERVER_CMD_FUNC(leave)
5506 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5507 SilcServer server = cmd->server;
5508 SilcSocketConnection sock = cmd->sock;
5509 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
5510 SilcChannelID *id = NULL;
5511 SilcChannelEntry channel;
5515 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !id_entry)
5518 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
5520 /* Get Channel ID */
5521 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
5523 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5524 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5527 id = silc_id_payload_parse_id(tmp, len, NULL);
5529 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5530 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5534 /* Get channel entry */
5535 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5537 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5539 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5540 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5546 /* Check whether this client is on the channel */
5547 if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
5548 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5549 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5553 /* Notify routers that they should remove this client from their list
5554 of clients on the channel. Send LEAVE notify type. */
5555 silc_server_send_notify_leave(server, SILC_PRIMARY_ROUTE(server),
5556 SILC_BROADCAST(server), channel, id_entry->id);
5558 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
5559 SILC_STATUS_OK, 0, 2, tmp, len);
5561 /* Remove client from channel */
5562 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5564 /* If the channel does not exist anymore we won't send anything */
5567 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5568 /* Re-generate channel key */
5569 if (!silc_server_create_channel_key(server, channel, 0))
5572 /* Send the channel key */
5573 silc_server_send_channel_key(server, NULL, channel,
5574 server->server_type == SILC_ROUTER ?
5575 FALSE : !server->standalone);
5580 silc_server_command_free(cmd);
5583 /* Server side of command USERS. Resolves clients and their USERS currently
5584 joined on the requested channel. The list of Client ID's and their modes
5585 on the channel is sent back. */
5587 SILC_SERVER_CMD_FUNC(users)
5589 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5590 SilcServer server = cmd->server;
5591 SilcChannelEntry channel;
5592 SilcChannelID *id = NULL;
5593 SilcBuffer packet, idp;
5594 unsigned char *channel_id;
5595 SilcUInt32 channel_id_len;
5596 SilcBuffer client_id_list;
5597 SilcBuffer client_mode_list;
5598 unsigned char lc[4];
5599 SilcUInt32 list_count = 0;
5600 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5603 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5605 /* Get Channel ID */
5606 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5608 /* Get channel name */
5609 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5611 if (!channel_id && !channel_name) {
5612 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5613 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5618 id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
5620 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5621 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5626 /* If we are server and we don't know about this channel we will send
5627 the command to our router. If we know about the channel then we also
5628 have the list of users already. */
5630 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5632 channel = silc_idlist_find_channel_by_name(server->local_list,
5633 channel_name, NULL);
5635 if (!channel || (!server->standalone && (channel->disabled ||
5636 !channel->users_resolved))) {
5637 if (server->server_type != SILC_ROUTER && !server->standalone &&
5641 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5642 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5644 /* Send USERS command */
5645 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5646 SILC_PACKET_COMMAND, cmd->packet->flags,
5647 tmpbuf->data, tmpbuf->len, TRUE);
5649 /* Reprocess this packet after received reply */
5650 silc_server_command_pending(server, SILC_COMMAND_USERS,
5651 silc_command_get_ident(cmd->payload),
5652 silc_server_command_users,
5653 silc_server_command_dup(cmd));
5654 cmd->pending = TRUE;
5655 silc_command_set_ident(cmd->payload, ident);
5656 silc_buffer_free(tmpbuf);
5661 /* Check the global list as well. */
5663 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5665 channel = silc_idlist_find_channel_by_name(server->global_list,
5666 channel_name, NULL);
5668 /* Channel really does not exist */
5669 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5670 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5676 /* If the channel is private or secret do not send anything, unless the
5677 user requesting this command is on the channel or is server */
5678 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5679 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5680 && !silc_server_client_on_channel(cmd->sock->user_data, channel,
5682 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5683 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5689 /* Get the users list */
5690 if (!silc_server_get_users_on_channel(server, channel, &client_id_list,
5691 &client_mode_list, &list_count)) {
5693 client_id_list = NULL;
5694 client_mode_list = NULL;
5698 SILC_PUT32_MSB(list_count, lc);
5701 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5702 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5703 SILC_STATUS_OK, 0, ident, 4,
5704 2, idp->data, idp->len,
5707 client_id_list->data : NULL,
5709 client_id_list->len : 0,
5710 5, client_mode_list ?
5711 client_mode_list->data : NULL,
5713 client_mode_list->len : 0);
5714 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5715 packet->data, packet->len, FALSE);
5717 silc_buffer_free(idp);
5718 silc_buffer_free(packet);
5720 silc_buffer_free(client_id_list);
5721 if (client_mode_list)
5722 silc_buffer_free(client_mode_list);
5726 silc_server_command_free(cmd);
5729 /* Server side of command GETKEY. This fetches the client's public key
5730 from the server where to the client is connected. */
5732 SILC_SERVER_CMD_FUNC(getkey)
5734 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5735 SilcServer server = cmd->server;
5737 SilcClientEntry client;
5738 SilcServerEntry server_entry;
5739 SilcClientID *client_id = NULL;
5740 SilcServerID *server_id = NULL;
5741 SilcIDPayload idp = NULL;
5742 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5743 unsigned char *tmp, *pkdata;
5744 SilcUInt32 tmp_len, pklen;
5745 SilcBuffer pk = NULL;
5747 SilcPublicKey public_key;
5749 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5751 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5752 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5756 idp = silc_id_payload_parse(tmp, tmp_len);
5758 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5759 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5764 id_type = silc_id_payload_get_type(idp);
5765 if (id_type == SILC_ID_CLIENT) {
5766 client_id = silc_id_payload_get_id(idp);
5768 /* If the client is not found from local list there is no chance it
5769 would be locally connected client so send the command further. */
5770 client = silc_idlist_find_client_by_id(server->local_list,
5771 client_id, TRUE, NULL);
5773 client = silc_idlist_find_client_by_id(server->global_list,
5774 client_id, TRUE, NULL);
5776 if ((!client && !cmd->pending && !server->standalone) ||
5777 (client && !client->connection && !cmd->pending &&
5778 !(client->mode & SILC_UMODE_DETACHED)) ||
5779 (client && !client->data.public_key && !cmd->pending)) {
5781 SilcUInt16 old_ident;
5782 SilcSocketConnection dest_sock;
5784 dest_sock = silc_server_get_client_route(server, NULL, 0,
5785 client_id, NULL, NULL);
5789 old_ident = silc_command_get_ident(cmd->payload);
5790 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5791 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5793 silc_server_packet_send(server, dest_sock,
5794 SILC_PACKET_COMMAND, cmd->packet->flags,
5795 tmpbuf->data, tmpbuf->len, TRUE);
5797 /* Reprocess this packet after received reply from router */
5798 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5799 silc_command_get_ident(cmd->payload),
5800 silc_server_command_getkey,
5801 silc_server_command_dup(cmd));
5802 cmd->pending = TRUE;
5803 silc_command_set_ident(cmd->payload, old_ident);
5804 silc_buffer_free(tmpbuf);
5809 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5810 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5815 /* The client is locally connected, just get the public key and
5816 send it back. If they key does not exist then do not send it,
5817 send just OK reply */
5818 public_key = client->data.public_key;
5823 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5824 pk = silc_buffer_alloc(4 + tmp_len);
5825 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5826 silc_buffer_format(pk,
5827 SILC_STR_UI_SHORT(tmp_len),
5828 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5829 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5835 } else if (id_type == SILC_ID_SERVER) {
5836 server_id = silc_id_payload_get_id(idp);
5838 /* If the server is not found from local list there is no chance it
5839 would be locally connected server so send the command further. */
5840 server_entry = silc_idlist_find_server_by_id(server->local_list,
5841 server_id, TRUE, NULL);
5843 server_entry = silc_idlist_find_server_by_id(server->global_list,
5844 server_id, TRUE, NULL);
5846 if (server_entry != server->id_entry &&
5847 ((!server_entry && !cmd->pending && !server->standalone) ||
5848 (server_entry && !server_entry->connection && !cmd->pending &&
5849 !server->standalone) ||
5850 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5851 !server->standalone))) {
5853 SilcUInt16 old_ident;
5855 old_ident = silc_command_get_ident(cmd->payload);
5856 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5857 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5859 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5860 SILC_PACKET_COMMAND, cmd->packet->flags,
5861 tmpbuf->data, tmpbuf->len, TRUE);
5863 /* Reprocess this packet after received reply from router */
5864 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5865 silc_command_get_ident(cmd->payload),
5866 silc_server_command_getkey,
5867 silc_server_command_dup(cmd));
5868 cmd->pending = TRUE;
5869 silc_command_set_ident(cmd->payload, old_ident);
5870 silc_buffer_free(tmpbuf);
5874 if (!server_entry) {
5875 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5876 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
5881 /* If they key does not exist then do not send it, send just OK reply */
5882 public_key = (!server_entry->data.public_key ?
5883 (server_entry == server->id_entry ? server->public_key :
5884 NULL) : server_entry->data.public_key);
5889 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5890 pk = silc_buffer_alloc(4 + tmp_len);
5891 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5892 silc_buffer_format(pk,
5893 SILC_STR_UI_SHORT(tmp_len),
5894 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5895 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5905 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5906 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5907 SILC_STATUS_OK, 0, ident,
5911 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5912 packet->data, packet->len, FALSE);
5913 silc_buffer_free(packet);
5916 silc_buffer_free(pk);
5920 silc_id_payload_free(idp);
5921 silc_free(client_id);
5922 silc_free(server_id);
5923 silc_server_command_free(cmd);
5927 /* Private range commands, specific to this implementation */
5929 /* Server side command of CONNECT. Connects us to the specified remote
5930 server or router. */
5932 SILC_SERVER_CMD_FUNC(connect)
5934 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5935 SilcServer server = cmd->server;
5936 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5937 unsigned char *tmp, *host;
5939 SilcUInt32 port = SILC_PORT;
5941 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
5944 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
5946 /* Check whether client has the permissions. */
5947 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5948 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5949 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5950 SILC_STATUS_ERR_NO_SERVER_PRIV, 0);
5954 if (server->server_type == SILC_ROUTER &&
5955 client->mode & SILC_UMODE_SERVER_OPERATOR) {
5956 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5957 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
5961 /* Get the remote server */
5962 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5964 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5965 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5971 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5973 SILC_GET32_MSB(port, tmp);
5975 /* Create the connection. It is done with timeout and is async. */
5976 silc_server_create_connection(server, host, port);
5978 /* Send reply to the sender */
5979 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5983 silc_server_command_free(cmd);
5986 /* Server side command of CLOSE. Closes connection to a specified server. */
5988 SILC_SERVER_CMD_FUNC(close)
5990 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5991 SilcServer server = cmd->server;
5992 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5993 SilcServerEntry server_entry;
5994 SilcSocketConnection sock;
5997 unsigned char *name;
5998 SilcUInt32 port = SILC_PORT;
6000 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
6003 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
6005 /* Check whether client has the permissions. */
6006 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
6007 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
6008 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
6009 SILC_STATUS_ERR_NO_SERVER_PRIV,
6014 /* Get the remote server */
6015 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
6017 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
6018 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
6024 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
6026 SILC_GET32_MSB(port, tmp);
6028 server_entry = silc_idlist_find_server_by_conn(server->local_list,
6029 name, port, FALSE, NULL);
6031 server_entry = silc_idlist_find_server_by_conn(server->global_list,
6032 name, port, FALSE, NULL);
6033 if (!server_entry) {
6034 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
6035 SILC_STATUS_ERR_NO_SERVER_ID, 0);
6039 /* Send reply to the sender */
6040 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
6043 /* Close the connection to the server */
6044 sock = (SilcSocketConnection)server_entry->connection;
6046 /* If we shutdown primary router connection manually then don't trigger
6047 any reconnect or backup router connections, by setting the router
6049 if (server->router == server_entry) {
6050 server->id_entry->router = NULL;
6051 server->router = NULL;
6052 server->standalone = TRUE;
6054 silc_server_free_sock_user_data(server, sock, NULL);
6055 silc_server_close_connection(server, sock);
6058 silc_server_command_free(cmd);
6061 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
6062 active connections. */
6064 SILC_SERVER_CMD_FUNC(shutdown)
6066 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
6067 SilcServer server = cmd->server;
6068 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
6070 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
6073 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
6075 /* Check whether client has the permission. */
6076 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
6077 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
6078 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
6079 SILC_STATUS_ERR_NO_SERVER_PRIV,
6084 /* Send reply to the sender */
6085 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
6088 /* Then, gracefully, or not, bring the server down. */
6089 silc_server_stop(server);
6093 silc_server_command_free(cmd);