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, fempty[20];
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 memset(fempty, 0, sizeof(fempty));
769 /* Start processing found clients. */
770 status = SILC_STATUS_OK;
772 status = SILC_STATUS_LIST_START;
774 for (i = 0, k = 0; i < clients_count; i++) {
780 status = SILC_STATUS_LIST_ITEM;
781 if (valid_count > 1 && k == valid_count - 1 && !errors_count)
782 status = SILC_STATUS_LIST_END;
783 if (count && k - 1 == count)
784 status = SILC_STATUS_LIST_END;
786 /* Send WHOIS reply */
787 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
788 tmp = silc_argument_get_first_arg(cmd->args, NULL);
790 memset(uh, 0, sizeof(uh));
791 memset(nh, 0, sizeof(nh));
792 memset(idle, 0, sizeof(idle));
794 strncat(nh, entry->nickname, strlen(entry->nickname));
795 if (!strchr(entry->nickname, '@')) {
797 if (entry->servername) {
798 strncat(nh, entry->servername, strlen(entry->servername));
800 len = entry->router ? strlen(entry->router->server_name) :
801 strlen(server->server_name);
802 strncat(nh, entry->router ? entry->router->server_name :
803 server->server_name, len);
807 strncat(uh, entry->username, strlen(entry->username));
808 if (!strchr(entry->username, '@') && entry->connection) {
810 hsock = (SilcSocketConnection)entry->connection;
811 len = strlen(hsock->hostname);
812 strncat(uh, hsock->hostname, len);
815 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
816 channels = silc_server_get_client_channel_list(server, entry, FALSE,
819 channels = silc_server_get_client_channel_list(server, entry, TRUE,
822 if (memcmp(entry->data.fingerprint, fempty, sizeof(fempty)))
823 fingerprint = entry->data.fingerprint;
827 SILC_PUT32_MSB(entry->mode, mode);
828 if (entry->connection)
829 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
832 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
834 2, idp->data, idp->len,
838 strlen(entry->userinfo),
839 6, channels ? channels->data : NULL,
840 channels ? channels->len : 0,
844 fingerprint ? 20 : 0,
845 10, umode_list ? umode_list->data :
846 NULL, umode_list ? umode_list->len :
849 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
850 0, packet->data, packet->len, FALSE);
852 silc_buffer_free(packet);
853 silc_buffer_free(idp);
855 silc_buffer_free(channels);
857 silc_buffer_free(umode_list);
861 if (status == SILC_STATUS_LIST_END)
866 /* Send error replies */
867 if (status == SILC_STATUS_OK && errors_count > 1)
868 status = SILC_STATUS_LIST_START;
871 for (i = 0, k = 0; i < errors_count; i++) {
873 idp = silc_id_payload_encode(errors[i].id, SILC_ID_CLIENT);
877 tmp = silc_argument_get_arg_type(cmd->args, errors[i].index, &len);
881 status = SILC_STATUS_LIST_ITEM;
882 if (errors_count > 1 && k == errors_count - 1)
883 status = SILC_STATUS_LIST_END;
884 if (count && k - 1 == count)
885 status = SILC_STATUS_LIST_END;
888 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
889 (status == SILC_STATUS_OK ?
890 errors[i].error : status),
891 (status == SILC_STATUS_OK ?
892 0 : errors[i].error),
894 silc_buffer_free(idp);
897 if (status == SILC_STATUS_LIST_END)
904 silc_server_command_whois_send_router(SilcServerCommandContext cmd)
906 SilcServer server = cmd->server;
908 SilcUInt16 old_ident;
910 old_ident = silc_command_get_ident(cmd->payload);
911 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
912 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
914 /* Send WHOIS command to our router */
915 silc_server_packet_send(server, (SilcSocketConnection)
916 SILC_PRIMARY_ROUTE(server),
917 SILC_PACKET_COMMAND, cmd->packet->flags,
918 tmpbuf->data, tmpbuf->len, TRUE);
920 /* Reprocess this packet after received reply from router */
921 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
922 silc_command_get_ident(cmd->payload),
923 silc_server_command_whois,
924 silc_server_command_dup(cmd));
926 silc_command_set_ident(cmd->payload, old_ident);
927 silc_buffer_free(tmpbuf);
931 silc_server_command_whois_process(SilcServerCommandContext cmd)
933 SilcServer server = cmd->server;
934 char *nick = NULL, *server_name = NULL;
936 SilcClientEntry *clients = NULL, entry;
937 SilcClientID **client_id = NULL;
938 SilcUInt32 client_id_count = 0, clients_count = 0, error_client_count = 0;
939 ResolveError error_client = NULL;
941 bool check_global = FALSE;
943 /* Parse the whois request */
944 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
945 &nick, &server_name, &count,
946 &error_client, &error_client_count))
949 /* Send the WHOIS request to the router only if it included nickname.
950 Since nicknames can be expanded into many clients we need to send it
951 to router. If the WHOIS included only client ID's we will check them
952 first locally since we just might have them. */
953 if (nick && !client_id_count && cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
954 server->server_type == SILC_SERVER && !cmd->pending &&
955 !server->standalone) {
956 silc_server_command_whois_send_router(cmd);
961 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
963 else if (server->server_type != SILC_SERVER)
966 /* Get all clients matching that ID or nickname from local list */
967 if (client_id_count) {
968 /* Check all Client ID's received in the command packet */
969 for (i = 0; i < client_id_count; i++) {
970 entry = silc_idlist_find_client_by_id(server->local_list,
971 client_id[i], TRUE, NULL);
972 if (!entry && check_global)
973 entry = silc_idlist_find_client_by_id(server->global_list,
974 client_id[i], TRUE, NULL);
976 clients = silc_realloc(clients, sizeof(*clients) *
977 (clients_count + 1));
978 clients[clients_count++] = entry;
980 /* If we are normal server and did not send the request first to router
981 do it now, since we do not have the Client ID information. */
982 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
983 server->server_type == SILC_SERVER && !cmd->pending &&
984 !server->standalone) {
985 silc_server_command_whois_send_router(cmd);
990 ADD_ERROR(error_client, error_client_count, client_id[i],
991 SILC_ID_CLIENT, 0, SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
995 /* Find by nickname */
996 if (!silc_idlist_get_clients_by_hash(server->local_list,
997 nick, server->md5hash,
998 &clients, &clients_count))
999 silc_idlist_get_clients_by_nickname(server->local_list,
1001 &clients, &clients_count);
1003 if (!silc_idlist_get_clients_by_hash(server->global_list,
1004 nick, server->md5hash,
1005 &clients, &clients_count))
1006 silc_idlist_get_clients_by_nickname(server->global_list,
1008 &clients, &clients_count);
1012 if (!clients && (client_id_count || nick)) {
1013 /* If we are normal server and did not send the request first to router
1014 do it now, since we do not have the information. */
1015 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1016 server->server_type == SILC_SERVER && !cmd->pending &&
1017 !server->standalone) {
1018 silc_server_command_whois_send_router(cmd);
1023 /* Such client(s) really does not exist in the SILC network. */
1024 if (!client_id_count)
1025 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
1026 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1027 3, nick, strlen(nick));
1029 silc_server_command_whois_send_reply(cmd, NULL, 0,
1030 error_client, error_client_count,
1035 /* Router always finds the client entry if it exists in the SILC network.
1036 However, it might be incomplete entry and does not include all the
1037 mandatory fields that WHOIS command reply requires. Check for these and
1038 make query from the server who owns the client if some fields are
1040 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
1045 /* Send the command reply */
1046 silc_server_command_whois_send_reply(cmd, clients, clients_count,
1047 error_client, error_client_count,
1048 count, nick, client_id);
1051 if (client_id_count) {
1052 for (i = 0; i < client_id_count; i++)
1053 silc_free(client_id[i]);
1054 silc_free(client_id);
1057 silc_free(error_client);
1059 silc_free(server_name);
1064 /* Server side of command WHOIS. Processes user's query and sends found
1065 results as command replies back to the client. */
1067 SILC_SERVER_CMD_FUNC(whois)
1069 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1072 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 3328);
1074 ret = silc_server_command_whois_process(cmd);
1075 silc_server_command_free(cmd);
1078 /******************************************************************************
1082 ******************************************************************************/
1085 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
1093 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1095 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
1096 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1101 /* Get the nickname@server string and parse it. */
1102 silc_parse_userfqdn(tmp, nickname, server_name);
1104 /* Get the max count of reply messages allowed */
1105 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1107 SILC_GET32_MSB(*count, tmp);
1115 silc_server_command_whowas_check(SilcServerCommandContext cmd,
1116 SilcClientEntry *clients,
1117 SilcUInt32 clients_count)
1119 SilcServer server = cmd->server;
1121 SilcClientEntry entry;
1123 for (i = 0; i < clients_count; i++) {
1126 if (!entry->nickname || !entry->username) {
1128 SilcUInt16 old_ident;
1133 old_ident = silc_command_get_ident(cmd->payload);
1134 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1135 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1137 /* Send WHOWAS command */
1138 silc_server_packet_send(server, entry->router->connection,
1139 SILC_PACKET_COMMAND, cmd->packet->flags,
1140 tmpbuf->data, tmpbuf->len, TRUE);
1142 /* Reprocess this packet after received reply */
1143 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1144 silc_command_get_ident(cmd->payload),
1145 silc_server_command_whowas,
1146 silc_server_command_dup(cmd));
1147 cmd->pending = TRUE;
1148 silc_command_set_ident(cmd->payload, old_ident);
1150 silc_buffer_free(tmpbuf);
1159 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1160 SilcClientEntry *clients,
1161 SilcUInt32 clients_count)
1163 SilcServer server = cmd->server;
1165 int i, k, count = 0, len;
1166 SilcBuffer packet, idp;
1167 SilcClientEntry entry = NULL;
1169 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1170 char nh[256], uh[256];
1173 status = SILC_STATUS_OK;
1175 /* Process only entries that are not registered anymore. */
1177 for (i = 0; i < clients_count; i++) {
1178 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1185 /* No valid entries found at all, just send error */
1186 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1187 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1188 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1189 3, tmp, tmp ? strlen(tmp) : 0);
1193 if (valid_count > 1)
1194 status = SILC_STATUS_LIST_START;
1196 for (i = 0, k = 0; i < clients_count; i++) {
1202 status = SILC_STATUS_LIST_ITEM;
1203 if (valid_count > 1 && k == valid_count - 1)
1204 status = SILC_STATUS_LIST_END;
1205 if (count && k - 1 == count)
1206 status = SILC_STATUS_LIST_END;
1208 /* Send WHOWAS reply */
1209 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1210 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1211 memset(uh, 0, sizeof(uh));
1212 memset(nh, 0, sizeof(nh));
1214 strncat(nh, entry->nickname, strlen(entry->nickname));
1215 if (!strchr(entry->nickname, '@')) {
1216 strncat(nh, "@", 1);
1217 if (entry->servername) {
1218 strncat(nh, entry->servername, strlen(entry->servername));
1220 len = entry->router ? strlen(entry->router->server_name) :
1221 strlen(server->server_name);
1222 strncat(nh, entry->router ? entry->router->server_name :
1223 server->server_name, len);
1227 strncat(uh, entry->username, strlen(entry->username));
1228 if (!strchr(entry->username, '@')) {
1229 strncat(uh, "@", 1);
1230 strcat(uh, "*private*");
1234 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1235 status, 0, ident, 4,
1236 2, idp->data, idp->len,
1241 strlen(entry->userinfo) : 0);
1242 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1243 0, packet->data, packet->len, FALSE);
1245 silc_buffer_free(packet);
1246 silc_buffer_free(idp);
1248 if (status == SILC_STATUS_LIST_END)
1255 silc_server_command_whowas_process(SilcServerCommandContext cmd)
1257 SilcServer server = cmd->server;
1258 char *nick = NULL, *server_name = NULL;
1260 SilcClientEntry *clients = NULL;
1261 SilcUInt32 clients_count = 0;
1263 bool check_global = FALSE;
1265 /* Protocol dictates that we must always send the received WHOWAS request
1266 to our router if we are normal server, so let's do it now unless we
1267 are standalone. We will not send any replies to the client until we
1268 have received reply from the router. */
1269 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1270 server->server_type == SILC_SERVER && !cmd->pending &&
1271 !server->standalone) {
1273 SilcUInt16 old_ident;
1275 old_ident = silc_command_get_ident(cmd->payload);
1276 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1277 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1279 /* Send WHOWAS command to our router */
1280 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
1281 SILC_PACKET_COMMAND, cmd->packet->flags,
1282 tmpbuf->data, tmpbuf->len, TRUE);
1284 /* Reprocess this packet after received reply from router */
1285 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1286 silc_command_get_ident(cmd->payload),
1287 silc_server_command_whowas,
1288 silc_server_command_dup(cmd));
1289 cmd->pending = TRUE;
1290 silc_command_set_ident(cmd->payload, old_ident);
1292 silc_buffer_free(tmpbuf);
1297 /* We are ready to process the command request. Let's search for the
1298 requested client and send reply to the requesting client. */
1300 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1301 check_global = TRUE;
1302 else if (server->server_type != SILC_SERVER)
1303 check_global = TRUE;
1305 /* Parse the whowas request */
1306 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1309 /* Get all clients matching that nickname from local list */
1310 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1312 &clients, &clients_count))
1313 silc_idlist_get_clients_by_hash(server->local_list,
1314 nick, server->md5hash,
1315 &clients, &clients_count);
1317 /* Check global list as well */
1319 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1321 &clients, &clients_count))
1322 silc_idlist_get_clients_by_hash(server->global_list,
1323 nick, server->md5hash,
1324 &clients, &clients_count);
1328 /* Such a client really does not exist in the SILC network. */
1329 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1330 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1331 3, nick, strlen(nick));
1335 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1340 /* Send the command reply to the client */
1341 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1346 silc_free(server_name);
1350 /* Server side of command WHOWAS. */
1352 SILC_SERVER_CMD_FUNC(whowas)
1354 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1357 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1359 ret = silc_server_command_whowas_process(cmd);
1360 silc_server_command_free(cmd);
1363 /******************************************************************************
1367 ******************************************************************************/
1370 silc_server_command_identify_send_router(SilcServerCommandContext cmd)
1372 SilcServer server = cmd->server;
1374 SilcUInt16 old_ident;
1376 old_ident = silc_command_get_ident(cmd->payload);
1377 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1378 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1380 /* Send IDENTIFY command to our router */
1381 silc_server_packet_send(server, (SilcSocketConnection)
1382 SILC_PRIMARY_ROUTE(server),
1383 SILC_PACKET_COMMAND, cmd->packet->flags,
1384 tmpbuf->data, tmpbuf->len, TRUE);
1386 /* Reprocess this packet after received reply from router */
1387 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1388 silc_command_get_ident(cmd->payload),
1389 silc_server_command_identify,
1390 silc_server_command_dup(cmd));
1391 cmd->pending = TRUE;
1392 silc_command_set_ident(cmd->payload, old_ident);
1393 silc_buffer_free(tmpbuf);
1397 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1398 SilcClientEntry **clients,
1399 SilcUInt32 *clients_count,
1400 SilcServerEntry **servers,
1401 SilcUInt32 *servers_count,
1402 SilcChannelEntry **channels,
1403 SilcUInt32 *channels_count,
1405 ResolveError *error_id,
1406 SilcUInt32 *error_id_count)
1408 SilcServer server = cmd->server;
1411 SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
1413 bool check_global = FALSE;
1417 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1418 check_global = TRUE;
1419 else if (server->server_type != SILC_SERVER)
1420 check_global = TRUE;
1422 /* If ID Payload is in the command it must be used instead of names */
1423 tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1425 /* No ID, get the names. */
1427 /* If we are normal server and have not resolved information from
1428 router yet, do so now. */
1429 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1430 server->server_type == SILC_SERVER && !cmd->pending &&
1431 !server->standalone) {
1432 silc_server_command_identify_send_router(cmd);
1436 /* Try to get nickname@server. */
1437 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1440 char *nick_server = NULL;
1442 silc_parse_userfqdn(tmp, &nick, &nick_server);
1444 if (!silc_idlist_get_clients_by_hash(server->local_list,
1445 nick, server->md5hash,
1446 clients, clients_count))
1447 silc_idlist_get_clients_by_nickname(server->local_list,
1449 clients, clients_count);
1451 if (!silc_idlist_get_clients_by_hash(server->global_list,
1452 nick, server->md5hash,
1453 clients, clients_count))
1454 silc_idlist_get_clients_by_nickname(server->global_list,
1456 clients, clients_count);
1460 silc_free(nick_server);
1463 /* the nickname does not exist, send error reply */
1464 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1465 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1466 3, tmp, strlen(tmp));
1471 /* Try to get server name */
1472 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1474 entry = silc_idlist_find_server_by_name(server->local_list,
1476 if (!entry && check_global)
1477 entry = silc_idlist_find_server_by_name(server->global_list,
1480 *servers = silc_realloc(*servers, sizeof(**servers) *
1481 (*servers_count + 1));
1482 (*servers)[(*servers_count)++] = entry;
1486 /* the server does not exist, send error reply */
1487 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1488 SILC_STATUS_ERR_NO_SUCH_SERVER,
1489 0, 3, tmp, strlen(tmp));
1494 /* Try to get channel name */
1495 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1497 entry = silc_idlist_find_channel_by_name(server->local_list,
1499 if (!entry && check_global)
1500 entry = silc_idlist_find_channel_by_name(server->global_list,
1503 *channels = silc_realloc(*channels, sizeof(**channels) *
1504 (*channels_count + 1));
1505 (*channels)[(*channels_count)++] = entry;
1509 /* The channel does not exist, send error reply */
1510 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1511 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1512 0, 3, tmp, strlen(tmp));
1517 if (!(*clients) && !(*servers) && !(*channels)) {
1518 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1519 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1524 /* Command includes ID, we must use that. Also check whether the command
1525 has more than one ID set - take them all. */
1527 /* Take all ID's from the command packet */
1528 for (i = 0; i < argc; i++) {
1531 tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
1535 idp = silc_id_payload_parse(tmp, len);
1537 ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1538 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1540 id = silc_id_payload_get_id(idp);
1541 switch (silc_id_payload_get_type(idp)) {
1543 case SILC_ID_CLIENT:
1544 entry = silc_idlist_find_client_by_id(server->local_list,
1546 if (!entry && check_global)
1547 entry = silc_idlist_find_client_by_id(server->global_list,
1550 *clients = silc_realloc(*clients, sizeof(**clients) *
1551 (*clients_count + 1));
1552 (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
1554 /* If we are normal server and have not resolved information from
1555 router yet, do so now. */
1556 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1557 server->server_type == SILC_SERVER && !cmd->pending &&
1558 !server->standalone) {
1559 silc_server_command_identify_send_router(cmd);
1560 silc_free(*clients);
1561 silc_free(*servers);
1562 silc_free(*channels);
1563 silc_free(*error_id);
1567 ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1568 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
1573 case SILC_ID_SERVER:
1574 entry = silc_idlist_find_server_by_id(server->local_list,
1576 if (!entry && check_global)
1577 entry = silc_idlist_find_server_by_id(server->global_list,
1580 *servers = silc_realloc(*servers, sizeof(**servers) *
1581 (*servers_count + 1));
1582 (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
1584 /* If we are normal server and have not resolved information from
1585 router yet, do so now. */
1586 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1587 server->server_type == SILC_SERVER && !cmd->pending &&
1588 !server->standalone) {
1589 silc_server_command_identify_send_router(cmd);
1590 silc_free(*clients);
1591 silc_free(*servers);
1592 silc_free(*channels);
1593 silc_free(*error_id);
1597 ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1598 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
1602 case SILC_ID_CHANNEL:
1603 entry = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
1604 if (!entry && check_global)
1605 entry = silc_idlist_find_channel_by_id(server->global_list, id,
1608 *channels = silc_realloc(*channels, sizeof(**channels) *
1609 (*channels_count + 1));
1610 (*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
1612 /* If we are normal server and have not resolved information from
1613 router yet, do so now. */
1614 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1615 server->server_type == SILC_SERVER && !cmd->pending &&
1616 !server->standalone) {
1617 silc_server_command_identify_send_router(cmd);
1618 silc_free(*clients);
1619 silc_free(*servers);
1620 silc_free(*channels);
1621 silc_free(*error_id);
1625 ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1626 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID);
1631 silc_id_payload_free(idp);
1636 /* Get the max count of reply messages allowed */
1637 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1639 SILC_GET32_MSB(*count, tmp);
1646 /* Checks that all mandatory fields in client entry are present. If not
1647 then send WHOIS request to the server who owns the client. We use
1648 WHOIS because we want to get as much information as possible at once. */
1651 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1652 SilcClientEntry *clients,
1653 SilcUInt32 clients_count)
1655 SilcServer server = cmd->server;
1656 SilcClientEntry entry;
1657 SilcServerResolveContext resolve = NULL, r = NULL;
1658 SilcUInt32 resolve_count = 0;
1662 for (i = 0; i < clients_count; i++) {
1667 if (entry->nickname ||
1668 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1672 /* If we are normal server, and we've not resolved this client from
1673 router and it is global client, we'll check whether it is on some
1674 channel. If not then we cannot be sure about its validity, and
1675 we'll resolve it from router. */
1676 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
1677 entry->connection || silc_hash_table_count(entry->channels))
1681 /* We need to resolve this entry since it is not complete */
1683 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1684 /* The entry is being resolved (and we are not the resolver) so attach
1685 to the command reply and we're done with this one. */
1686 silc_server_command_pending(server, SILC_COMMAND_NONE,
1687 entry->resolve_cmd_ident,
1688 silc_server_command_identify,
1689 silc_server_command_dup(cmd));
1692 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1693 /* We've resolved this and it still is not ready. We'll return
1694 and are that this will be handled again after it is resolved. */
1695 for (i = 0; i < resolve_count; i++) {
1696 for (k = 0; k < r->res_argc; k++)
1697 silc_free(r->res_argv[k]);
1698 silc_free(r->res_argv);
1699 silc_free(r->res_argv_lens);
1700 silc_free(r->res_argv_types);
1705 /* We'll resolve this client */
1709 for (k = 0; k < resolve_count; k++) {
1710 if (resolve[k].router == entry->router) {
1717 resolve = silc_realloc(resolve, sizeof(*resolve) *
1718 (resolve_count + 1));
1719 r = &resolve[resolve_count];
1720 memset(r, 0, sizeof(*r));
1721 r->router = entry->router;
1722 r->ident = ++server->cmd_ident;
1726 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1728 r->res_argv_lens = silc_realloc(r->res_argv_lens,
1729 sizeof(*r->res_argv_lens) *
1731 r->res_argv_types = silc_realloc(r->res_argv_types,
1732 sizeof(*r->res_argv_types) *
1734 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1735 r->res_argv[r->res_argc] = silc_calloc(idp->len,
1736 sizeof(**r->res_argv));
1737 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1738 r->res_argv_lens[r->res_argc] = idp->len;
1739 r->res_argv_types[r->res_argc] = r->res_argc + 4;
1741 silc_buffer_free(idp);
1743 entry->resolve_cmd_ident = r->ident;
1744 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1745 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1750 /* Do the resolving */
1751 for (i = 0; i < resolve_count; i++) {
1756 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1757 now anyway so make it a good one. */
1758 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1759 r->res_argc, r->res_argv,
1763 silc_server_packet_send(server, r->router->connection,
1764 SILC_PACKET_COMMAND, cmd->packet->flags,
1765 res_cmd->data, res_cmd->len, FALSE);
1767 /* Reprocess this packet after received reply */
1768 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1770 silc_server_command_identify,
1771 silc_server_command_dup(cmd));
1772 cmd->pending = TRUE;
1774 silc_buffer_free(res_cmd);
1775 for (k = 0; k < r->res_argc; k++)
1776 silc_free(r->res_argv[k]);
1777 silc_free(r->res_argv);
1778 silc_free(r->res_argv_lens);
1779 silc_free(r->res_argv_types);
1788 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1789 SilcClientEntry *clients,
1790 SilcUInt32 clients_count,
1791 SilcServerEntry *servers,
1792 SilcUInt32 servers_count,
1793 SilcChannelEntry *channels,
1794 SilcUInt32 channels_count,
1795 ResolveError errors,
1796 SilcUInt32 errors_count,
1799 SilcServer server = cmd->server;
1800 int i, k, valid_count;
1802 SilcBuffer packet, idp;
1804 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1805 char nh[256], uh[256];
1806 SilcSocketConnection hsock;
1809 status = SILC_STATUS_OK;
1812 SilcClientEntry entry;
1813 valid_count = clients_count;
1815 if (silc_argument_get_arg_type(cmd->args, 1, NULL)) {
1816 /* Process only valid clients and ignore those that are not registered.
1817 This is checked with nickname only because when resolved client IDs
1818 we check that they are registered earlier. */
1820 for (i = 0; i < clients_count; i++) {
1821 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1828 /* No valid entries found at all, just send error */
1829 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1830 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1831 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1832 3, tmp, tmp ? strlen(tmp) : 0);
1837 /* Process all valid client entries and send command replies */
1839 if (valid_count > 1)
1840 status = SILC_STATUS_LIST_START;
1842 for (i = 0, k = 0; i < clients_count; i++) {
1848 status = SILC_STATUS_LIST_ITEM;
1849 if (valid_count > 1 && k == valid_count - 1
1850 && !servers_count && !channels_count && !errors_count)
1851 status = SILC_STATUS_LIST_END;
1852 if (count && k - 1 == count)
1853 status = SILC_STATUS_LIST_END;
1855 /* Send IDENTIFY reply */
1857 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1858 memset(uh, 0, sizeof(uh));
1859 memset(nh, 0, sizeof(nh));
1860 strncat(nh, entry->nickname, strlen(entry->nickname));
1861 if (!strchr(entry->nickname, '@')) {
1862 strncat(nh, "@", 1);
1863 if (entry->servername) {
1864 strncat(nh, entry->servername, strlen(entry->servername));
1866 len = entry->router ? strlen(entry->router->server_name) :
1867 strlen(server->server_name);
1868 strncat(nh, entry->router ? entry->router->server_name :
1869 server->server_name, len);
1873 if (!entry->username) {
1874 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1875 status, 0, ident, 2,
1876 2, idp->data, idp->len,
1879 strncat(uh, entry->username, strlen(entry->username));
1880 if (!strchr(entry->username, '@') && entry->connection) {
1881 strncat(uh, "@", 1);
1882 hsock = (SilcSocketConnection)entry->connection;
1883 len = strlen(hsock->hostname);
1884 strncat(uh, hsock->hostname, len);
1887 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1888 status, 0, ident, 3,
1889 2, idp->data, idp->len,
1894 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1895 0, packet->data, packet->len, FALSE);
1897 silc_buffer_free(packet);
1898 silc_buffer_free(idp);
1900 if (status == SILC_STATUS_LIST_END)
1907 SilcServerEntry entry;
1909 if (status == SILC_STATUS_OK && servers_count > 1)
1910 status = SILC_STATUS_LIST_START;
1912 for (i = 0, k = 0; i < servers_count; i++) {
1916 status = SILC_STATUS_LIST_ITEM;
1917 if (servers_count > 1 && k == servers_count - 1 && !channels_count &&
1919 status = SILC_STATUS_LIST_END;
1920 if (count && k - 1 == count)
1921 status = SILC_STATUS_LIST_END;
1923 /* Send IDENTIFY reply */
1924 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1926 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1927 status, 0, ident, 2,
1928 2, idp->data, idp->len,
1929 3, entry->server_name,
1930 entry->server_name ?
1931 strlen(entry->server_name) : 0);
1932 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1933 0, packet->data, packet->len, FALSE);
1935 silc_buffer_free(packet);
1936 silc_buffer_free(idp);
1938 if (status == SILC_STATUS_LIST_END)
1945 SilcChannelEntry entry;
1947 if (status == SILC_STATUS_OK && channels_count > 1)
1948 status = SILC_STATUS_LIST_START;
1950 for (i = 0, k = 0; i < channels_count; i++) {
1951 entry = channels[i];
1954 status = SILC_STATUS_LIST_ITEM;
1955 if (channels_count > 1 && k == channels_count - 1 && !errors_count)
1956 status = SILC_STATUS_LIST_END;
1957 if (count && k - 1 == count)
1958 status = SILC_STATUS_LIST_END;
1960 /* Send IDENTIFY reply */
1961 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1963 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1964 status, 0, ident, 2,
1965 2, idp->data, idp->len,
1966 3, entry->channel_name,
1967 entry->channel_name ?
1968 strlen(entry->channel_name): 0);
1969 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1970 0, packet->data, packet->len, FALSE);
1972 silc_buffer_free(packet);
1973 silc_buffer_free(idp);
1975 if (status == SILC_STATUS_LIST_END)
1981 /* Send error replies */
1983 if (status == SILC_STATUS_OK && errors_count > 1)
1984 status = SILC_STATUS_LIST_START;
1987 for (i = 0, k = 0; i < errors_count; i++) {
1989 idp = silc_id_payload_encode(errors[i].id, SILC_ID_CLIENT);
1993 tmp = silc_argument_get_arg_type(cmd->args, errors[i].index, &len);
1997 status = SILC_STATUS_LIST_ITEM;
1998 if (errors_count > 1 && k == errors_count - 1)
1999 status = SILC_STATUS_LIST_END;
2000 if (count && k - 1 == count)
2001 status = SILC_STATUS_LIST_END;
2004 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
2005 (status == SILC_STATUS_OK ?
2006 errors[i].error : status),
2007 (status == SILC_STATUS_OK ?
2008 0 : errors[i].error),
2010 silc_buffer_free(idp);
2013 if (status == SILC_STATUS_LIST_END)
2021 silc_server_command_identify_process(SilcServerCommandContext cmd)
2023 SilcUInt32 count = 0;
2025 SilcClientEntry *clients = NULL;
2026 SilcServerEntry *servers = NULL;
2027 SilcChannelEntry *channels = NULL;
2028 SilcUInt32 clients_count = 0, servers_count = 0, channels_count = 0;
2029 SilcUInt32 errors_count = 0;
2030 ResolveError errors = NULL;
2032 /* Parse the IDENTIFY request */
2033 ret = silc_server_command_identify_parse(cmd,
2034 &clients, &clients_count,
2035 &servers, &servers_count,
2036 &channels, &channels_count,
2037 &count, &errors, &errors_count);
2042 /* Check that all mandatory fields are present and request those data
2043 from the server who owns the client if necessary. */
2044 if (!silc_server_command_identify_check_client(cmd, clients,
2050 /* Send the command reply to the client */
2051 silc_server_command_identify_send_reply(cmd,
2052 clients, clients_count,
2053 servers, servers_count,
2054 channels, channels_count,
2055 errors, errors_count,
2061 silc_free(channels);
2066 SILC_SERVER_CMD_FUNC(identify)
2068 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2071 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
2073 ret = silc_server_command_identify_process(cmd);
2074 silc_server_command_free(cmd);
2077 /* Server side of command NICK. Sets nickname for user. Setting
2078 nickname causes generation of a new client ID for the client. The
2079 new client ID is sent to the client after changing the nickname. */
2081 SILC_SERVER_CMD_FUNC(nick)
2083 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2084 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2085 SilcServer server = cmd->server;
2086 SilcBuffer packet, nidp, oidp = NULL;
2087 SilcClientID *new_id;
2088 SilcUInt32 nick_len;
2090 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2093 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
2096 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
2098 /* Check nickname */
2099 nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
2102 if (silc_server_name_bad_chars(nick, nick_len) == TRUE) {
2103 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2104 SILC_STATUS_ERR_BAD_NICKNAME, 0);
2108 /* Check for same nickname */
2109 if (!strcmp(client->nickname, nick)) {
2110 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2114 /* Create new Client ID */
2115 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
2117 cmd->server->md5hash, nick,
2121 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2122 SILC_STATUS_ERR_BAD_NICKNAME, 0);
2125 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2128 /* Send notify about nickname change to our router. We send the new
2129 ID and ask to replace it with the old one. If we are router the
2130 packet is broadcasted. Send NICK_CHANGE notify. */
2131 silc_server_send_notify_nick_change(server, SILC_PRIMARY_ROUTE(server),
2132 SILC_BROADCAST(server), client->id,
2135 /* Check if anyone is watching the old nickname */
2136 if (server->server_type == SILC_ROUTER)
2137 silc_server_check_watcher_list(server, client, nick,
2138 SILC_NOTIFY_TYPE_NICK_CHANGE);
2140 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2142 /* Remove old cache entry */
2143 silc_idcache_del_by_context(server->local_list->clients, client);
2145 silc_free(client->id);
2146 client->id = new_id;
2148 silc_free(client->nickname);
2149 client->nickname = strdup(nick);
2151 /* Update client cache */
2152 silc_idcache_add(server->local_list->clients, client->nickname,
2153 client->id, (void *)client, 0, NULL);
2155 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2157 /* Send NICK_CHANGE notify to the client's channels */
2158 silc_server_send_notify_on_channels(server, NULL, client,
2159 SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
2160 oidp->data, oidp->len,
2161 nidp->data, nidp->len,
2163 strlen(client->nickname));
2165 /* Check if anyone is watching the new nickname */
2166 if (server->server_type == SILC_ROUTER)
2167 silc_server_check_watcher_list(server, client, NULL,
2168 SILC_NOTIFY_TYPE_NICK_CHANGE);
2171 /* Send the new Client ID as reply command back to client */
2172 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
2173 SILC_STATUS_OK, 0, ident, 2,
2174 2, nidp->data, nidp->len,
2175 3, nick, strlen(nick));
2176 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2177 0, packet->data, packet->len, FALSE);
2179 silc_buffer_free(packet);
2180 silc_buffer_free(nidp);
2182 silc_buffer_free(oidp);
2185 silc_server_command_free(cmd);
2188 /* Sends the LIST command reply */
2191 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2192 SilcChannelEntry *lch,
2193 SilcUInt32 lch_count,
2194 SilcChannelEntry *gch,
2195 SilcUInt32 gch_count)
2198 SilcBuffer packet, idp;
2199 SilcChannelEntry entry;
2201 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2203 unsigned char usercount[4];
2205 int valid_lcount = 0, valid_rcount = 0;
2207 for (i = 0; i < lch_count; i++) {
2208 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2213 for (i = 0; i < gch_count; i++) {
2214 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2220 status = SILC_STATUS_OK;
2221 if ((lch_count + gch_count) > 1)
2222 status = SILC_STATUS_LIST_START;
2225 for (i = 0, k = 0; i < lch_count; i++) {
2231 status = SILC_STATUS_LIST_ITEM;
2232 if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
2233 status = SILC_STATUS_LIST_END;
2235 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2237 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2238 topic = "*private*";
2239 memset(usercount, 0, sizeof(usercount));
2241 topic = entry->topic;
2242 users = silc_hash_table_count(entry->user_list);
2243 SILC_PUT32_MSB(users, usercount);
2246 /* Send the reply */
2248 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2249 status, 0, ident, 4,
2250 2, idp->data, idp->len,
2251 3, entry->channel_name,
2252 strlen(entry->channel_name),
2253 4, topic, topic ? strlen(topic) : 0,
2255 silc_server_packet_send(cmd->server, cmd->sock,
2256 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2257 packet->len, FALSE);
2258 silc_buffer_free(packet);
2259 silc_buffer_free(idp);
2264 for (i = 0, k = 0; i < gch_count; i++) {
2270 status = SILC_STATUS_LIST_ITEM;
2271 if (valid_rcount > 1 && k == valid_rcount - 1)
2272 status = SILC_STATUS_LIST_END;
2274 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2276 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2277 topic = "*private*";
2278 memset(usercount, 0, sizeof(usercount));
2280 topic = entry->topic;
2281 users = entry->user_count;
2282 SILC_PUT32_MSB(users, usercount);
2285 /* Send the reply */
2287 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2288 status, 0, ident, 4,
2289 2, idp->data, idp->len,
2290 3, entry->channel_name,
2291 strlen(entry->channel_name),
2292 4, topic, topic ? strlen(topic) : 0,
2294 silc_server_packet_send(cmd->server, cmd->sock,
2295 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2296 packet->len, FALSE);
2297 silc_buffer_free(packet);
2298 silc_buffer_free(idp);
2303 /* Server side of LIST command. This lists the channel of the requested
2304 server. Secret channels are not listed. */
2306 SILC_SERVER_CMD_FUNC(list)
2308 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2309 SilcServer server = cmd->server;
2310 SilcChannelID *channel_id = NULL;
2313 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2314 SilcUInt32 lch_count = 0, gch_count = 0;
2316 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2318 /* If we are normal server, send the command to router, since we
2319 want to know all channels in the network. */
2320 if (!cmd->pending && server->server_type == SILC_SERVER &&
2321 !server->standalone) {
2323 SilcUInt16 old_ident;
2325 old_ident = silc_command_get_ident(cmd->payload);
2326 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2327 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2328 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
2329 SILC_PACKET_COMMAND, cmd->packet->flags,
2330 tmpbuf->data, tmpbuf->len, TRUE);
2332 /* Reprocess this packet after received reply from router */
2333 silc_server_command_pending(server, SILC_COMMAND_LIST,
2334 silc_command_get_ident(cmd->payload),
2335 silc_server_command_list,
2336 silc_server_command_dup(cmd));
2337 cmd->pending = TRUE;
2338 silc_command_set_ident(cmd->payload, old_ident);
2339 silc_buffer_free(tmpbuf);
2343 /* Get Channel ID */
2344 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2346 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2348 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2349 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2354 /* Get the channels from local list */
2355 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2358 /* Get the channels from global list */
2359 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2362 /* Send the reply */
2363 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2364 gchannels, gch_count);
2366 silc_free(lchannels);
2367 silc_free(gchannels);
2370 silc_server_command_free(cmd);
2373 /* Server side of TOPIC command. Sets topic for channel and/or returns
2374 current topic to client. */
2376 SILC_SERVER_CMD_FUNC(topic)
2378 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2379 SilcServer server = cmd->server;
2380 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2381 SilcChannelID *channel_id;
2382 SilcChannelEntry channel;
2383 SilcChannelClientEntry chl;
2384 SilcBuffer packet, idp;
2386 SilcUInt32 argc, tmp_len;
2387 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2389 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
2392 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2394 argc = silc_argument_get_arg_num(cmd->args);
2396 /* Get Channel ID */
2397 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2399 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2400 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2403 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2405 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2406 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2410 /* Check whether the channel exists */
2411 channel = silc_idlist_find_channel_by_id(server->local_list,
2414 channel = silc_idlist_find_channel_by_id(server->global_list,
2417 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2418 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
2426 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2428 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2429 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2434 if (strlen(tmp) > 256) {
2435 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2436 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2441 /* See whether the client is on channel and has rights to change topic */
2442 if (!silc_server_client_on_channel(client, channel, &chl)) {
2443 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2444 SILC_STATUS_ERR_NOT_ON_CHANNEL,
2449 if (channel->mode & SILC_CHANNEL_MODE_TOPIC &&
2450 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
2451 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
2452 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2453 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
2458 if (!channel->topic || strcmp(channel->topic, tmp)) {
2459 /* Set the topic for channel */
2460 silc_free(channel->topic);
2461 channel->topic = strdup(tmp);
2463 /* Send TOPIC_SET notify type to the network */
2464 silc_server_send_notify_topic_set(server, SILC_PRIMARY_ROUTE(server),
2465 SILC_BROADCAST(server), channel,
2466 client->id, SILC_ID_CLIENT,
2469 /* Send notify about topic change to all clients on the channel */
2470 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2471 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2472 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2473 idp->data, idp->len,
2475 strlen(channel->topic));
2476 silc_buffer_free(idp);
2480 /* Send the topic to client as reply packet */
2481 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2482 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2483 SILC_STATUS_OK, 0, ident, 2,
2484 2, idp->data, idp->len,
2487 strlen(channel->topic) : 0);
2488 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2489 0, packet->data, packet->len, FALSE);
2491 silc_buffer_free(packet);
2492 silc_buffer_free(idp);
2493 silc_free(channel_id);
2496 silc_server_command_free(cmd);
2499 /* Server side of INVITE command. Invites some client to join some channel.
2500 This command is also used to manage the invite list of the channel. */
2502 SILC_SERVER_CMD_FUNC(invite)
2504 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2505 SilcServer server = cmd->server;
2506 SilcSocketConnection sock = cmd->sock, dest_sock;
2507 SilcChannelClientEntry chl;
2508 SilcClientEntry sender, dest;
2509 SilcClientID *dest_id = NULL;
2510 SilcChannelEntry channel;
2511 SilcChannelID *channel_id = NULL;
2512 SilcIDListData idata;
2513 SilcBuffer idp, idp2, packet;
2514 unsigned char *tmp, *add, *del;
2516 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2518 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2520 /* Get Channel ID */
2521 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2523 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2524 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2527 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
2529 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2530 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2534 /* Get the channel entry */
2535 channel = silc_idlist_find_channel_by_id(server->local_list,
2538 channel = silc_idlist_find_channel_by_id(server->global_list,
2541 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2542 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
2548 /* Check whether the sender of this command is on the channel. */
2549 sender = (SilcClientEntry)sock->user_data;
2550 if (!sender || !silc_server_client_on_channel(sender, channel, &chl)) {
2551 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2552 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
2556 /* Check whether the channel is invite-only channel. If yes then the
2557 sender of this command must be at least channel operator. */
2558 if (channel->mode & SILC_CHANNEL_MODE_INVITE &&
2559 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
2560 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
2561 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2562 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
2567 /* Get destination client ID */
2568 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2573 dest_id = silc_id_payload_parse_id(tmp, len, NULL);
2575 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2576 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
2580 /* Get the client entry */
2581 dest = silc_server_get_client_resolve(server, dest_id, FALSE, &resolve);
2583 if (server->server_type != SILC_SERVER || !resolve) {
2584 silc_server_command_send_status_reply(
2585 cmd, SILC_COMMAND_INVITE,
2586 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0);
2590 /* The client info is being resolved. Reprocess this packet after
2591 receiving the reply to the query. */
2592 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2594 silc_server_command_invite,
2595 silc_server_command_dup(cmd));
2596 cmd->pending = TRUE;
2597 silc_free(channel_id);
2602 /* Check whether the requested client is already on the channel. */
2603 if (silc_server_client_on_channel(dest, channel, NULL)) {
2604 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2605 SILC_STATUS_ERR_USER_ON_CHANNEL,
2610 /* Get route to the client */
2611 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id,
2614 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2615 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2620 memset(invite, 0, sizeof(invite));
2621 strncat(invite, dest->nickname, strlen(dest->nickname));
2622 strncat(invite, "!", 1);
2623 strncat(invite, dest->username, strlen(dest->username));
2624 if (!strchr(dest->username, '@')) {
2625 strncat(invite, "@", 1);
2626 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2629 len = strlen(invite);
2630 if (!channel->invite_list)
2631 channel->invite_list = silc_calloc(len + 2,
2632 sizeof(*channel->invite_list));
2634 channel->invite_list = silc_realloc(channel->invite_list,
2635 sizeof(*channel->invite_list) *
2637 strlen(channel->invite_list) + 2));
2638 strncat(channel->invite_list, invite, len);
2639 strncat(channel->invite_list, ",", 1);
2641 if (!(dest->mode & SILC_UMODE_BLOCK_INVITE)) {
2642 /* Send notify to the client that is invited to the channel */
2643 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2644 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2645 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2647 SILC_NOTIFY_TYPE_INVITE, 3,
2648 idp->data, idp->len,
2649 channel->channel_name,
2650 strlen(channel->channel_name),
2651 idp2->data, idp2->len);
2652 silc_buffer_free(idp);
2653 silc_buffer_free(idp2);
2657 /* Add the client to the invite list of the channel */
2658 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2660 if (!channel->invite_list)
2661 channel->invite_list = silc_calloc(len + 2,
2662 sizeof(*channel->invite_list));
2664 channel->invite_list = silc_realloc(channel->invite_list,
2665 sizeof(*channel->invite_list) *
2667 strlen(channel->invite_list) + 2));
2668 if (add[len - 1] == ',')
2669 add[len - 1] = '\0';
2671 strncat(channel->invite_list, add, len);
2672 strncat(channel->invite_list, ",", 1);
2675 /* Get the invite to be removed and remove it from the list */
2676 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2677 if (del && channel->invite_list) {
2678 char *start, *end, *n;
2680 if (!strncmp(channel->invite_list, del,
2681 strlen(channel->invite_list) - 1)) {
2682 silc_free(channel->invite_list);
2683 channel->invite_list = NULL;
2685 start = strstr(channel->invite_list, del);
2686 if (start && strlen(start) >= len) {
2688 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2689 strncat(n, channel->invite_list, start - channel->invite_list);
2690 strncat(n, end + 1, ((channel->invite_list +
2691 strlen(channel->invite_list)) - end) - 1);
2692 silc_free(channel->invite_list);
2693 channel->invite_list = n;
2698 /* Send notify to the primary router */
2699 silc_server_send_notify_invite(server, SILC_PRIMARY_ROUTE(server),
2700 SILC_BROADCAST(server), channel,
2701 sender->id, add, del);
2703 /* Send command reply */
2704 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2708 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2709 SILC_STATUS_OK, 0, ident, 2,
2711 3, channel->invite_list,
2712 channel->invite_list ?
2713 strlen(channel->invite_list) : 0);
2716 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2717 SILC_STATUS_OK, 0, ident, 1,
2719 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2720 packet->data, packet->len, FALSE);
2721 silc_buffer_free(packet);
2725 silc_free(channel_id);
2726 silc_server_command_free(cmd);
2731 SilcSocketConnection sock;
2735 /* Quits connection to client. This gets called if client won't
2736 close the connection even when it has issued QUIT command. */
2738 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2740 QuitInternal q = (QuitInternal)context;
2742 /* Free all client specific data, such as client entry and entires
2743 on channels this client may be on. */
2744 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2746 q->sock->user_data = NULL;
2748 /* Close the connection on our side */
2749 silc_server_close_connection(q->server, q->sock);
2751 silc_free(q->signoff);
2755 /* Quits SILC session. This is the normal way to disconnect client. */
2757 SILC_SERVER_CMD_FUNC(quit)
2759 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2760 SilcServer server = cmd->server;
2761 SilcSocketConnection sock = cmd->sock;
2763 unsigned char *tmp = NULL;
2766 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2768 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2772 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2776 q = silc_calloc(1, sizeof(*q));
2779 q->signoff = tmp ? strdup(tmp) : NULL;
2781 /* We quit the connection with little timeout */
2782 silc_schedule_task_add(server->schedule, sock->sock,
2783 silc_server_command_quit_cb, (void *)q,
2784 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2787 silc_server_command_free(cmd);
2790 /* Server side of command KILL. This command is used by router operator
2791 to remove an client from the SILC Network temporarily. */
2793 SILC_SERVER_CMD_FUNC(kill)
2795 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2796 SilcServer server = cmd->server;
2797 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2798 SilcClientEntry remote_client;
2799 SilcClientID *client_id;
2800 unsigned char *tmp, *comment;
2801 SilcUInt32 tmp_len, tmp_len2;
2804 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2806 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
2809 /* KILL command works only on router */
2810 if (server->server_type != SILC_ROUTER) {
2811 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2812 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
2816 /* Check whether client has the permissions. */
2817 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2818 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2819 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
2823 /* Get the client ID */
2824 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2826 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2827 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2831 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2833 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2834 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2839 /* Get the client entry */
2840 remote_client = silc_idlist_find_client_by_id(server->local_list,
2841 client_id, TRUE, NULL);
2843 if (!remote_client) {
2844 remote_client = silc_idlist_find_client_by_id(server->global_list,
2845 client_id, TRUE, NULL);
2847 if (!remote_client) {
2848 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2849 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2856 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2860 /* Send reply to the sender */
2861 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2864 /* Check if anyone is watching this nickname */
2865 if (server->server_type == SILC_ROUTER)
2866 silc_server_check_watcher_list(server, client, NULL,
2867 SILC_NOTIFY_TYPE_KILLED);
2869 /* Now do the killing */
2870 silc_server_kill_client(server, remote_client, comment, client->id,
2874 silc_server_command_free(cmd);
2877 /* Server side of command INFO. This sends information about us to
2878 the client. If client requested specific server we will send the
2879 command to that server. */
2881 SILC_SERVER_CMD_FUNC(info)
2883 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2884 SilcServer server = cmd->server;
2885 SilcBuffer packet, idp;
2888 char *dest_server, *server_info = NULL, *server_name;
2889 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2890 SilcServerEntry entry = NULL;
2891 SilcServerID *server_id = NULL;
2893 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2895 /* Get server name */
2896 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2899 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2901 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2903 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2904 SILC_STATUS_ERR_NO_SERVER_ID, 0);
2910 /* Check whether we have this server cached */
2911 entry = silc_idlist_find_server_by_id(server->local_list,
2912 server_id, TRUE, NULL);
2914 entry = silc_idlist_find_server_by_id(server->global_list,
2915 server_id, TRUE, NULL);
2916 if (!entry && server->server_type != SILC_SERVER) {
2917 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2918 SILC_STATUS_ERR_NO_SUCH_SERVER,
2925 /* Some buggy servers has sent request to router about themselves. */
2926 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2929 if ((!dest_server && !server_id && !entry) || (entry &&
2930 entry == server->id_entry) ||
2931 (dest_server && !cmd->pending &&
2932 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2933 /* Send our reply */
2934 char info_string[256];
2936 memset(info_string, 0, sizeof(info_string));
2937 snprintf(info_string, sizeof(info_string),
2938 "location: %s server: %s admin: %s <%s>",
2939 server->config->server_info->location,
2940 server->config->server_info->server_type,
2941 server->config->server_info->admin,
2942 server->config->server_info->email);
2944 server_info = info_string;
2945 entry = server->id_entry;
2947 /* Check whether we have this server cached */
2948 if (!entry && dest_server) {
2949 entry = silc_idlist_find_server_by_name(server->global_list,
2950 dest_server, TRUE, NULL);
2952 entry = silc_idlist_find_server_by_name(server->local_list,
2953 dest_server, TRUE, NULL);
2957 if (!cmd->pending &&
2958 server->server_type != SILC_SERVER && entry && !entry->server_info) {
2959 /* Send to the server */
2961 SilcUInt16 old_ident;
2963 old_ident = silc_command_get_ident(cmd->payload);
2964 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2965 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2967 silc_server_packet_send(server, entry->connection,
2968 SILC_PACKET_COMMAND, cmd->packet->flags,
2969 tmpbuf->data, tmpbuf->len, TRUE);
2971 /* Reprocess this packet after received reply from router */
2972 silc_server_command_pending(server, SILC_COMMAND_INFO,
2973 silc_command_get_ident(cmd->payload),
2974 silc_server_command_info,
2975 silc_server_command_dup(cmd));
2976 cmd->pending = TRUE;
2977 silc_command_set_ident(cmd->payload, old_ident);
2978 silc_buffer_free(tmpbuf);
2982 if (!entry && !cmd->pending && !server->standalone) {
2983 /* Send to the primary router */
2985 SilcUInt16 old_ident;
2987 old_ident = silc_command_get_ident(cmd->payload);
2988 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2989 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2991 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
2992 SILC_PACKET_COMMAND, cmd->packet->flags,
2993 tmpbuf->data, tmpbuf->len, TRUE);
2995 /* Reprocess this packet after received reply from router */
2996 silc_server_command_pending(server, SILC_COMMAND_INFO,
2997 silc_command_get_ident(cmd->payload),
2998 silc_server_command_info,
2999 silc_server_command_dup(cmd));
3000 cmd->pending = TRUE;
3001 silc_command_set_ident(cmd->payload, old_ident);
3002 silc_buffer_free(tmpbuf);
3007 silc_free(server_id);
3010 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3011 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3015 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
3017 server_info = entry->server_info;
3018 server_name = entry->server_name;
3020 /* Send the reply */
3021 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
3022 SILC_STATUS_OK, 0, ident, 3,
3023 2, idp->data, idp->len,
3025 strlen(server_name),
3028 strlen(server_info) : 0);
3029 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3030 packet->data, packet->len, FALSE);
3032 silc_buffer_free(packet);
3033 silc_buffer_free(idp);
3036 silc_server_command_free(cmd);
3039 /* Server side of command PING. This just replies to the ping. */
3041 SILC_SERVER_CMD_FUNC(ping)
3043 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3044 SilcServer server = cmd->server;
3049 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
3052 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
3054 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3055 SILC_STATUS_ERR_NO_SERVER_ID, 0);
3058 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
3062 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
3063 /* Send our reply */
3064 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3067 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3068 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3075 silc_server_command_free(cmd);
3078 /* Server side of command STATS. */
3080 SILC_SERVER_CMD_FUNC(stats)
3082 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3083 SilcServer server = cmd->server;
3084 SilcServerID *server_id;
3087 SilcBuffer packet, stats;
3088 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3091 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1);
3094 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3096 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3097 SILC_STATUS_ERR_NO_SERVER_ID, 0);
3100 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3104 /* The ID must be ours */
3105 if (!SILC_ID_SERVER_COMPARE(server->id, server_id)) {
3106 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3107 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3108 silc_free(server_id);
3111 silc_free(server_id);
3113 /* If we are router then just send everything we got. If we are normal
3114 server then we'll send this to our router to get all the latest
3115 statistical information. */
3116 if (!cmd->pending && server->server_type != SILC_ROUTER &&
3117 !server->standalone) {
3118 /* Send request to our router */
3119 SilcBuffer idp = silc_id_payload_encode(server->router->id,
3121 packet = silc_command_payload_encode_va(SILC_COMMAND_STATS,
3122 ++server->cmd_ident, 1,
3123 1, idp->data, idp->len);
3124 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
3125 SILC_PACKET_COMMAND, 0, packet->data,
3126 packet->len, FALSE);
3128 /* Reprocess this packet after received reply from router */
3129 silc_server_command_pending(server, SILC_COMMAND_STATS,
3131 silc_server_command_stats,
3132 silc_server_command_dup(cmd));
3133 cmd->pending = TRUE;
3134 silc_buffer_free(packet);
3135 silc_buffer_free(idp);
3139 /* Send our reply to sender */
3140 uptime = time(NULL) - server->starttime;
3142 stats = silc_buffer_alloc_size(60);
3143 silc_buffer_format(stats,
3144 SILC_STR_UI_INT(server->starttime),
3145 SILC_STR_UI_INT(uptime),
3146 SILC_STR_UI_INT(server->stat.my_clients),
3147 SILC_STR_UI_INT(server->stat.my_channels),
3148 SILC_STR_UI_INT(server->stat.my_server_ops),
3149 SILC_STR_UI_INT(server->stat.my_router_ops),
3150 SILC_STR_UI_INT(server->stat.cell_clients),
3151 SILC_STR_UI_INT(server->stat.cell_channels),
3152 SILC_STR_UI_INT(server->stat.cell_servers),
3153 SILC_STR_UI_INT(server->stat.clients),
3154 SILC_STR_UI_INT(server->stat.channels),
3155 SILC_STR_UI_INT(server->stat.servers),
3156 SILC_STR_UI_INT(server->stat.routers),
3157 SILC_STR_UI_INT(server->stat.server_ops),
3158 SILC_STR_UI_INT(server->stat.router_ops),
3161 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_STATS,
3162 SILC_STATUS_OK, 0, ident, 2,
3164 3, stats->data, stats->len);
3165 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
3166 0, packet->data, packet->len, FALSE);
3167 silc_buffer_free(packet);
3168 silc_buffer_free(stats);
3171 silc_server_command_free(cmd);
3174 /* Internal routine to join channel. The channel sent to this function
3175 has been either created or resolved from ID lists. This joins the sent
3176 client to the channel. */
3178 static void silc_server_command_join_channel(SilcServer server,
3179 SilcServerCommandContext cmd,
3180 SilcChannelEntry channel,
3181 SilcClientID *client_id,
3185 const unsigned char *auth,
3186 SilcUInt32 auth_len)
3188 SilcSocketConnection sock = cmd->sock;
3190 SilcUInt32 tmp_len, user_count;
3191 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
3192 SilcClientEntry client;
3193 SilcChannelClientEntry chl;
3194 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
3195 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3196 char check[512], check2[512];
3197 bool founder = FALSE;
3199 unsigned char *fkey = NULL;
3200 SilcUInt32 fkey_len = 0;
3202 SILC_LOG_DEBUG(("Joining client to channel"));
3207 /* Get the client entry */
3208 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3209 client = (SilcClientEntry)sock->user_data;
3213 client = silc_server_get_client_resolve(server, client_id, FALSE,
3220 silc_server_command_send_status_reply(
3221 cmd, SILC_COMMAND_JOIN,
3222 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3226 /* The client info is being resolved. Reprocess this packet after
3227 receiving the reply to the query. */
3228 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
3230 silc_server_command_join,
3231 silc_server_command_dup(cmd));
3232 cmd->pending = TRUE;
3236 cmd->pending = FALSE;
3240 * Check founder auth payload if provided. If client can gain founder
3241 * privileges it can override various conditions on joining the channel,
3242 * and can have directly the founder mode set on the channel.
3244 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3245 SilcIDListData idata = (SilcIDListData)client;
3246 SilcChannelClientEntry chl2;
3247 SilcHashTableList htl;
3249 if (channel->founder_key && idata->public_key &&
3250 silc_pkcs_public_key_compare(channel->founder_key,
3251 idata->public_key)) {
3252 /* Check whether the client is to become founder */
3253 if (silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
3254 channel->founder_key, 0, server->sha1hash,
3255 client->id, SILC_ID_CLIENT)) {
3257 /* There cannot be anyone else as founder on the channel now. This
3258 client is definitely the founder due to this authentication */
3259 silc_hash_table_list(channel->user_list, &htl);
3260 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
3261 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
3262 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3263 silc_server_force_cumode_change(server, NULL, channel, chl2,
3267 silc_hash_table_list_reset(&htl);
3269 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3276 * Check channel modes
3280 memset(check, 0, sizeof(check));
3281 memset(check2, 0, sizeof(check2));
3282 strncat(check, client->nickname, strlen(client->nickname));
3283 strncat(check, "!", 1);
3284 strncat(check, client->username, strlen(client->username));
3285 if (!strchr(client->username, '@')) {
3286 strncat(check, "@", 1);
3287 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3290 strncat(check2, client->nickname, strlen(client->nickname));
3291 if (!strchr(client->nickname, '@')) {
3292 strncat(check2, "@", 1);
3293 strncat(check2, server->server_name, strlen(server->server_name));
3295 strncat(check2, "!", 1);
3296 strncat(check2, client->username, strlen(client->username));
3297 if (!strchr(client->username, '@')) {
3298 strncat(check2, "@", 1);
3299 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3302 /* Check invite list if channel is invite-only channel */
3303 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3304 if (!channel->invite_list ||
3305 (!silc_string_match(channel->invite_list, check) &&
3306 !silc_string_match(channel->invite_list, check2))) {
3307 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3308 SILC_STATUS_ERR_NOT_INVITED, 0);
3313 /* Check ban list if it exists. If the client's nickname, server,
3314 username and/or hostname is in the ban list the access to the
3315 channel is denied. */
3316 if (channel->ban_list) {
3317 if (silc_string_match(channel->ban_list, check) ||
3318 silc_string_match(channel->ban_list, check2)) {
3319 silc_server_command_send_status_reply(
3320 cmd, SILC_COMMAND_JOIN,
3321 SILC_STATUS_ERR_BANNED_FROM_CHANNEL, 0);
3326 /* Check user count limit if set. */
3327 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3328 if (silc_hash_table_count(channel->user_list) + 1 >
3329 channel->user_limit) {
3330 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3331 SILC_STATUS_ERR_CHANNEL_IS_FULL,
3338 /* Check the channel passphrase if set. */
3339 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3340 /* Get passphrase */
3341 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3343 passphrase = silc_memdup(tmp, tmp_len);
3345 if (!passphrase || !channel->passphrase ||
3346 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3347 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3348 SILC_STATUS_ERR_BAD_PASSWORD, 0);
3354 * Client is allowed to join to the channel. Make it happen.
3357 /* Check whether the client already is on the channel */
3358 if (silc_server_client_on_channel(client, channel, NULL)) {
3359 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3360 SILC_STATUS_ERR_USER_ON_CHANNEL, 0);
3364 /* Generate new channel key as protocol dictates */
3366 if (!silc_server_create_channel_key(server, channel, 0))
3369 /* Send the channel key. This is broadcasted to the channel but is not
3370 sent to the client who is joining to the channel. */
3371 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3372 silc_server_send_channel_key(server, NULL, channel,
3373 server->server_type == SILC_ROUTER ?
3374 FALSE : !server->standalone);
3377 /* Join the client to the channel by adding it to channel's user list.
3378 Add also the channel to client entry's channels list for fast cross-
3380 chl = silc_calloc(1, sizeof(*chl));
3382 chl->client = client;
3383 chl->channel = channel;
3384 silc_hash_table_add(channel->user_list, client, chl);
3385 silc_hash_table_add(client->channels, channel, chl);
3386 channel->user_count++;
3387 channel->disabled = FALSE;
3389 /* Get users on the channel */
3390 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3393 /* Encode Client ID Payload of the original client who wants to join */
3394 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3396 /* Encode command reply packet */
3397 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3398 SILC_PUT32_MSB(channel->mode, mode);
3399 SILC_PUT32_MSB(created, tmp2);
3400 SILC_PUT32_MSB(user_count, tmp3);
3402 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3403 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3404 keyp = silc_channel_key_payload_encode(silc_id_get_len(channel->id,
3407 strlen(channel->channel_key->
3409 channel->channel_key->cipher->name,
3410 channel->key_len / 8, channel->key);
3414 if (channel->founder_key)
3415 fkey = silc_pkcs_public_key_encode(channel->founder_key, &fkey_len);
3418 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3419 SILC_STATUS_OK, 0, ident, 14,
3420 2, channel->channel_name,
3421 strlen(channel->channel_name),
3422 3, chidp->data, chidp->len,
3423 4, clidp->data, clidp->len,
3426 7, keyp ? keyp->data : NULL,
3427 keyp ? keyp->len : 0,
3428 8, channel->ban_list,
3430 strlen(channel->ban_list) : 0,
3431 9, channel->invite_list,
3432 channel->invite_list ?
3433 strlen(channel->invite_list) : 0,
3436 strlen(channel->topic) : 0,
3437 11, silc_hmac_get_name(channel->hmac),
3438 strlen(silc_hmac_get_name(channel->
3441 13, user_list->data, user_list->len,
3442 14, mode_list->data,
3444 15, fkey, fkey_len);
3446 /* Send command reply */
3447 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3448 reply->data, reply->len, FALSE);
3450 /* Send JOIN notify to locally connected clients on the channel. If
3451 we are normal server then router will send or have sent JOIN notify
3452 already. However since we've added the client already to our channel
3453 we'll ignore it (in packet_receive.c) so we must send it here. If
3454 we are router then this will send it to local clients and local
3456 SILC_LOG_DEBUG(("Send JOIN notify to channel"));
3457 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3458 SILC_NOTIFY_TYPE_JOIN, 2,
3459 clidp->data, clidp->len,
3460 chidp->data, chidp->len);
3462 /* Update statistics */
3463 server->stat.my_chanclients++;
3464 if (server->server_type == SILC_ROUTER) {
3465 server->stat.cell_chanclients++;
3466 server->stat.chanclients++;
3469 if (!cmd->pending) {
3470 /* Send JOIN notify packet to our primary router */
3471 silc_server_send_notify_join(server, SILC_PRIMARY_ROUTE(server),
3472 SILC_BROADCAST(server), channel, client->id);
3475 /* Distribute the channel key to all backup routers. */
3476 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3477 keyp->data, keyp->len, FALSE, TRUE);
3479 /* If client became founder by providing correct founder auth data
3480 notify the mode change to the channel. */
3482 SILC_PUT32_MSB(chl->mode, mode);
3483 SILC_LOG_DEBUG(("Send CUMODE_CHANGE notify to channel"));
3484 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3485 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
3486 clidp->data, clidp->len,
3487 mode, 4, clidp->data, clidp->len,
3492 /* Set CUMODE notify type to network */
3494 silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
3495 SILC_BROADCAST(server), channel,
3496 chl->mode, client->id, SILC_ID_CLIENT,
3497 client->id, channel->founder_key);
3499 silc_buffer_free(reply);
3500 silc_buffer_free(clidp);
3501 silc_buffer_free(chidp);
3502 silc_buffer_free(keyp);
3503 silc_buffer_free(user_list);
3504 silc_buffer_free(mode_list);
3508 silc_free(passphrase);
3511 /* Server side of command JOIN. Joins client into requested channel. If
3512 the channel does not exist it will be created. */
3514 SILC_SERVER_CMD_FUNC(join)
3516 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3517 SilcServer server = cmd->server;
3518 unsigned char *auth;
3519 SilcUInt32 tmp_len, auth_len;
3520 char *tmp, *channel_name = NULL, *cipher, *hmac;
3521 SilcChannelEntry channel;
3522 SilcUInt32 umode = 0;
3523 bool created = FALSE, create_key = TRUE;
3524 SilcClientID *client_id;
3526 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3528 /* Get channel name */
3529 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3531 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3532 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3539 channel_name[255] = '\0';
3541 if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
3542 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3543 SILC_STATUS_ERR_BAD_CHANNEL, 0);
3547 /* Get Client ID of the client who is joining to the channel */
3548 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3550 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3551 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3555 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3557 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3558 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3563 /* Get cipher, hmac name and auth payload */
3564 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3565 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3566 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3568 /* See if the channel exists */
3569 channel = silc_idlist_find_channel_by_name(server->local_list,
3570 channel_name, NULL);
3572 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3573 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3575 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3576 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3581 silc_free(client_id);
3582 client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
3585 (channel->disabled && server->server_type != SILC_ROUTER)) {
3586 /* Channel not found */
3588 /* If we are standalone server we don't have a router, we just create
3589 the channel by ourselves. */
3590 if (server->standalone) {
3591 channel = silc_server_create_new_channel(server, server->id, cipher,
3592 hmac, channel_name, TRUE);
3594 silc_server_command_send_status_reply(
3595 cmd, SILC_COMMAND_JOIN,
3596 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
3598 silc_free(client_id);
3602 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3608 /* The channel does not exist on our server. If we are normal server
3609 we will send JOIN command to our router which will handle the
3610 joining procedure (either creates the channel if it doesn't exist
3611 or joins the client to it). */
3612 if (server->server_type != SILC_ROUTER) {
3614 SilcUInt16 old_ident;
3616 /* If this is pending command callback then we've resolved
3617 it and it didn't work, return since we've notified the
3618 client already in the command reply callback. */
3620 silc_free(client_id);
3624 old_ident = silc_command_get_ident(cmd->payload);
3625 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3626 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3628 /* Send JOIN command to our router */
3629 silc_server_packet_send(server, (SilcSocketConnection)
3630 SILC_PRIMARY_ROUTE(server),
3631 SILC_PACKET_COMMAND, cmd->packet->flags,
3632 tmpbuf->data, tmpbuf->len, TRUE);
3634 /* Reprocess this packet after received reply from router */
3635 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3636 silc_command_get_ident(cmd->payload),
3637 silc_server_command_join,
3638 silc_server_command_dup(cmd));
3639 cmd->pending = TRUE;
3640 silc_command_set_ident(cmd->payload, old_ident);
3641 silc_buffer_free(tmpbuf);
3642 silc_free(client_id);
3646 /* We are router and the channel does not seem exist so we will check
3647 our global list as well for the channel. */
3648 channel = silc_idlist_find_channel_by_name(server->global_list,
3649 channel_name, NULL);
3651 /* Channel really does not exist, create it */
3652 channel = silc_server_create_new_channel(server, server->id, cipher,
3653 hmac, channel_name, TRUE);
3655 silc_server_command_send_status_reply(
3656 cmd, SILC_COMMAND_JOIN,
3657 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
3658 silc_free(client_id);
3662 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3670 /* Channel not found */
3672 /* If the command came from router and we are normal server then
3673 something went wrong with the joining as the channel was not found.
3674 We can't do anything else but ignore this. */
3675 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3676 server->server_type != SILC_ROUTER) {
3677 silc_free(client_id);
3681 /* We are router and the channel does not seem exist so we will check
3682 our global list as well for the channel. */
3683 channel = silc_idlist_find_channel_by_name(server->global_list,
3684 channel_name, NULL);
3686 /* Channel really does not exist, create it */
3687 channel = silc_server_create_new_channel(server, server->id, cipher,
3688 hmac, channel_name, TRUE);
3690 silc_server_command_send_status_reply(
3691 cmd, SILC_COMMAND_JOIN,
3692 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
3693 silc_free(client_id);
3697 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3704 /* Check whether the channel was created by our router */
3705 if (cmd->pending && context2) {
3706 SilcServerCommandReplyContext reply = context2;
3708 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3709 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3710 SILC_GET32_MSB(created, tmp);
3711 if (silc_argument_get_arg_type(reply->args, 7, NULL))
3712 create_key = FALSE; /* Router returned the key already */
3714 if (silc_command_get_status(reply->payload, NULL, NULL) &&
3715 channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3716 /* Save channel passphrase, if user provided it successfully */
3719 pa = silc_argument_get_arg_type(cmd->args, 3, &pa_len);
3721 silc_free(channel->passphrase);
3722 channel->passphrase = silc_memdup(pa, pa_len);
3727 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
3728 !channel->disabled && !silc_hash_table_count(channel->user_list))
3732 /* If the channel does not have global users and is also empty the client
3733 will be the channel founder and operator. */
3734 if (!channel->disabled &&
3735 !channel->global_users && !silc_hash_table_count(channel->user_list))
3736 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3738 /* Join to the channel */
3739 silc_server_command_join_channel(server, cmd, channel, client_id,
3740 created, create_key, umode,
3743 silc_free(client_id);
3746 silc_server_command_free(cmd);
3749 /* Server side of command MOTD. Sends server's current "message of the
3750 day" to the client. */
3752 SILC_SERVER_CMD_FUNC(motd)
3754 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3755 SilcServer server = cmd->server;
3756 SilcBuffer packet, idp;
3757 char *motd, *dest_server;
3758 SilcUInt32 motd_len;
3759 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3761 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3763 /* Get server name */
3764 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3766 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3767 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3771 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3774 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3776 if (server->config && server->config->server_info &&
3777 server->config->server_info->motd_file) {
3779 motd = silc_file_readfile(server->config->server_info->motd_file,
3785 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3792 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3798 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3799 packet->data, packet->len, FALSE);
3800 silc_buffer_free(packet);
3801 silc_buffer_free(idp);
3803 SilcServerEntry entry;
3805 /* Check whether we have this server cached */
3806 entry = silc_idlist_find_server_by_name(server->global_list,
3807 dest_server, TRUE, NULL);
3809 entry = silc_idlist_find_server_by_name(server->local_list,
3810 dest_server, TRUE, NULL);
3813 if (server->server_type != SILC_SERVER && !cmd->pending &&
3814 entry && !entry->motd) {
3815 /* Send to the server */
3817 SilcUInt16 old_ident;
3819 old_ident = silc_command_get_ident(cmd->payload);
3820 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3821 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3823 silc_server_packet_send(server, entry->connection,
3824 SILC_PACKET_COMMAND, cmd->packet->flags,
3825 tmpbuf->data, tmpbuf->len, TRUE);
3827 /* Reprocess this packet after received reply from router */
3828 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3829 silc_command_get_ident(cmd->payload),
3830 silc_server_command_motd,
3831 silc_server_command_dup(cmd));
3832 cmd->pending = TRUE;
3833 silc_command_set_ident(cmd->payload, old_ident);
3834 silc_buffer_free(tmpbuf);
3838 if (!entry && !cmd->pending && !server->standalone) {
3839 /* Send to the primary router */
3841 SilcUInt16 old_ident;
3843 old_ident = silc_command_get_ident(cmd->payload);
3844 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3845 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3847 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
3848 SILC_PACKET_COMMAND, cmd->packet->flags,
3849 tmpbuf->data, tmpbuf->len, TRUE);
3851 /* Reprocess this packet after received reply from router */
3852 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3853 silc_command_get_ident(cmd->payload),
3854 silc_server_command_motd,
3855 silc_server_command_dup(cmd));
3856 cmd->pending = TRUE;
3857 silc_command_set_ident(cmd->payload, old_ident);
3858 silc_buffer_free(tmpbuf);
3863 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3864 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3868 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3869 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3870 SILC_STATUS_OK, 0, ident, 2,
3874 strlen(entry->motd) : 0);
3875 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3876 packet->data, packet->len, FALSE);
3877 silc_buffer_free(packet);
3878 silc_buffer_free(idp);
3882 silc_server_command_free(cmd);
3885 /* Server side of command UMODE. Client can use this command to set/unset
3886 user mode. Client actually cannot set itself to be as server/router
3887 operator so this can be used only to unset the modes. */
3889 SILC_SERVER_CMD_FUNC(umode)
3891 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3892 SilcServer server = cmd->server;
3893 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3895 unsigned char *tmp_mask, m[4];
3896 SilcUInt32 mask = 0;
3897 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3898 bool set_mask = FALSE;
3900 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
3903 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2);
3905 /* Get the client's mode mask */
3906 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3908 SILC_GET32_MSB(mask, tmp_mask);
3913 /* Check that mode changing is allowed. */
3914 if (!silc_server_check_umode_rights(server, client, mask)) {
3915 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3916 SILC_STATUS_ERR_PERM_DENIED, 0);
3920 /* Anonymous mode cannot be set by client */
3921 if (mask & SILC_UMODE_ANONYMOUS) {
3922 if (!(client->mode & SILC_UMODE_ANONYMOUS)) {
3923 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3924 SILC_STATUS_ERR_PERM_DENIED, 0);
3928 if (client->mode & SILC_UMODE_ANONYMOUS) {
3929 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3930 SILC_STATUS_ERR_PERM_DENIED, 0);
3935 /* Update statistics */
3936 if (mask & SILC_UMODE_GONE) {
3937 if (!(client->mode & SILC_UMODE_GONE))
3938 server->stat.my_aways++;
3940 if (client->mode & SILC_UMODE_GONE)
3941 server->stat.my_aways--;
3944 /* Change the mode */
3945 client->mode = mask;
3947 /* Send UMODE change to primary router */
3948 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
3949 SILC_BROADCAST(server), client->id,
3952 /* Check if anyone is watching this nickname */
3953 if (server->server_type == SILC_ROUTER)
3954 silc_server_check_watcher_list(server, client, NULL,
3955 SILC_NOTIFY_TYPE_UMODE_CHANGE);
3958 /* Send command reply to sender */
3959 SILC_PUT32_MSB(client->mode, m);
3960 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3961 SILC_STATUS_OK, 0, ident, 1,
3963 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3964 packet->data, packet->len, FALSE);
3965 silc_buffer_free(packet);
3968 silc_server_command_free(cmd);
3971 /* Server side command of CMODE. Changes channel mode */
3973 SILC_SERVER_CMD_FUNC(cmode)
3975 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3976 SilcServer server = cmd->server;
3977 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3978 SilcIDListData idata = (SilcIDListData)client;
3979 SilcChannelID *channel_id = NULL;
3980 SilcChannelEntry channel;
3981 SilcChannelClientEntry chl;
3982 SilcBuffer packet, cidp;
3983 unsigned char *tmp, *tmp_id, *tmp_mask;
3984 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3985 SilcUInt32 mode_mask = 0, old_mask = 0, tmp_len, tmp_len2;
3986 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3987 bool set_mask = FALSE;
3988 SilcPublicKey founder_key = NULL;
3989 unsigned char *fkey = NULL;
3990 SilcUInt32 fkey_len = 0;
3993 silc_server_command_free(cmd);
3997 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 7);
3999 /* Get Channel ID */
4000 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
4002 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4003 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4004 silc_server_command_free(cmd);
4007 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
4009 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4010 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4011 silc_server_command_free(cmd);
4015 /* Get channel entry */
4016 channel = silc_idlist_find_channel_by_id(server->local_list,
4019 channel = silc_idlist_find_channel_by_id(server->global_list,
4022 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4023 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4025 silc_free(channel_id);
4026 silc_server_command_free(cmd);
4030 old_mask = channel->mode;
4032 /* Get the channel mode mask */
4033 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4035 SILC_GET32_MSB(mode_mask, tmp_mask);
4039 /* Check whether this client is on the channel */
4040 if (!silc_server_client_on_channel(client, channel, &chl)) {
4041 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4042 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4046 /* Check that client has rights to change any requested channel modes */
4047 if (set_mask && !silc_server_check_cmode_rights(server, channel, chl,
4049 SILC_LOG_DEBUG(("Client does not have rights to change mode"));
4050 silc_server_command_send_status_reply(
4051 cmd, SILC_COMMAND_CMODE,
4052 (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) ?
4053 SILC_STATUS_ERR_NO_CHANNEL_PRIV :
4054 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV), 0);
4058 /* If mode mask was not sent as argument then merely return the current
4059 mode mask to the sender. */
4062 SILC_PUT32_MSB(channel->mode, m);
4063 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4064 SILC_STATUS_OK, 0, ident, 2,
4065 2, tmp_id, tmp_len2,
4067 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4068 packet->data, packet->len, FALSE);
4069 silc_buffer_free(packet);
4074 * Check the modes. Modes that requires nothing special operation are
4078 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
4079 /* Channel uses private keys to protect traffic. Client(s) has set the
4080 key locally they want to use, server does not know that key. */
4081 /* Nothing interesting to do here */
4083 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
4084 /* The mode is removed and we need to generate and distribute
4085 new channel key. Clients are not using private channel keys
4086 anymore after this. */
4088 /* Re-generate channel key */
4089 if (!silc_server_create_channel_key(server, channel, 0))
4092 /* Send the channel key. This sends it to our local clients and if
4093 we are normal server to our router as well. */
4094 silc_server_send_channel_key(server, NULL, channel,
4095 server->server_type == SILC_ROUTER ?
4096 FALSE : !server->standalone);
4098 cipher = channel->channel_key->cipher->name;
4099 hmac = (char *)silc_hmac_get_name(channel->hmac);
4103 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
4104 /* User limit is set on channel */
4105 SilcUInt32 user_limit;
4107 /* Get user limit */
4108 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
4110 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
4111 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4112 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4116 SILC_GET32_MSB(user_limit, tmp);
4117 channel->user_limit = user_limit;
4120 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
4121 /* User limit mode is unset. Remove user limit */
4122 channel->user_limit = 0;
4125 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
4126 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
4127 /* Passphrase has been set to channel */
4129 /* Get the passphrase */
4130 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
4132 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4133 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4137 /* Save the passphrase */
4138 passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
4141 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
4142 /* Passphrase mode is unset. remove the passphrase */
4143 silc_free(channel->passphrase);
4144 channel->passphrase = NULL;
4148 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
4149 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
4150 /* Cipher to use protect the traffic */
4151 SilcCipher newkey, oldkey;
4154 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
4156 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4157 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4161 /* Delete old cipher and allocate the new one */
4162 if (!silc_cipher_alloc(cipher, &newkey)) {
4163 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4164 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4168 oldkey = channel->channel_key;
4169 channel->channel_key = newkey;
4171 /* Re-generate channel key */
4172 if (!silc_server_create_channel_key(server, channel, 0)) {
4173 /* We don't have new key, revert to old one */
4174 channel->channel_key = oldkey;
4178 /* Remove old channel key for good */
4179 silc_cipher_free(oldkey);
4181 /* Send the channel key. This sends it to our local clients and if
4182 we are normal server to our router as well. */
4183 silc_server_send_channel_key(server, NULL, channel,
4184 server->server_type == SILC_ROUTER ?
4185 FALSE : !server->standalone);
4188 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
4189 /* Cipher mode is unset. Remove the cipher and revert back to
4191 SilcCipher newkey, oldkey;
4192 cipher = channel->cipher;
4194 /* Delete old cipher and allocate default one */
4195 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
4196 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4197 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4201 oldkey = channel->channel_key;
4202 channel->channel_key = newkey;
4204 /* Re-generate channel key */
4205 if (!silc_server_create_channel_key(server, channel, 0)) {
4206 /* We don't have new key, revert to old one */
4207 channel->channel_key = oldkey;
4211 /* Remove old channel key for good */
4212 silc_cipher_free(oldkey);
4214 /* Send the channel key. This sends it to our local clients and if
4215 we are normal server to our router as well. */
4216 silc_server_send_channel_key(server, NULL, channel,
4217 server->server_type == SILC_ROUTER ?
4218 FALSE : !server->standalone);
4222 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
4223 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
4224 /* HMAC to use protect the traffic */
4225 unsigned char hash[32];
4229 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4231 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4232 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4236 /* Delete old hmac and allocate the new one */
4237 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4238 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4239 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4243 silc_hmac_free(channel->hmac);
4244 channel->hmac = newhmac;
4246 /* Set the HMAC key out of current channel key. The client must do
4248 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4249 channel->key_len / 8, hash);
4250 silc_hmac_set_key(channel->hmac, hash,
4251 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4252 memset(hash, 0, sizeof(hash));
4255 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4256 /* Hmac mode is unset. Remove the hmac and revert back to
4259 unsigned char hash[32];
4260 hmac = channel->hmac_name;
4262 /* Delete old hmac and allocate default one */
4263 silc_hmac_free(channel->hmac);
4264 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4265 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4266 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4270 silc_hmac_free(channel->hmac);
4271 channel->hmac = newhmac;
4273 /* Set the HMAC key out of current channel key. The client must do
4275 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4276 channel->key_len / 8,
4278 silc_hmac_set_key(channel->hmac, hash,
4279 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4280 memset(hash, 0, sizeof(hash));
4284 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4285 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4286 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4287 /* Set the founder authentication */
4288 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4290 silc_server_command_send_status_reply(
4291 cmd, SILC_COMMAND_CMODE,
4292 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4296 /* Verify the payload before setting the mode */
4297 if (!silc_auth_verify_data(tmp, tmp_len, SILC_AUTH_PUBLIC_KEY,
4298 idata->public_key, 0, server->sha1hash,
4299 client->id, SILC_ID_CLIENT)) {
4300 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4301 SILC_STATUS_ERR_AUTH_FAILED,
4306 /* Save the public key */
4307 channel->founder_key = silc_pkcs_public_key_copy(idata->public_key);
4308 if (!channel->founder_key) {
4309 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4310 SILC_STATUS_ERR_AUTH_FAILED,
4315 founder_key = channel->founder_key;
4316 fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
4318 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4319 SILC_STATUS_ERR_AUTH_FAILED,
4321 silc_pkcs_public_key_free(channel->founder_key);
4322 channel->founder_key = NULL;
4328 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4329 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4330 if (channel->founder_key)
4331 silc_pkcs_public_key_free(channel->founder_key);
4332 channel->founder_key = NULL;
4337 /* Finally, set the mode */
4338 old_mask = channel->mode = mode_mask;
4340 /* Send CMODE_CHANGE notify. */
4341 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4342 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4343 SILC_NOTIFY_TYPE_CMODE_CHANGE, 6,
4344 cidp->data, cidp->len,
4346 cipher, cipher ? strlen(cipher) : 0,
4347 hmac, hmac ? strlen(hmac) : 0,
4348 passphrase, passphrase ?
4349 strlen(passphrase) : 0,
4352 /* Set CMODE notify type to network */
4353 silc_server_send_notify_cmode(server, SILC_PRIMARY_ROUTE(server),
4354 SILC_BROADCAST(server), channel,
4355 mode_mask, client->id, SILC_ID_CLIENT,
4356 cipher, hmac, passphrase, founder_key);
4358 /* Send command reply to sender */
4359 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4360 SILC_STATUS_OK, 0, ident, 2,
4361 2, tmp_id, tmp_len2,
4363 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4364 packet->data, packet->len, FALSE);
4366 silc_buffer_free(packet);
4367 silc_buffer_free(cidp);
4370 channel->mode = old_mask;
4372 silc_free(channel_id);
4373 silc_server_command_free(cmd);
4376 /* Server side of CUMODE command. Changes client's mode on a channel. */
4378 SILC_SERVER_CMD_FUNC(cumode)
4380 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4381 SilcServer server = cmd->server;
4382 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4383 SilcIDListData idata = (SilcIDListData)client;
4384 SilcChannelID *channel_id;
4385 SilcClientID *client_id;
4386 SilcChannelEntry channel;
4387 SilcClientEntry target_client;
4388 SilcChannelClientEntry chl;
4389 SilcBuffer packet, idp;
4390 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4391 SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4393 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4394 SilcPublicKey founder_key = NULL;
4395 unsigned char *fkey = NULL;
4396 SilcUInt32 fkey_len = 0;
4401 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4403 /* Get Channel ID */
4404 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4406 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4407 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4410 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
4412 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4413 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4417 /* Get channel entry */
4418 channel = silc_idlist_find_channel_by_id(server->local_list,
4421 channel = silc_idlist_find_channel_by_id(server->global_list,
4424 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4425 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4431 /* Check whether sender is on the channel */
4432 if (!silc_server_client_on_channel(client, channel, &chl)) {
4433 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4434 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4437 sender_mask = chl->mode;
4439 /* Get the target client's channel mode mask */
4440 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4442 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4443 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4447 SILC_GET32_MSB(target_mask, tmp_mask);
4449 /* Get target Client ID */
4450 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4452 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4453 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4456 client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
4458 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4459 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4463 /* Get target client's entry */
4464 target_client = silc_idlist_find_client_by_id(server->local_list,
4465 client_id, TRUE, NULL);
4466 if (!target_client) {
4467 target_client = silc_idlist_find_client_by_id(server->global_list,
4468 client_id, TRUE, NULL);
4471 if (target_client != client &&
4472 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4473 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4474 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4475 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
4479 /* Check whether target client is on the channel */
4480 if (target_client != client) {
4481 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4482 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4483 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL, 0);
4492 /* If the target client is founder, no one else can change their mode
4494 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4495 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4496 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
4501 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4502 if (target_client != client) {
4503 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4504 SILC_STATUS_ERR_NOT_YOU, 0);
4508 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4509 /* The client tries to claim the founder rights. */
4510 unsigned char *tmp_auth;
4511 SilcUInt32 tmp_auth_len;
4512 SilcChannelClientEntry chl2;
4513 SilcHashTableList htl;
4515 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4516 !channel->founder_key || !idata->public_key ||
4517 !silc_pkcs_public_key_compare(channel->founder_key,
4518 idata->public_key)) {
4519 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4520 SILC_STATUS_ERR_AUTH_FAILED, 0);
4524 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4526 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4527 SILC_STATUS_ERR_AUTH_FAILED, 0);
4531 /* Verify the authentication payload */
4532 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len, SILC_AUTH_PUBLIC_KEY,
4533 channel->founder_key, 0, server->sha1hash,
4534 client->id, SILC_ID_CLIENT)) {
4535 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4536 SILC_STATUS_ERR_AUTH_FAILED, 0);
4541 founder_key = channel->founder_key;
4542 fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
4544 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4545 SILC_STATUS_ERR_AUTH_FAILED, 0);
4549 /* There cannot be anyone else as founder on the channel now. This
4550 client is definitely the founder due to this authentication */
4551 silc_hash_table_list(channel->user_list, &htl);
4552 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
4553 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
4554 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4555 silc_server_force_cumode_change(server, NULL, channel, chl2,
4559 silc_hash_table_list_reset(&htl);
4561 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4564 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4565 if (target_client == client) {
4566 /* Remove channel founder rights from itself */
4567 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4570 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4571 SILC_STATUS_ERR_NOT_YOU, 0);
4577 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4578 /* Promote to operator */
4579 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4580 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4581 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4582 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4583 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
4588 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4592 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4593 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4594 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4595 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4596 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
4601 /* Demote to normal user */
4602 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4607 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4608 if (target_client != client) {
4609 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4610 SILC_STATUS_ERR_NOT_YOU, 0);
4614 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
4615 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4619 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4620 if (target_client != client) {
4621 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4622 SILC_STATUS_ERR_NOT_YOU, 0);
4626 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4631 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4632 if (target_client != client) {
4633 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4634 SILC_STATUS_ERR_NOT_YOU, 0);
4638 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)) {
4639 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4643 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4644 if (target_client != client) {
4645 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4646 SILC_STATUS_ERR_NOT_YOU, 0);
4650 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4655 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4656 if (target_client != client) {
4657 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4658 SILC_STATUS_ERR_NOT_YOU, 0);
4662 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)) {
4663 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4667 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4668 if (target_client != client) {
4669 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4670 SILC_STATUS_ERR_NOT_YOU, 0);
4674 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4679 if (target_mask & SILC_CHANNEL_UMODE_QUIET) {
4680 if (!(chl->mode & SILC_CHANNEL_UMODE_QUIET)) {
4681 if (client == target_client) {
4682 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4683 SILC_STATUS_ERR_PERM_DENIED, 0);
4686 chl->mode |= SILC_CHANNEL_UMODE_QUIET;
4690 if (chl->mode & SILC_CHANNEL_UMODE_QUIET) {
4691 if (client == target_client) {
4692 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4693 SILC_STATUS_ERR_PERM_DENIED, 0);
4696 chl->mode &= ~SILC_CHANNEL_UMODE_QUIET;
4701 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4702 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4704 /* Send notify to channel, notify only if mode was actually changed. */
4706 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4707 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
4708 idp->data, idp->len,
4713 /* Set CUMODE notify type to network */
4714 silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
4715 SILC_BROADCAST(server), channel,
4716 target_mask, client->id, SILC_ID_CLIENT,
4717 target_client->id, founder_key);
4720 /* Send command reply to sender */
4721 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4722 SILC_STATUS_OK, 0, ident, 3,
4724 3, tmp_ch_id, tmp_ch_len,
4725 4, tmp_id, tmp_len);
4726 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4727 packet->data, packet->len, FALSE);
4729 silc_buffer_free(packet);
4730 silc_free(channel_id);
4731 silc_free(client_id);
4732 silc_buffer_free(idp);
4736 silc_server_command_free(cmd);
4739 /* Server side of KICK command. Kicks client out of channel. */
4741 SILC_SERVER_CMD_FUNC(kick)
4743 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4744 SilcServer server = cmd->server;
4745 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4746 SilcClientEntry target_client;
4747 SilcChannelID *channel_id;
4748 SilcClientID *client_id;
4749 SilcChannelEntry channel;
4750 SilcChannelClientEntry chl;
4752 SilcUInt32 tmp_len, target_idp_len;
4753 unsigned char *tmp, *comment, *target_idp;
4758 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4760 /* Get Channel ID */
4761 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4763 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4764 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4767 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4769 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4770 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4774 /* Get channel entry */
4775 channel = silc_idlist_find_channel_by_id(server->local_list,
4778 channel = silc_idlist_find_channel_by_id(server->local_list,
4781 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4782 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4788 /* Check whether sender is on the channel */
4789 if (!silc_server_client_on_channel(client, channel, &chl)) {
4790 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4791 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4795 /* Check that the kicker is channel operator or channel founder */
4796 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
4797 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4798 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4799 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
4803 /* Get target Client ID */
4804 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4806 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4807 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4810 client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
4812 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4813 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4817 /* Get target client's entry */
4818 target_client = silc_idlist_find_client_by_id(server->local_list,
4819 client_id, TRUE, NULL);
4820 if (!target_client) {
4821 target_client = silc_idlist_find_client_by_id(server->global_list,
4822 client_id, TRUE, NULL);
4825 /* Check whether target client is on the channel */
4826 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4827 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4828 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL,
4833 /* Check that the target client is not channel founder. Channel founder
4834 cannot be kicked from the channel. */
4835 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4836 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4837 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
4844 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4848 /* Send command reply to sender */
4849 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4852 /* Send KICKED notify to local clients on the channel */
4853 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4854 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4855 SILC_NOTIFY_TYPE_KICKED, 3,
4856 target_idp, target_idp_len,
4857 comment, comment ? strlen(comment) : 0,
4858 idp->data, idp->len);
4859 silc_buffer_free(idp);
4861 /* Send KICKED notify to primary route */
4862 silc_server_send_notify_kicked(server, SILC_PRIMARY_ROUTE(server),
4863 SILC_BROADCAST(server), channel,
4864 target_client->id, client->id, comment);
4866 /* Remove the client from the channel. If the channel does not exist
4867 after removing the client then the client kicked itself off the channel
4868 and we don't have to send anything after that. */
4869 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4870 target_client, FALSE))
4873 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4874 /* Re-generate channel key */
4875 if (!silc_server_create_channel_key(server, channel, 0))
4878 /* Send the channel key to the channel. The key of course is not sent
4879 to the client who was kicked off the channel. */
4880 silc_server_send_channel_key(server, target_client->connection, channel,
4881 server->server_type == SILC_ROUTER ?
4882 FALSE : !server->standalone);
4886 silc_server_command_free(cmd);
4889 /* Server side of OPER command. Client uses this comand to obtain server
4890 operator privileges to this server/router. */
4892 SILC_SERVER_CMD_FUNC(oper)
4894 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4895 SilcServer server = cmd->server;
4896 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4897 unsigned char *username, *auth;
4899 SilcServerConfigAdmin *admin;
4900 SilcIDListData idata = (SilcIDListData)client;
4901 bool result = FALSE;
4902 SilcPublicKey cached_key;
4904 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
4907 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4909 /* Get the username */
4910 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4912 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4913 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4918 /* Get the admin configuration */
4919 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4920 username, client->nickname);
4922 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4923 username, client->nickname);
4925 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4926 SILC_STATUS_ERR_AUTH_FAILED,
4932 /* Get the authentication payload */
4933 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4935 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4936 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4941 /* Verify the authentication data. If both passphrase and public key
4942 is set then try both of them. */
4943 if (admin->passphrase)
4944 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4945 admin->passphrase, admin->passphrase_len,
4946 idata->hash, client->id, SILC_ID_CLIENT);
4947 if (!result && admin->publickeys) {
4948 cached_key = silc_server_get_public_key(server, admin->publickeys);
4951 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4952 cached_key, 0, idata->hash,
4953 client->id, SILC_ID_CLIENT);
4956 /* Authentication failed */
4957 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4958 SILC_STATUS_ERR_AUTH_FAILED,
4963 /* Client is now server operator */
4964 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4966 /* Update statistics */
4967 if (SILC_IS_LOCAL(client))
4968 server->stat.my_server_ops++;
4969 if (server->server_type == SILC_ROUTER)
4970 server->stat.server_ops++;
4972 /* Send UMODE change to primary router */
4973 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
4974 SILC_BROADCAST(server), client->id,
4977 /* Check if anyone is watching this nickname */
4978 if (server->server_type == SILC_ROUTER)
4979 silc_server_check_watcher_list(server, client, NULL,
4980 SILC_NOTIFY_TYPE_UMODE_CHANGE);
4982 /* Send reply to the sender */
4983 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4987 silc_server_command_free(cmd);
4990 SILC_TASK_CALLBACK(silc_server_command_detach_cb)
4992 QuitInternal q = (QuitInternal)context;
4993 SilcClientID *client_id = (SilcClientID *)q->sock;
4994 SilcClientEntry client;
4995 SilcSocketConnection sock;
4997 client = silc_idlist_find_client_by_id(q->server->local_list, client_id,
4999 if (client && client->connection) {
5000 sock = client->connection;
5002 /* If there is pending outgoing data for the client then purge it
5003 to the network before closing connection. */
5004 silc_server_packet_queue_purge(q->server, sock);
5006 /* Close the connection on our side */
5007 client->router = NULL;
5008 client->connection = NULL;
5009 sock->user_data = NULL;
5010 silc_server_close_connection(q->server, sock);
5013 silc_free(client_id);
5017 SILC_TASK_CALLBACK(silc_server_command_detach_timeout)
5019 QuitInternal q = (QuitInternal)context;
5020 SilcClientID *client_id = (SilcClientID *)q->sock;
5021 SilcClientEntry client;
5023 client = silc_idlist_find_client_by_id(q->server->local_list, client_id,
5025 if (client && client->mode & SILC_UMODE_DETACHED) {
5026 SILC_LOG_DEBUG(("Detach timeout"));
5027 silc_server_free_client_data(q->server, NULL, client, TRUE,
5031 silc_free(client_id);
5035 /* Server side of DETACH command. Detached the client from the network
5036 by closing the connection but preserving the session. */
5038 SILC_SERVER_CMD_FUNC(detach)
5040 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5041 SilcServer server = cmd->server;
5042 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5045 if (server->config->detach_disabled) {
5046 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
5047 SILC_STATUS_ERR_UNKNOWN_COMMAND, 0);
5051 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
5054 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
5056 /* Remove operator privileges, since the client may resume in some
5057 other server which to it does not have operator privileges. */
5058 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
5059 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
5061 /* Send the user mode notify to notify that client is detached */
5062 client->mode |= SILC_UMODE_DETACHED;
5063 client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
5064 client->last_command = 0;
5065 client->fast_command = 0;
5066 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
5067 SILC_BROADCAST(server), client->id,
5069 server->stat.my_detached++;
5071 /* Check if anyone is watching this nickname */
5072 if (server->server_type == SILC_ROUTER)
5073 silc_server_check_watcher_list(server, client, NULL,
5074 SILC_NOTIFY_TYPE_UMODE_CHANGE);
5076 q = silc_calloc(1, sizeof(*q));
5078 q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
5079 silc_schedule_task_add(server->schedule, 0, silc_server_command_detach_cb,
5080 q, 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
5082 if (server->config->detach_timeout) {
5083 q = silc_calloc(1, sizeof(*q));
5085 q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
5086 silc_schedule_task_add(server->schedule, 0,
5087 silc_server_command_detach_timeout,
5088 q, server->config->detach_timeout * 60,
5089 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
5092 /* Send reply to the sender */
5093 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
5097 silc_server_command_free(cmd);
5100 /* Server side of WATCH command. */
5102 SILC_SERVER_CMD_FUNC(watch)
5104 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5105 SilcServer server = cmd->server;
5106 char *add_nick, *del_nick;
5107 SilcUInt32 add_nick_len, del_nick_len, tmp_len;
5109 unsigned char hash[16], *tmp;
5110 SilcClientEntry client;
5111 SilcClientID *client_id = NULL;
5113 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WATCH, cmd, 1, 3);
5115 if (server->server_type == SILC_SERVER && !server->standalone) {
5116 if (!cmd->pending) {
5117 /* Send the command to router */
5119 SilcUInt16 old_ident;
5121 old_ident = silc_command_get_ident(cmd->payload);
5122 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5123 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5125 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5126 SILC_PACKET_COMMAND, cmd->packet->flags,
5127 tmpbuf->data, tmpbuf->len, TRUE);
5129 /* Reprocess this packet after received reply from router */
5130 silc_server_command_pending(server, SILC_COMMAND_WATCH,
5131 silc_command_get_ident(cmd->payload),
5132 silc_server_command_watch,
5133 silc_server_command_dup(cmd));
5134 cmd->pending = TRUE;
5135 silc_command_set_ident(cmd->payload, old_ident);
5136 silc_buffer_free(tmpbuf);
5137 } else if (context2) {
5138 /* Received reply from router, just send same data to the client. */
5139 SilcServerCommandReplyContext reply = context2;
5141 silc_command_get_status(reply->payload, &status, NULL);
5142 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, status,
5149 /* We are router and keep the watch list for local cell */
5151 /* Get the client ID */
5152 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5154 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5155 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5159 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
5161 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5162 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5167 /* Get the client entry which must be in local list */
5168 client = silc_idlist_find_client_by_id(server->local_list,
5169 client_id, TRUE, NULL);
5171 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5172 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5178 add_nick = silc_argument_get_arg_type(cmd->args, 2, &add_nick_len);
5179 del_nick = silc_argument_get_arg_type(cmd->args, 3, &del_nick_len);
5180 if (!add_nick && !del_nick) {
5181 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5182 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5187 if (add_nick && add_nick_len > 128)
5188 add_nick[128] = '\0';
5189 if (del_nick && del_nick_len > 128)
5190 del_nick[128] = '\0';
5192 memset(nick, 0, sizeof(nick));
5194 /* Add new nickname to be watched in our cell */
5196 if (silc_server_name_bad_chars(add_nick, strlen(add_nick)) == TRUE) {
5197 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5198 SILC_STATUS_ERR_BAD_NICKNAME, 0);
5202 /* Hash the nick, we have the hash saved, not nicks because we can
5203 do one to one mapping to the nick from Client ID hash this way. */
5204 silc_to_lower(add_nick, nick, sizeof(nick) - 1);
5205 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
5207 /* Check whether this client is already watching this nickname */
5208 if (silc_hash_table_find_by_context(server->watcher_list, hash,
5210 /* Nickname is alredy being watched for this client */
5211 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5212 SILC_STATUS_ERR_NICKNAME_IN_USE,
5217 /* Get the nickname from the watcher list and use the same key in
5218 new entries as well. If key doesn't exist then create it. */
5219 if (!silc_hash_table_find(server->watcher_list, hash, (void **)&tmp, NULL))
5220 tmp = silc_memdup(hash, CLIENTID_HASH_LEN);
5222 /* Add the client to the watcher list with the specified nickname hash. */
5223 silc_hash_table_add(server->watcher_list, tmp, client);
5226 /* Delete nickname from watch list */
5228 if (silc_server_name_bad_chars(del_nick, strlen(del_nick)) == TRUE) {
5229 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5230 SILC_STATUS_ERR_BAD_NICKNAME, 0);
5234 /* Hash the nick, we have the hash saved, not nicks because we can
5235 do one to one mapping to the nick from Client ID hash this way. */
5236 silc_to_lower(del_nick, nick, sizeof(nick) - 1);
5237 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
5239 /* Check that this client is watching for this nickname */
5240 if (!silc_hash_table_find_by_context(server->watcher_list, hash,
5241 client, (void **)&tmp)) {
5242 /* Nickname is alredy being watched for this client */
5243 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5244 SILC_STATUS_ERR_NO_SUCH_NICK, 0);
5248 /* Delete the nickname from the watcher list. */
5249 silc_hash_table_del_by_context(server->watcher_list, hash, client);
5251 /* Now check whether there still exists entries with this key, if not
5252 then free the key to not leak memory. */
5253 if (!silc_hash_table_find(server->watcher_list, hash, NULL, NULL))
5257 /* Distribute the watch list to backup routers too */
5258 if (server->backup) {
5260 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5261 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5262 silc_server_backup_send(server, NULL, SILC_PACKET_COMMAND,
5263 cmd->packet->flags, tmpbuf->data, tmpbuf->len,
5265 silc_buffer_free(tmpbuf);
5268 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5272 silc_free(client_id);
5273 silc_server_command_free(cmd);
5276 /* Server side of SILCOPER command. Client uses this comand to obtain router
5277 operator privileges to this router. */
5279 SILC_SERVER_CMD_FUNC(silcoper)
5281 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5282 SilcServer server = cmd->server;
5283 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5284 unsigned char *username, *auth;
5286 SilcServerConfigAdmin *admin;
5287 SilcIDListData idata = (SilcIDListData)client;
5288 bool result = FALSE;
5289 SilcPublicKey cached_key;
5291 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
5294 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
5296 if (server->server_type != SILC_ROUTER) {
5297 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5298 SILC_STATUS_ERR_AUTH_FAILED, 0);
5302 /* Get the username */
5303 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5305 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5306 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5311 /* Get the admin configuration */
5312 admin = silc_server_config_find_admin(server, cmd->sock->ip,
5313 username, client->nickname);
5315 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
5316 username, client->nickname);
5318 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5319 SILC_STATUS_ERR_AUTH_FAILED, 0);
5324 /* Get the authentication payload */
5325 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5327 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5328 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5333 /* Verify the authentication data. If both passphrase and public key
5334 is set then try both of them. */
5335 if (admin->passphrase)
5336 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
5337 admin->passphrase, admin->passphrase_len,
5338 idata->hash, client->id, SILC_ID_CLIENT);
5339 if (!result && admin->publickeys) {
5340 cached_key = silc_server_get_public_key(server, admin->publickeys);
5343 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
5344 cached_key, 0, idata->hash,
5345 client->id, SILC_ID_CLIENT);
5348 /* Authentication failed */
5349 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
5350 SILC_STATUS_ERR_AUTH_FAILED, 0);
5354 /* Client is now router operator */
5355 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
5357 /* Update statistics */
5358 if (SILC_IS_LOCAL(client))
5359 server->stat.my_router_ops++;
5360 if (server->server_type == SILC_ROUTER)
5361 server->stat.router_ops++;
5363 /* Send UMODE change to primary router */
5364 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
5365 SILC_BROADCAST(server), client->id,
5368 /* Check if anyone is watching this nickname */
5369 if (server->server_type == SILC_ROUTER)
5370 silc_server_check_watcher_list(server, client, NULL,
5371 SILC_NOTIFY_TYPE_UMODE_CHANGE);
5373 /* Send reply to the sender */
5374 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5378 silc_server_command_free(cmd);
5381 /* Server side of command BAN. This is used to manage the ban list of the
5382 channel. To add clients and remove clients from the ban list. */
5384 SILC_SERVER_CMD_FUNC(ban)
5386 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5387 SilcServer server = cmd->server;
5388 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5390 SilcChannelEntry channel;
5391 SilcChannelClientEntry chl;
5392 SilcChannelID *channel_id = NULL;
5393 unsigned char *id, *add, *del;
5394 SilcUInt32 id_len, tmp_len;
5395 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5397 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
5400 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
5402 /* Get Channel ID */
5403 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
5405 channel_id = silc_id_payload_parse_id(id, id_len, NULL);
5407 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5408 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5413 /* Get channel entry. The server must know about the channel since the
5414 client is expected to be on the channel. */
5415 channel = silc_idlist_find_channel_by_id(server->local_list,
5418 channel = silc_idlist_find_channel_by_id(server->global_list,
5421 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5422 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5428 /* Check whether this client is on the channel */
5429 if (!silc_server_client_on_channel(client, channel, &chl)) {
5430 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5431 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5435 /* The client must be at least channel operator. */
5436 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
5437 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5438 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
5442 /* Get the new ban and add it to the ban list */
5443 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5445 if (!channel->ban_list)
5446 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
5448 channel->ban_list = silc_realloc(channel->ban_list,
5449 sizeof(*channel->ban_list) *
5451 strlen(channel->ban_list) + 2));
5452 if (add[tmp_len - 1] == ',')
5453 add[tmp_len - 1] = '\0';
5455 strncat(channel->ban_list, add, tmp_len);
5456 strncat(channel->ban_list, ",", 1);
5459 /* Get the ban to be removed and remove it from the list */
5460 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
5461 if (del && channel->ban_list) {
5462 char *start, *end, *n;
5464 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
5465 silc_free(channel->ban_list);
5466 channel->ban_list = NULL;
5468 start = strstr(channel->ban_list, del);
5469 if (start && strlen(start) >= tmp_len) {
5470 end = start + tmp_len;
5471 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
5472 strncat(n, channel->ban_list, start - channel->ban_list);
5473 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
5475 silc_free(channel->ban_list);
5476 channel->ban_list = n;
5481 /* Send the BAN notify type to our primary router. */
5483 silc_server_send_notify_ban(server, SILC_PRIMARY_ROUTE(server),
5484 SILC_BROADCAST(server), channel, add, del);
5486 /* Send the reply back to the client */
5488 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
5489 SILC_STATUS_OK, 0, ident, 2,
5491 3, channel->ban_list,
5493 strlen(channel->ban_list) -1 : 0);
5494 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5495 packet->data, packet->len, FALSE);
5497 silc_buffer_free(packet);
5500 silc_free(channel_id);
5501 silc_server_command_free(cmd);
5504 /* Server side command of LEAVE. Removes client from a channel. */
5506 SILC_SERVER_CMD_FUNC(leave)
5508 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5509 SilcServer server = cmd->server;
5510 SilcSocketConnection sock = cmd->sock;
5511 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
5512 SilcChannelID *id = NULL;
5513 SilcChannelEntry channel;
5517 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !id_entry)
5520 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
5522 /* Get Channel ID */
5523 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
5525 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5526 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5529 id = silc_id_payload_parse_id(tmp, len, NULL);
5531 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5532 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5536 /* Get channel entry */
5537 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5539 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5541 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5542 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5548 /* Check whether this client is on the channel */
5549 if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
5550 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5551 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5555 /* Notify routers that they should remove this client from their list
5556 of clients on the channel. Send LEAVE notify type. */
5557 silc_server_send_notify_leave(server, SILC_PRIMARY_ROUTE(server),
5558 SILC_BROADCAST(server), channel, id_entry->id);
5560 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
5561 SILC_STATUS_OK, 0, 2, tmp, len);
5563 /* Remove client from channel */
5564 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5566 /* If the channel does not exist anymore we won't send anything */
5569 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5570 /* Re-generate channel key */
5571 if (!silc_server_create_channel_key(server, channel, 0))
5574 /* Send the channel key */
5575 silc_server_send_channel_key(server, NULL, channel,
5576 server->server_type == SILC_ROUTER ?
5577 FALSE : !server->standalone);
5582 silc_server_command_free(cmd);
5585 /* Server side of command USERS. Resolves clients and their USERS currently
5586 joined on the requested channel. The list of Client ID's and their modes
5587 on the channel is sent back. */
5589 SILC_SERVER_CMD_FUNC(users)
5591 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5592 SilcServer server = cmd->server;
5593 SilcChannelEntry channel;
5594 SilcChannelID *id = NULL;
5595 SilcBuffer packet, idp;
5596 unsigned char *channel_id;
5597 SilcUInt32 channel_id_len;
5598 SilcBuffer client_id_list;
5599 SilcBuffer client_mode_list;
5600 unsigned char lc[4];
5601 SilcUInt32 list_count = 0;
5602 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5605 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5607 /* Get Channel ID */
5608 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5610 /* Get channel name */
5611 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5613 if (!channel_id && !channel_name) {
5614 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5615 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5620 id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
5622 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5623 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5628 /* If we are server and we don't know about this channel we will send
5629 the command to our router. If we know about the channel then we also
5630 have the list of users already. */
5632 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5634 channel = silc_idlist_find_channel_by_name(server->local_list,
5635 channel_name, NULL);
5637 if (!channel || (!server->standalone && (channel->disabled ||
5638 !channel->users_resolved))) {
5639 if (server->server_type != SILC_ROUTER && !server->standalone &&
5643 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5644 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5646 /* Send USERS command */
5647 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5648 SILC_PACKET_COMMAND, cmd->packet->flags,
5649 tmpbuf->data, tmpbuf->len, TRUE);
5651 /* Reprocess this packet after received reply */
5652 silc_server_command_pending(server, SILC_COMMAND_USERS,
5653 silc_command_get_ident(cmd->payload),
5654 silc_server_command_users,
5655 silc_server_command_dup(cmd));
5656 cmd->pending = TRUE;
5657 silc_command_set_ident(cmd->payload, ident);
5658 silc_buffer_free(tmpbuf);
5663 /* Check the global list as well. */
5665 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5667 channel = silc_idlist_find_channel_by_name(server->global_list,
5668 channel_name, NULL);
5670 /* Channel really does not exist */
5671 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5672 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5678 /* If the channel is private or secret do not send anything, unless the
5679 user requesting this command is on the channel or is server */
5680 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5681 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5682 && !silc_server_client_on_channel(cmd->sock->user_data, channel,
5684 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5685 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5691 /* Get the users list */
5692 if (!silc_server_get_users_on_channel(server, channel, &client_id_list,
5693 &client_mode_list, &list_count)) {
5695 client_id_list = NULL;
5696 client_mode_list = NULL;
5700 SILC_PUT32_MSB(list_count, lc);
5703 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5704 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5705 SILC_STATUS_OK, 0, ident, 4,
5706 2, idp->data, idp->len,
5709 client_id_list->data : NULL,
5711 client_id_list->len : 0,
5712 5, client_mode_list ?
5713 client_mode_list->data : NULL,
5715 client_mode_list->len : 0);
5716 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5717 packet->data, packet->len, FALSE);
5719 silc_buffer_free(idp);
5720 silc_buffer_free(packet);
5722 silc_buffer_free(client_id_list);
5723 if (client_mode_list)
5724 silc_buffer_free(client_mode_list);
5728 silc_server_command_free(cmd);
5731 /* Server side of command GETKEY. This fetches the client's public key
5732 from the server where to the client is connected. */
5734 SILC_SERVER_CMD_FUNC(getkey)
5736 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5737 SilcServer server = cmd->server;
5739 SilcClientEntry client;
5740 SilcServerEntry server_entry;
5741 SilcClientID *client_id = NULL;
5742 SilcServerID *server_id = NULL;
5743 SilcIDPayload idp = NULL;
5744 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5745 unsigned char *tmp, *pkdata;
5746 SilcUInt32 tmp_len, pklen;
5747 SilcBuffer pk = NULL;
5749 SilcPublicKey public_key;
5751 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5753 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5754 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5758 idp = silc_id_payload_parse(tmp, tmp_len);
5760 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5761 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5766 id_type = silc_id_payload_get_type(idp);
5767 if (id_type == SILC_ID_CLIENT) {
5768 client_id = silc_id_payload_get_id(idp);
5770 /* If the client is not found from local list there is no chance it
5771 would be locally connected client so send the command further. */
5772 client = silc_idlist_find_client_by_id(server->local_list,
5773 client_id, TRUE, NULL);
5775 client = silc_idlist_find_client_by_id(server->global_list,
5776 client_id, TRUE, NULL);
5778 if ((!client && !cmd->pending && !server->standalone) ||
5779 (client && !client->connection && !cmd->pending &&
5780 !(client->mode & SILC_UMODE_DETACHED)) ||
5781 (client && !client->data.public_key && !cmd->pending)) {
5783 SilcUInt16 old_ident;
5784 SilcSocketConnection dest_sock;
5786 dest_sock = silc_server_get_client_route(server, NULL, 0,
5787 client_id, NULL, NULL);
5791 old_ident = silc_command_get_ident(cmd->payload);
5792 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5793 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5795 silc_server_packet_send(server, dest_sock,
5796 SILC_PACKET_COMMAND, cmd->packet->flags,
5797 tmpbuf->data, tmpbuf->len, TRUE);
5799 /* Reprocess this packet after received reply from router */
5800 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5801 silc_command_get_ident(cmd->payload),
5802 silc_server_command_getkey,
5803 silc_server_command_dup(cmd));
5804 cmd->pending = TRUE;
5805 silc_command_set_ident(cmd->payload, old_ident);
5806 silc_buffer_free(tmpbuf);
5811 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5812 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5817 /* The client is locally connected, just get the public key and
5818 send it back. If they key does not exist then do not send it,
5819 send just OK reply */
5820 public_key = client->data.public_key;
5825 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5826 pk = silc_buffer_alloc(4 + tmp_len);
5827 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5828 silc_buffer_format(pk,
5829 SILC_STR_UI_SHORT(tmp_len),
5830 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5831 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5837 } else if (id_type == SILC_ID_SERVER) {
5838 server_id = silc_id_payload_get_id(idp);
5840 /* If the server is not found from local list there is no chance it
5841 would be locally connected server so send the command further. */
5842 server_entry = silc_idlist_find_server_by_id(server->local_list,
5843 server_id, TRUE, NULL);
5845 server_entry = silc_idlist_find_server_by_id(server->global_list,
5846 server_id, TRUE, NULL);
5848 if (server_entry != server->id_entry &&
5849 ((!server_entry && !cmd->pending && !server->standalone) ||
5850 (server_entry && !server_entry->connection && !cmd->pending &&
5851 !server->standalone) ||
5852 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5853 !server->standalone))) {
5855 SilcUInt16 old_ident;
5857 old_ident = silc_command_get_ident(cmd->payload);
5858 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5859 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5861 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5862 SILC_PACKET_COMMAND, cmd->packet->flags,
5863 tmpbuf->data, tmpbuf->len, TRUE);
5865 /* Reprocess this packet after received reply from router */
5866 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5867 silc_command_get_ident(cmd->payload),
5868 silc_server_command_getkey,
5869 silc_server_command_dup(cmd));
5870 cmd->pending = TRUE;
5871 silc_command_set_ident(cmd->payload, old_ident);
5872 silc_buffer_free(tmpbuf);
5876 if (!server_entry) {
5877 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5878 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
5883 /* If they key does not exist then do not send it, send just OK reply */
5884 public_key = (!server_entry->data.public_key ?
5885 (server_entry == server->id_entry ? server->public_key :
5886 NULL) : server_entry->data.public_key);
5891 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5892 pk = silc_buffer_alloc(4 + tmp_len);
5893 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5894 silc_buffer_format(pk,
5895 SILC_STR_UI_SHORT(tmp_len),
5896 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5897 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5907 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5908 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5909 SILC_STATUS_OK, 0, ident,
5913 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5914 packet->data, packet->len, FALSE);
5915 silc_buffer_free(packet);
5918 silc_buffer_free(pk);
5922 silc_id_payload_free(idp);
5923 silc_free(client_id);
5924 silc_free(server_id);
5925 silc_server_command_free(cmd);
5929 /* Private range commands, specific to this implementation */
5931 /* Server side command of CONNECT. Connects us to the specified remote
5932 server or router. */
5934 SILC_SERVER_CMD_FUNC(connect)
5936 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5937 SilcServer server = cmd->server;
5938 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5939 unsigned char *tmp, *host;
5941 SilcUInt32 port = SILC_PORT;
5943 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
5946 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
5948 /* Check whether client has the permissions. */
5949 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5950 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5951 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5952 SILC_STATUS_ERR_NO_SERVER_PRIV, 0);
5956 if (server->server_type == SILC_ROUTER &&
5957 client->mode & SILC_UMODE_SERVER_OPERATOR) {
5958 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5959 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
5963 /* Get the remote server */
5964 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5966 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5967 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5973 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5975 SILC_GET32_MSB(port, tmp);
5977 /* Create the connection. It is done with timeout and is async. */
5978 silc_server_create_connection(server, host, port);
5980 /* Send reply to the sender */
5981 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5985 silc_server_command_free(cmd);
5988 /* Server side command of CLOSE. Closes connection to a specified server. */
5990 SILC_SERVER_CMD_FUNC(close)
5992 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5993 SilcServer server = cmd->server;
5994 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5995 SilcServerEntry server_entry;
5996 SilcSocketConnection sock;
5999 unsigned char *name;
6000 SilcUInt32 port = SILC_PORT;
6002 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
6005 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
6007 /* Check whether client has the permissions. */
6008 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
6009 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
6010 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
6011 SILC_STATUS_ERR_NO_SERVER_PRIV,
6016 /* Get the remote server */
6017 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
6019 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
6020 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
6026 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
6028 SILC_GET32_MSB(port, tmp);
6030 server_entry = silc_idlist_find_server_by_conn(server->local_list,
6031 name, port, FALSE, NULL);
6033 server_entry = silc_idlist_find_server_by_conn(server->global_list,
6034 name, port, FALSE, NULL);
6035 if (!server_entry) {
6036 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
6037 SILC_STATUS_ERR_NO_SERVER_ID, 0);
6041 if (server_entry == server->id_entry) {
6042 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
6043 SILC_STATUS_ERR_NO_SERVER_ID, 0);
6047 /* Send reply to the sender */
6048 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
6051 /* Close the connection to the server */
6052 sock = (SilcSocketConnection)server_entry->connection;
6054 /* If we shutdown primary router connection manually then don't trigger
6055 any reconnect or backup router connections, by setting the router
6057 if (server->router == server_entry) {
6058 server->id_entry->router = NULL;
6059 server->router = NULL;
6060 server->standalone = TRUE;
6062 silc_server_free_sock_user_data(server, sock, NULL);
6063 silc_server_close_connection(server, sock);
6066 silc_server_command_free(cmd);
6069 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
6070 active connections. */
6072 SILC_SERVER_CMD_FUNC(shutdown)
6074 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
6075 SilcServer server = cmd->server;
6076 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
6078 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
6081 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
6083 /* Check whether client has the permission. */
6084 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
6085 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
6086 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
6087 SILC_STATUS_ERR_NO_SERVER_PRIV,
6092 /* Send reply to the sender */
6093 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
6096 /* Then, gracefully, or not, bring the server down. */
6097 silc_server_stop(server);
6101 silc_server_command_free(cmd);