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 or not valid */
3588 /* If we are standalone server we don't have a router, we just create
3589 the channel by ourselves (unless it existed). */
3590 if (server->standalone) {
3592 channel = silc_server_create_new_channel(server, server->id, cipher,
3593 hmac, channel_name, TRUE);
3595 silc_server_command_send_status_reply(
3596 cmd, SILC_COMMAND_JOIN,
3597 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
3599 silc_free(client_id);
3603 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3609 /* The channel does not exist on our server. If we are normal server
3610 we will send JOIN command to our router which will handle the
3611 joining procedure (either creates the channel if it doesn't exist
3612 or joins the client to it). */
3613 if (server->server_type != SILC_ROUTER) {
3615 SilcUInt16 old_ident;
3617 /* If this is pending command callback then we've resolved
3618 it and it didn't work, return since we've notified the
3619 client already in the command reply callback. */
3621 silc_free(client_id);
3625 old_ident = silc_command_get_ident(cmd->payload);
3626 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3627 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3629 /* Send JOIN command to our router */
3630 silc_server_packet_send(server, (SilcSocketConnection)
3631 SILC_PRIMARY_ROUTE(server),
3632 SILC_PACKET_COMMAND, cmd->packet->flags,
3633 tmpbuf->data, tmpbuf->len, TRUE);
3635 /* Reprocess this packet after received reply from router */
3636 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3637 silc_command_get_ident(cmd->payload),
3638 silc_server_command_join,
3639 silc_server_command_dup(cmd));
3640 cmd->pending = TRUE;
3641 silc_command_set_ident(cmd->payload, old_ident);
3642 silc_buffer_free(tmpbuf);
3643 silc_free(client_id);
3647 /* We are router and the channel does not seem exist so we will check
3648 our global list as well for the channel. */
3649 channel = silc_idlist_find_channel_by_name(server->global_list,
3650 channel_name, NULL);
3652 /* Channel really does not exist, create it */
3653 channel = silc_server_create_new_channel(server, server->id, cipher,
3654 hmac, channel_name, TRUE);
3656 silc_server_command_send_status_reply(
3657 cmd, SILC_COMMAND_JOIN,
3658 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
3659 silc_free(client_id);
3663 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3671 /* Channel not found */
3673 /* If the command came from router and we are normal server then
3674 something went wrong with the joining as the channel was not found.
3675 We can't do anything else but ignore this. */
3676 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3677 server->server_type != SILC_ROUTER) {
3678 silc_free(client_id);
3682 /* We are router and the channel does not seem exist so we will check
3683 our global list as well for the channel. */
3684 channel = silc_idlist_find_channel_by_name(server->global_list,
3685 channel_name, NULL);
3687 /* Channel really does not exist, create it */
3688 channel = silc_server_create_new_channel(server, server->id, cipher,
3689 hmac, channel_name, TRUE);
3691 silc_server_command_send_status_reply(
3692 cmd, SILC_COMMAND_JOIN,
3693 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
3694 silc_free(client_id);
3698 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3705 /* Check whether the channel was created by our router */
3706 if (cmd->pending && context2) {
3707 SilcServerCommandReplyContext reply = context2;
3709 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3710 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3711 SILC_GET32_MSB(created, tmp);
3712 if (silc_argument_get_arg_type(reply->args, 7, NULL))
3713 create_key = FALSE; /* Router returned the key already */
3715 if (silc_command_get_status(reply->payload, NULL, NULL) &&
3716 channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3717 /* Save channel passphrase, if user provided it successfully */
3720 pa = silc_argument_get_arg_type(cmd->args, 3, &pa_len);
3722 silc_free(channel->passphrase);
3723 channel->passphrase = silc_memdup(pa, pa_len);
3728 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
3729 !channel->disabled && !silc_hash_table_count(channel->user_list))
3733 /* If the channel does not have global users and is also empty the client
3734 will be the channel founder and operator. */
3735 if (!channel->disabled &&
3736 !channel->global_users && !silc_hash_table_count(channel->user_list))
3737 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3739 /* Join to the channel */
3740 silc_server_command_join_channel(server, cmd, channel, client_id,
3741 created, create_key, umode,
3744 silc_free(client_id);
3747 silc_server_command_free(cmd);
3750 /* Server side of command MOTD. Sends server's current "message of the
3751 day" to the client. */
3753 SILC_SERVER_CMD_FUNC(motd)
3755 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3756 SilcServer server = cmd->server;
3757 SilcBuffer packet, idp;
3758 char *motd, *dest_server;
3759 SilcUInt32 motd_len;
3760 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3762 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3764 /* Get server name */
3765 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3767 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3768 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3772 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3775 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3777 if (server->config && server->config->server_info &&
3778 server->config->server_info->motd_file) {
3780 motd = silc_file_readfile(server->config->server_info->motd_file,
3786 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3793 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3799 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3800 packet->data, packet->len, FALSE);
3801 silc_buffer_free(packet);
3802 silc_buffer_free(idp);
3804 SilcServerEntry entry;
3806 /* Check whether we have this server cached */
3807 entry = silc_idlist_find_server_by_name(server->global_list,
3808 dest_server, TRUE, NULL);
3810 entry = silc_idlist_find_server_by_name(server->local_list,
3811 dest_server, TRUE, NULL);
3814 if (server->server_type != SILC_SERVER && !cmd->pending &&
3815 entry && !entry->motd) {
3816 /* Send to the server */
3818 SilcUInt16 old_ident;
3820 old_ident = silc_command_get_ident(cmd->payload);
3821 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3822 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3824 silc_server_packet_send(server, entry->connection,
3825 SILC_PACKET_COMMAND, cmd->packet->flags,
3826 tmpbuf->data, tmpbuf->len, TRUE);
3828 /* Reprocess this packet after received reply from router */
3829 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3830 silc_command_get_ident(cmd->payload),
3831 silc_server_command_motd,
3832 silc_server_command_dup(cmd));
3833 cmd->pending = TRUE;
3834 silc_command_set_ident(cmd->payload, old_ident);
3835 silc_buffer_free(tmpbuf);
3839 if (!entry && !cmd->pending && !server->standalone) {
3840 /* Send to the primary router */
3842 SilcUInt16 old_ident;
3844 old_ident = silc_command_get_ident(cmd->payload);
3845 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3846 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3848 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
3849 SILC_PACKET_COMMAND, cmd->packet->flags,
3850 tmpbuf->data, tmpbuf->len, TRUE);
3852 /* Reprocess this packet after received reply from router */
3853 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3854 silc_command_get_ident(cmd->payload),
3855 silc_server_command_motd,
3856 silc_server_command_dup(cmd));
3857 cmd->pending = TRUE;
3858 silc_command_set_ident(cmd->payload, old_ident);
3859 silc_buffer_free(tmpbuf);
3864 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3865 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3869 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3870 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3871 SILC_STATUS_OK, 0, ident, 2,
3875 strlen(entry->motd) : 0);
3876 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3877 packet->data, packet->len, FALSE);
3878 silc_buffer_free(packet);
3879 silc_buffer_free(idp);
3883 silc_server_command_free(cmd);
3886 /* Server side of command UMODE. Client can use this command to set/unset
3887 user mode. Client actually cannot set itself to be as server/router
3888 operator so this can be used only to unset the modes. */
3890 SILC_SERVER_CMD_FUNC(umode)
3892 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3893 SilcServer server = cmd->server;
3894 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3896 unsigned char *tmp_mask, m[4];
3897 SilcUInt32 mask = 0;
3898 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3899 bool set_mask = FALSE;
3901 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
3904 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2);
3906 /* Get the client's mode mask */
3907 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3909 SILC_GET32_MSB(mask, tmp_mask);
3914 /* Check that mode changing is allowed. */
3915 if (!silc_server_check_umode_rights(server, client, mask)) {
3916 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3917 SILC_STATUS_ERR_PERM_DENIED, 0);
3921 /* Anonymous mode cannot be set by client */
3922 if (mask & SILC_UMODE_ANONYMOUS) {
3923 if (!(client->mode & SILC_UMODE_ANONYMOUS)) {
3924 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3925 SILC_STATUS_ERR_PERM_DENIED, 0);
3929 if (client->mode & SILC_UMODE_ANONYMOUS) {
3930 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3931 SILC_STATUS_ERR_PERM_DENIED, 0);
3936 /* Update statistics */
3937 if (mask & SILC_UMODE_GONE) {
3938 if (!(client->mode & SILC_UMODE_GONE))
3939 server->stat.my_aways++;
3941 if (client->mode & SILC_UMODE_GONE)
3942 server->stat.my_aways--;
3945 /* Change the mode */
3946 client->mode = mask;
3948 /* Send UMODE change to primary router */
3949 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
3950 SILC_BROADCAST(server), client->id,
3953 /* Check if anyone is watching this nickname */
3954 if (server->server_type == SILC_ROUTER)
3955 silc_server_check_watcher_list(server, client, NULL,
3956 SILC_NOTIFY_TYPE_UMODE_CHANGE);
3959 /* Send command reply to sender */
3960 SILC_PUT32_MSB(client->mode, m);
3961 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3962 SILC_STATUS_OK, 0, ident, 1,
3964 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3965 packet->data, packet->len, FALSE);
3966 silc_buffer_free(packet);
3969 silc_server_command_free(cmd);
3972 /* Server side command of CMODE. Changes channel mode */
3974 SILC_SERVER_CMD_FUNC(cmode)
3976 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3977 SilcServer server = cmd->server;
3978 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3979 SilcIDListData idata = (SilcIDListData)client;
3980 SilcChannelID *channel_id = NULL;
3981 SilcChannelEntry channel;
3982 SilcChannelClientEntry chl;
3983 SilcBuffer packet, cidp;
3984 unsigned char *tmp, *tmp_id, *tmp_mask;
3985 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3986 SilcUInt32 mode_mask = 0, old_mask = 0, tmp_len, tmp_len2;
3987 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3988 bool set_mask = FALSE;
3989 SilcPublicKey founder_key = NULL;
3990 unsigned char *fkey = NULL;
3991 SilcUInt32 fkey_len = 0;
3994 silc_server_command_free(cmd);
3998 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 7);
4000 /* Get Channel ID */
4001 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
4003 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4004 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4005 silc_server_command_free(cmd);
4008 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
4010 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4011 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4012 silc_server_command_free(cmd);
4016 /* Get channel entry */
4017 channel = silc_idlist_find_channel_by_id(server->local_list,
4020 channel = silc_idlist_find_channel_by_id(server->global_list,
4023 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4024 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4026 silc_free(channel_id);
4027 silc_server_command_free(cmd);
4031 old_mask = channel->mode;
4033 /* Get the channel mode mask */
4034 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4036 SILC_GET32_MSB(mode_mask, tmp_mask);
4040 /* Check whether this client is on the channel */
4041 if (!silc_server_client_on_channel(client, channel, &chl)) {
4042 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4043 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4047 /* Check that client has rights to change any requested channel modes */
4048 if (set_mask && !silc_server_check_cmode_rights(server, channel, chl,
4050 SILC_LOG_DEBUG(("Client does not have rights to change mode"));
4051 silc_server_command_send_status_reply(
4052 cmd, SILC_COMMAND_CMODE,
4053 (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) ?
4054 SILC_STATUS_ERR_NO_CHANNEL_PRIV :
4055 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV), 0);
4059 /* If mode mask was not sent as argument then merely return the current
4060 mode mask to the sender. */
4063 SILC_PUT32_MSB(channel->mode, m);
4064 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4065 SILC_STATUS_OK, 0, ident, 2,
4066 2, tmp_id, tmp_len2,
4068 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4069 packet->data, packet->len, FALSE);
4070 silc_buffer_free(packet);
4075 * Check the modes. Modes that requires nothing special operation are
4079 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
4080 /* Channel uses private keys to protect traffic. Client(s) has set the
4081 key locally they want to use, server does not know that key. */
4082 /* Nothing interesting to do here */
4084 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
4085 /* The mode is removed and we need to generate and distribute
4086 new channel key. Clients are not using private channel keys
4087 anymore after this. */
4089 /* Re-generate channel key */
4090 if (!silc_server_create_channel_key(server, channel, 0))
4093 /* Send the channel key. This sends it to our local clients and if
4094 we are normal server to our router as well. */
4095 silc_server_send_channel_key(server, NULL, channel,
4096 server->server_type == SILC_ROUTER ?
4097 FALSE : !server->standalone);
4099 cipher = channel->channel_key->cipher->name;
4100 hmac = (char *)silc_hmac_get_name(channel->hmac);
4104 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
4105 /* User limit is set on channel */
4106 SilcUInt32 user_limit;
4108 /* Get user limit */
4109 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
4111 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
4112 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4113 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4117 SILC_GET32_MSB(user_limit, tmp);
4118 channel->user_limit = user_limit;
4121 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
4122 /* User limit mode is unset. Remove user limit */
4123 channel->user_limit = 0;
4126 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
4127 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
4128 /* Passphrase has been set to channel */
4130 /* Get the passphrase */
4131 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
4133 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4134 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4138 /* Save the passphrase */
4139 passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
4142 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
4143 /* Passphrase mode is unset. remove the passphrase */
4144 silc_free(channel->passphrase);
4145 channel->passphrase = NULL;
4149 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
4150 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
4151 /* Cipher to use protect the traffic */
4152 SilcCipher newkey, oldkey;
4155 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
4157 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4158 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4162 /* Delete old cipher and allocate the new one */
4163 if (!silc_cipher_alloc(cipher, &newkey)) {
4164 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4165 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4169 oldkey = channel->channel_key;
4170 channel->channel_key = newkey;
4172 /* Re-generate channel key */
4173 if (!silc_server_create_channel_key(server, channel, 0)) {
4174 /* We don't have new key, revert to old one */
4175 channel->channel_key = oldkey;
4179 /* Remove old channel key for good */
4180 silc_cipher_free(oldkey);
4182 /* Send the channel key. This sends it to our local clients and if
4183 we are normal server to our router as well. */
4184 silc_server_send_channel_key(server, NULL, channel,
4185 server->server_type == SILC_ROUTER ?
4186 FALSE : !server->standalone);
4189 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
4190 /* Cipher mode is unset. Remove the cipher and revert back to
4192 SilcCipher newkey, oldkey;
4193 cipher = channel->cipher;
4195 /* Delete old cipher and allocate default one */
4196 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
4197 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4198 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4202 oldkey = channel->channel_key;
4203 channel->channel_key = newkey;
4205 /* Re-generate channel key */
4206 if (!silc_server_create_channel_key(server, channel, 0)) {
4207 /* We don't have new key, revert to old one */
4208 channel->channel_key = oldkey;
4212 /* Remove old channel key for good */
4213 silc_cipher_free(oldkey);
4215 /* Send the channel key. This sends it to our local clients and if
4216 we are normal server to our router as well. */
4217 silc_server_send_channel_key(server, NULL, channel,
4218 server->server_type == SILC_ROUTER ?
4219 FALSE : !server->standalone);
4223 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
4224 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
4225 /* HMAC to use protect the traffic */
4226 unsigned char hash[32];
4230 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4232 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4233 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4237 /* Delete old hmac and allocate the new one */
4238 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4239 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4240 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4244 silc_hmac_free(channel->hmac);
4245 channel->hmac = newhmac;
4247 /* Set the HMAC key out of current channel key. The client must do
4249 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4250 channel->key_len / 8, hash);
4251 silc_hmac_set_key(channel->hmac, hash,
4252 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4253 memset(hash, 0, sizeof(hash));
4256 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4257 /* Hmac mode is unset. Remove the hmac and revert back to
4260 unsigned char hash[32];
4261 hmac = channel->hmac_name;
4263 /* Delete old hmac and allocate default one */
4264 silc_hmac_free(channel->hmac);
4265 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4266 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4267 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4271 silc_hmac_free(channel->hmac);
4272 channel->hmac = newhmac;
4274 /* Set the HMAC key out of current channel key. The client must do
4276 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4277 channel->key_len / 8,
4279 silc_hmac_set_key(channel->hmac, hash,
4280 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4281 memset(hash, 0, sizeof(hash));
4285 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4286 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4287 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4288 /* Set the founder authentication */
4289 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4291 silc_server_command_send_status_reply(
4292 cmd, SILC_COMMAND_CMODE,
4293 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4297 /* Verify the payload before setting the mode */
4298 if (!silc_auth_verify_data(tmp, tmp_len, SILC_AUTH_PUBLIC_KEY,
4299 idata->public_key, 0, server->sha1hash,
4300 client->id, SILC_ID_CLIENT)) {
4301 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4302 SILC_STATUS_ERR_AUTH_FAILED,
4307 /* Save the public key */
4308 channel->founder_key = silc_pkcs_public_key_copy(idata->public_key);
4309 if (!channel->founder_key) {
4310 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4311 SILC_STATUS_ERR_AUTH_FAILED,
4316 founder_key = channel->founder_key;
4317 fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
4319 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4320 SILC_STATUS_ERR_AUTH_FAILED,
4322 silc_pkcs_public_key_free(channel->founder_key);
4323 channel->founder_key = NULL;
4329 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4330 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4331 if (channel->founder_key)
4332 silc_pkcs_public_key_free(channel->founder_key);
4333 channel->founder_key = NULL;
4338 /* Finally, set the mode */
4339 old_mask = channel->mode = mode_mask;
4341 /* Send CMODE_CHANGE notify. */
4342 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4343 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4344 SILC_NOTIFY_TYPE_CMODE_CHANGE, 6,
4345 cidp->data, cidp->len,
4347 cipher, cipher ? strlen(cipher) : 0,
4348 hmac, hmac ? strlen(hmac) : 0,
4349 passphrase, passphrase ?
4350 strlen(passphrase) : 0,
4353 /* Set CMODE notify type to network */
4354 silc_server_send_notify_cmode(server, SILC_PRIMARY_ROUTE(server),
4355 SILC_BROADCAST(server), channel,
4356 mode_mask, client->id, SILC_ID_CLIENT,
4357 cipher, hmac, passphrase, founder_key);
4359 /* Send command reply to sender */
4360 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4361 SILC_STATUS_OK, 0, ident, 2,
4362 2, tmp_id, tmp_len2,
4364 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4365 packet->data, packet->len, FALSE);
4367 silc_buffer_free(packet);
4368 silc_buffer_free(cidp);
4371 channel->mode = old_mask;
4373 silc_free(channel_id);
4374 silc_server_command_free(cmd);
4377 /* Server side of CUMODE command. Changes client's mode on a channel. */
4379 SILC_SERVER_CMD_FUNC(cumode)
4381 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4382 SilcServer server = cmd->server;
4383 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4384 SilcIDListData idata = (SilcIDListData)client;
4385 SilcChannelID *channel_id;
4386 SilcClientID *client_id;
4387 SilcChannelEntry channel;
4388 SilcClientEntry target_client;
4389 SilcChannelClientEntry chl;
4390 SilcBuffer packet, idp;
4391 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4392 SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4394 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4395 SilcPublicKey founder_key = NULL;
4396 unsigned char *fkey = NULL;
4397 SilcUInt32 fkey_len = 0;
4402 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4404 /* Get Channel ID */
4405 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4407 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4408 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4411 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
4413 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4414 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4418 /* Get channel entry */
4419 channel = silc_idlist_find_channel_by_id(server->local_list,
4422 channel = silc_idlist_find_channel_by_id(server->global_list,
4425 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4426 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4432 /* Check whether sender is on the channel */
4433 if (!silc_server_client_on_channel(client, channel, &chl)) {
4434 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4435 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4438 sender_mask = chl->mode;
4440 /* Get the target client's channel mode mask */
4441 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4443 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4444 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4448 SILC_GET32_MSB(target_mask, tmp_mask);
4450 /* Get target Client ID */
4451 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4453 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4454 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4457 client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
4459 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4460 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4464 /* Get target client's entry */
4465 target_client = silc_idlist_find_client_by_id(server->local_list,
4466 client_id, TRUE, NULL);
4467 if (!target_client) {
4468 target_client = silc_idlist_find_client_by_id(server->global_list,
4469 client_id, TRUE, NULL);
4472 if (target_client != client &&
4473 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4474 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4475 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4476 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
4480 /* Check whether target client is on the channel */
4481 if (target_client != client) {
4482 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4483 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4484 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL, 0);
4493 /* If the target client is founder, no one else can change their mode
4495 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4496 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4497 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
4502 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4503 if (target_client != client) {
4504 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4505 SILC_STATUS_ERR_NOT_YOU, 0);
4509 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4510 /* The client tries to claim the founder rights. */
4511 unsigned char *tmp_auth;
4512 SilcUInt32 tmp_auth_len;
4513 SilcChannelClientEntry chl2;
4514 SilcHashTableList htl;
4516 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4517 !channel->founder_key || !idata->public_key ||
4518 !silc_pkcs_public_key_compare(channel->founder_key,
4519 idata->public_key)) {
4520 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4521 SILC_STATUS_ERR_AUTH_FAILED, 0);
4525 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4527 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4528 SILC_STATUS_ERR_AUTH_FAILED, 0);
4532 /* Verify the authentication payload */
4533 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len, SILC_AUTH_PUBLIC_KEY,
4534 channel->founder_key, 0, server->sha1hash,
4535 client->id, SILC_ID_CLIENT)) {
4536 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4537 SILC_STATUS_ERR_AUTH_FAILED, 0);
4542 founder_key = channel->founder_key;
4543 fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
4545 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4546 SILC_STATUS_ERR_AUTH_FAILED, 0);
4550 /* There cannot be anyone else as founder on the channel now. This
4551 client is definitely the founder due to this authentication */
4552 silc_hash_table_list(channel->user_list, &htl);
4553 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
4554 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
4555 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4556 silc_server_force_cumode_change(server, NULL, channel, chl2,
4560 silc_hash_table_list_reset(&htl);
4562 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4565 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4566 if (target_client == client) {
4567 /* Remove channel founder rights from itself */
4568 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4571 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4572 SILC_STATUS_ERR_NOT_YOU, 0);
4578 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4579 /* Promote to operator */
4580 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4581 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4582 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4583 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4584 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
4589 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4593 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4594 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4595 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4596 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4597 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
4602 /* Demote to normal user */
4603 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4608 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4609 if (target_client != client) {
4610 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4611 SILC_STATUS_ERR_NOT_YOU, 0);
4615 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
4616 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4620 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4621 if (target_client != client) {
4622 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4623 SILC_STATUS_ERR_NOT_YOU, 0);
4627 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4632 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4633 if (target_client != client) {
4634 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4635 SILC_STATUS_ERR_NOT_YOU, 0);
4639 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)) {
4640 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4644 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4645 if (target_client != client) {
4646 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4647 SILC_STATUS_ERR_NOT_YOU, 0);
4651 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4656 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4657 if (target_client != client) {
4658 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4659 SILC_STATUS_ERR_NOT_YOU, 0);
4663 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)) {
4664 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4668 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4669 if (target_client != client) {
4670 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4671 SILC_STATUS_ERR_NOT_YOU, 0);
4675 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4680 if (target_mask & SILC_CHANNEL_UMODE_QUIET) {
4681 if (!(chl->mode & SILC_CHANNEL_UMODE_QUIET)) {
4682 if (client == target_client) {
4683 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4684 SILC_STATUS_ERR_PERM_DENIED, 0);
4687 chl->mode |= SILC_CHANNEL_UMODE_QUIET;
4691 if (chl->mode & SILC_CHANNEL_UMODE_QUIET) {
4692 if (client == target_client) {
4693 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4694 SILC_STATUS_ERR_PERM_DENIED, 0);
4697 chl->mode &= ~SILC_CHANNEL_UMODE_QUIET;
4702 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4703 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4705 /* Send notify to channel, notify only if mode was actually changed. */
4707 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4708 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
4709 idp->data, idp->len,
4714 /* Set CUMODE notify type to network */
4715 silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
4716 SILC_BROADCAST(server), channel,
4717 target_mask, client->id, SILC_ID_CLIENT,
4718 target_client->id, founder_key);
4721 /* Send command reply to sender */
4722 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4723 SILC_STATUS_OK, 0, ident, 3,
4725 3, tmp_ch_id, tmp_ch_len,
4726 4, tmp_id, tmp_len);
4727 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4728 packet->data, packet->len, FALSE);
4730 silc_buffer_free(packet);
4731 silc_free(channel_id);
4732 silc_free(client_id);
4733 silc_buffer_free(idp);
4737 silc_server_command_free(cmd);
4740 /* Server side of KICK command. Kicks client out of channel. */
4742 SILC_SERVER_CMD_FUNC(kick)
4744 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4745 SilcServer server = cmd->server;
4746 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4747 SilcClientEntry target_client;
4748 SilcChannelID *channel_id;
4749 SilcClientID *client_id;
4750 SilcChannelEntry channel;
4751 SilcChannelClientEntry chl;
4753 SilcUInt32 tmp_len, target_idp_len;
4754 unsigned char *tmp, *comment, *target_idp;
4759 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4761 /* Get Channel ID */
4762 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4764 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4765 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4768 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4770 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4771 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4775 /* Get channel entry */
4776 channel = silc_idlist_find_channel_by_id(server->local_list,
4779 channel = silc_idlist_find_channel_by_id(server->local_list,
4782 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4783 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4789 /* Check whether sender is on the channel */
4790 if (!silc_server_client_on_channel(client, channel, &chl)) {
4791 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4792 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4796 /* Check that the kicker is channel operator or channel founder */
4797 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
4798 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4799 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4800 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
4804 /* Get target Client ID */
4805 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4807 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4808 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4811 client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
4813 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4814 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4818 /* Get target client's entry */
4819 target_client = silc_idlist_find_client_by_id(server->local_list,
4820 client_id, TRUE, NULL);
4821 if (!target_client) {
4822 target_client = silc_idlist_find_client_by_id(server->global_list,
4823 client_id, TRUE, NULL);
4826 /* Check whether target client is on the channel */
4827 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4828 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4829 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL,
4834 /* Check that the target client is not channel founder. Channel founder
4835 cannot be kicked from the channel. */
4836 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4837 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4838 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
4845 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4849 /* Send command reply to sender */
4850 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4853 /* Send KICKED notify to local clients on the channel */
4854 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4855 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4856 SILC_NOTIFY_TYPE_KICKED, 3,
4857 target_idp, target_idp_len,
4858 comment, comment ? strlen(comment) : 0,
4859 idp->data, idp->len);
4860 silc_buffer_free(idp);
4862 /* Send KICKED notify to primary route */
4863 silc_server_send_notify_kicked(server, SILC_PRIMARY_ROUTE(server),
4864 SILC_BROADCAST(server), channel,
4865 target_client->id, client->id, comment);
4867 /* Remove the client from the channel. If the channel does not exist
4868 after removing the client then the client kicked itself off the channel
4869 and we don't have to send anything after that. */
4870 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4871 target_client, FALSE))
4874 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4875 /* Re-generate channel key */
4876 if (!silc_server_create_channel_key(server, channel, 0))
4879 /* Send the channel key to the channel. The key of course is not sent
4880 to the client who was kicked off the channel. */
4881 silc_server_send_channel_key(server, target_client->connection, channel,
4882 server->server_type == SILC_ROUTER ?
4883 FALSE : !server->standalone);
4887 silc_server_command_free(cmd);
4890 /* Server side of OPER command. Client uses this comand to obtain server
4891 operator privileges to this server/router. */
4893 SILC_SERVER_CMD_FUNC(oper)
4895 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4896 SilcServer server = cmd->server;
4897 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4898 unsigned char *username, *auth;
4900 SilcServerConfigAdmin *admin;
4901 SilcIDListData idata = (SilcIDListData)client;
4902 bool result = FALSE;
4903 SilcPublicKey cached_key;
4905 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
4908 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4910 /* Get the username */
4911 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4913 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4914 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4919 /* Get the admin configuration */
4920 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4921 username, client->nickname);
4923 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4924 username, client->nickname);
4926 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4927 SILC_STATUS_ERR_AUTH_FAILED,
4933 /* Get the authentication payload */
4934 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4936 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4937 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4942 /* Verify the authentication data. If both passphrase and public key
4943 is set then try both of them. */
4944 if (admin->passphrase)
4945 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4946 admin->passphrase, admin->passphrase_len,
4947 idata->hash, client->id, SILC_ID_CLIENT);
4948 if (!result && admin->publickeys) {
4949 cached_key = silc_server_get_public_key(server, admin->publickeys);
4952 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4953 cached_key, 0, idata->hash,
4954 client->id, SILC_ID_CLIENT);
4957 /* Authentication failed */
4958 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4959 SILC_STATUS_ERR_AUTH_FAILED,
4964 /* Client is now server operator */
4965 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4967 /* Update statistics */
4968 if (SILC_IS_LOCAL(client))
4969 server->stat.my_server_ops++;
4970 if (server->server_type == SILC_ROUTER)
4971 server->stat.server_ops++;
4973 /* Send UMODE change to primary router */
4974 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
4975 SILC_BROADCAST(server), client->id,
4978 /* Check if anyone is watching this nickname */
4979 if (server->server_type == SILC_ROUTER)
4980 silc_server_check_watcher_list(server, client, NULL,
4981 SILC_NOTIFY_TYPE_UMODE_CHANGE);
4983 /* Send reply to the sender */
4984 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4988 silc_server_command_free(cmd);
4991 SILC_TASK_CALLBACK(silc_server_command_detach_cb)
4993 QuitInternal q = (QuitInternal)context;
4994 SilcClientID *client_id = (SilcClientID *)q->sock;
4995 SilcClientEntry client;
4996 SilcSocketConnection sock;
4998 client = silc_idlist_find_client_by_id(q->server->local_list, client_id,
5000 if (client && client->connection) {
5001 sock = client->connection;
5003 /* If there is pending outgoing data for the client then purge it
5004 to the network before closing connection. */
5005 silc_server_packet_queue_purge(q->server, sock);
5007 /* Close the connection on our side */
5008 client->router = NULL;
5009 client->connection = NULL;
5010 sock->user_data = NULL;
5011 silc_server_close_connection(q->server, sock);
5014 silc_free(client_id);
5018 SILC_TASK_CALLBACK(silc_server_command_detach_timeout)
5020 QuitInternal q = (QuitInternal)context;
5021 SilcClientID *client_id = (SilcClientID *)q->sock;
5022 SilcClientEntry client;
5024 client = silc_idlist_find_client_by_id(q->server->local_list, client_id,
5026 if (client && client->mode & SILC_UMODE_DETACHED) {
5027 SILC_LOG_DEBUG(("Detach timeout"));
5028 silc_server_free_client_data(q->server, NULL, client, TRUE,
5032 silc_free(client_id);
5036 /* Server side of DETACH command. Detached the client from the network
5037 by closing the connection but preserving the session. */
5039 SILC_SERVER_CMD_FUNC(detach)
5041 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5042 SilcServer server = cmd->server;
5043 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5046 if (server->config->detach_disabled) {
5047 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
5048 SILC_STATUS_ERR_UNKNOWN_COMMAND, 0);
5052 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
5055 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
5057 /* Remove operator privileges, since the client may resume in some
5058 other server which to it does not have operator privileges. */
5059 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
5060 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
5062 /* Send the user mode notify to notify that client is detached */
5063 client->mode |= SILC_UMODE_DETACHED;
5064 client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
5065 client->last_command = 0;
5066 client->fast_command = 0;
5067 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
5068 SILC_BROADCAST(server), client->id,
5070 server->stat.my_detached++;
5072 /* Check if anyone is watching this nickname */
5073 if (server->server_type == SILC_ROUTER)
5074 silc_server_check_watcher_list(server, client, NULL,
5075 SILC_NOTIFY_TYPE_UMODE_CHANGE);
5077 q = silc_calloc(1, sizeof(*q));
5079 q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
5080 silc_schedule_task_add(server->schedule, 0, silc_server_command_detach_cb,
5081 q, 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
5083 if (server->config->detach_timeout) {
5084 q = silc_calloc(1, sizeof(*q));
5086 q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
5087 silc_schedule_task_add(server->schedule, 0,
5088 silc_server_command_detach_timeout,
5089 q, server->config->detach_timeout * 60,
5090 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
5093 /* Send reply to the sender */
5094 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
5098 silc_server_command_free(cmd);
5101 /* Server side of WATCH command. */
5103 SILC_SERVER_CMD_FUNC(watch)
5105 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5106 SilcServer server = cmd->server;
5107 char *add_nick, *del_nick;
5108 SilcUInt32 add_nick_len, del_nick_len, tmp_len;
5110 unsigned char hash[16], *tmp;
5111 SilcClientEntry client;
5112 SilcClientID *client_id = NULL;
5114 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WATCH, cmd, 1, 3);
5116 if (server->server_type == SILC_SERVER && !server->standalone) {
5117 if (!cmd->pending) {
5118 /* Send the command to router */
5120 SilcUInt16 old_ident;
5122 old_ident = silc_command_get_ident(cmd->payload);
5123 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5124 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5126 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5127 SILC_PACKET_COMMAND, cmd->packet->flags,
5128 tmpbuf->data, tmpbuf->len, TRUE);
5130 /* Reprocess this packet after received reply from router */
5131 silc_server_command_pending(server, SILC_COMMAND_WATCH,
5132 silc_command_get_ident(cmd->payload),
5133 silc_server_command_watch,
5134 silc_server_command_dup(cmd));
5135 cmd->pending = TRUE;
5136 silc_command_set_ident(cmd->payload, old_ident);
5137 silc_buffer_free(tmpbuf);
5138 } else if (context2) {
5139 /* Received reply from router, just send same data to the client. */
5140 SilcServerCommandReplyContext reply = context2;
5142 silc_command_get_status(reply->payload, &status, NULL);
5143 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, status,
5150 /* We are router and keep the watch list for local cell */
5152 /* Get the client ID */
5153 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5155 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5156 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5160 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
5162 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5163 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5168 /* Get the client entry which must be in local list */
5169 client = silc_idlist_find_client_by_id(server->local_list,
5170 client_id, TRUE, NULL);
5172 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5173 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5179 add_nick = silc_argument_get_arg_type(cmd->args, 2, &add_nick_len);
5180 del_nick = silc_argument_get_arg_type(cmd->args, 3, &del_nick_len);
5181 if (!add_nick && !del_nick) {
5182 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5183 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5188 if (add_nick && add_nick_len > 128)
5189 add_nick[128] = '\0';
5190 if (del_nick && del_nick_len > 128)
5191 del_nick[128] = '\0';
5193 memset(nick, 0, sizeof(nick));
5195 /* Add new nickname to be watched in our cell */
5197 if (silc_server_name_bad_chars(add_nick, strlen(add_nick)) == TRUE) {
5198 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5199 SILC_STATUS_ERR_BAD_NICKNAME, 0);
5203 /* Hash the nick, we have the hash saved, not nicks because we can
5204 do one to one mapping to the nick from Client ID hash this way. */
5205 silc_to_lower(add_nick, nick, sizeof(nick) - 1);
5206 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
5208 /* Check whether this client is already watching this nickname */
5209 if (silc_hash_table_find_by_context(server->watcher_list, hash,
5211 /* Nickname is alredy being watched for this client */
5212 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5213 SILC_STATUS_ERR_NICKNAME_IN_USE,
5218 /* Get the nickname from the watcher list and use the same key in
5219 new entries as well. If key doesn't exist then create it. */
5220 if (!silc_hash_table_find(server->watcher_list, hash, (void **)&tmp, NULL))
5221 tmp = silc_memdup(hash, CLIENTID_HASH_LEN);
5223 /* Add the client to the watcher list with the specified nickname hash. */
5224 silc_hash_table_add(server->watcher_list, tmp, client);
5227 /* Delete nickname from watch list */
5229 if (silc_server_name_bad_chars(del_nick, strlen(del_nick)) == TRUE) {
5230 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5231 SILC_STATUS_ERR_BAD_NICKNAME, 0);
5235 /* Hash the nick, we have the hash saved, not nicks because we can
5236 do one to one mapping to the nick from Client ID hash this way. */
5237 silc_to_lower(del_nick, nick, sizeof(nick) - 1);
5238 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
5240 /* Check that this client is watching for this nickname */
5241 if (!silc_hash_table_find_by_context(server->watcher_list, hash,
5242 client, (void **)&tmp)) {
5243 /* Nickname is alredy being watched for this client */
5244 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5245 SILC_STATUS_ERR_NO_SUCH_NICK, 0);
5249 /* Delete the nickname from the watcher list. */
5250 silc_hash_table_del_by_context(server->watcher_list, hash, client);
5252 /* Now check whether there still exists entries with this key, if not
5253 then free the key to not leak memory. */
5254 if (!silc_hash_table_find(server->watcher_list, hash, NULL, NULL))
5258 /* Distribute the watch list to backup routers too */
5259 if (server->backup) {
5261 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5262 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5263 silc_server_backup_send(server, NULL, SILC_PACKET_COMMAND,
5264 cmd->packet->flags, tmpbuf->data, tmpbuf->len,
5266 silc_buffer_free(tmpbuf);
5269 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5273 silc_free(client_id);
5274 silc_server_command_free(cmd);
5277 /* Server side of SILCOPER command. Client uses this comand to obtain router
5278 operator privileges to this router. */
5280 SILC_SERVER_CMD_FUNC(silcoper)
5282 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5283 SilcServer server = cmd->server;
5284 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5285 unsigned char *username, *auth;
5287 SilcServerConfigAdmin *admin;
5288 SilcIDListData idata = (SilcIDListData)client;
5289 bool result = FALSE;
5290 SilcPublicKey cached_key;
5292 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
5295 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
5297 if (server->server_type != SILC_ROUTER) {
5298 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5299 SILC_STATUS_ERR_AUTH_FAILED, 0);
5303 /* Get the username */
5304 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5306 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5307 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5312 /* Get the admin configuration */
5313 admin = silc_server_config_find_admin(server, cmd->sock->ip,
5314 username, client->nickname);
5316 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
5317 username, client->nickname);
5319 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5320 SILC_STATUS_ERR_AUTH_FAILED, 0);
5325 /* Get the authentication payload */
5326 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5328 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5329 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5334 /* Verify the authentication data. If both passphrase and public key
5335 is set then try both of them. */
5336 if (admin->passphrase)
5337 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
5338 admin->passphrase, admin->passphrase_len,
5339 idata->hash, client->id, SILC_ID_CLIENT);
5340 if (!result && admin->publickeys) {
5341 cached_key = silc_server_get_public_key(server, admin->publickeys);
5344 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
5345 cached_key, 0, idata->hash,
5346 client->id, SILC_ID_CLIENT);
5349 /* Authentication failed */
5350 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
5351 SILC_STATUS_ERR_AUTH_FAILED, 0);
5355 /* Client is now router operator */
5356 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
5358 /* Update statistics */
5359 if (SILC_IS_LOCAL(client))
5360 server->stat.my_router_ops++;
5361 if (server->server_type == SILC_ROUTER)
5362 server->stat.router_ops++;
5364 /* Send UMODE change to primary router */
5365 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
5366 SILC_BROADCAST(server), client->id,
5369 /* Check if anyone is watching this nickname */
5370 if (server->server_type == SILC_ROUTER)
5371 silc_server_check_watcher_list(server, client, NULL,
5372 SILC_NOTIFY_TYPE_UMODE_CHANGE);
5374 /* Send reply to the sender */
5375 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5379 silc_server_command_free(cmd);
5382 /* Server side of command BAN. This is used to manage the ban list of the
5383 channel. To add clients and remove clients from the ban list. */
5385 SILC_SERVER_CMD_FUNC(ban)
5387 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5388 SilcServer server = cmd->server;
5389 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5391 SilcChannelEntry channel;
5392 SilcChannelClientEntry chl;
5393 SilcChannelID *channel_id = NULL;
5394 unsigned char *id, *add, *del;
5395 SilcUInt32 id_len, tmp_len;
5396 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5398 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
5401 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
5403 /* Get Channel ID */
5404 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
5406 channel_id = silc_id_payload_parse_id(id, id_len, NULL);
5408 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5409 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5414 /* Get channel entry. The server must know about the channel since the
5415 client is expected to be on the channel. */
5416 channel = silc_idlist_find_channel_by_id(server->local_list,
5419 channel = silc_idlist_find_channel_by_id(server->global_list,
5422 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5423 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5429 /* Check whether this client is on the channel */
5430 if (!silc_server_client_on_channel(client, channel, &chl)) {
5431 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5432 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5436 /* The client must be at least channel operator. */
5437 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
5438 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5439 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
5443 /* Get the new ban and add it to the ban list */
5444 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5446 if (!channel->ban_list)
5447 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
5449 channel->ban_list = silc_realloc(channel->ban_list,
5450 sizeof(*channel->ban_list) *
5452 strlen(channel->ban_list) + 2));
5453 if (add[tmp_len - 1] == ',')
5454 add[tmp_len - 1] = '\0';
5456 strncat(channel->ban_list, add, tmp_len);
5457 strncat(channel->ban_list, ",", 1);
5460 /* Get the ban to be removed and remove it from the list */
5461 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
5462 if (del && channel->ban_list) {
5463 char *start, *end, *n;
5465 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
5466 silc_free(channel->ban_list);
5467 channel->ban_list = NULL;
5469 start = strstr(channel->ban_list, del);
5470 if (start && strlen(start) >= tmp_len) {
5471 end = start + tmp_len;
5472 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
5473 strncat(n, channel->ban_list, start - channel->ban_list);
5474 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
5476 silc_free(channel->ban_list);
5477 channel->ban_list = n;
5482 /* Send the BAN notify type to our primary router. */
5484 silc_server_send_notify_ban(server, SILC_PRIMARY_ROUTE(server),
5485 SILC_BROADCAST(server), channel, add, del);
5487 /* Send the reply back to the client */
5489 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
5490 SILC_STATUS_OK, 0, ident, 2,
5492 3, channel->ban_list,
5494 strlen(channel->ban_list) -1 : 0);
5495 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5496 packet->data, packet->len, FALSE);
5498 silc_buffer_free(packet);
5501 silc_free(channel_id);
5502 silc_server_command_free(cmd);
5505 /* Server side command of LEAVE. Removes client from a channel. */
5507 SILC_SERVER_CMD_FUNC(leave)
5509 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5510 SilcServer server = cmd->server;
5511 SilcSocketConnection sock = cmd->sock;
5512 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
5513 SilcChannelID *id = NULL;
5514 SilcChannelEntry channel;
5518 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !id_entry)
5521 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
5523 /* Get Channel ID */
5524 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
5526 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5527 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5530 id = silc_id_payload_parse_id(tmp, len, NULL);
5532 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5533 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5537 /* Get channel entry */
5538 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5540 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5542 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5543 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5549 /* Check whether this client is on the channel */
5550 if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
5551 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5552 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5556 /* Notify routers that they should remove this client from their list
5557 of clients on the channel. Send LEAVE notify type. */
5558 silc_server_send_notify_leave(server, SILC_PRIMARY_ROUTE(server),
5559 SILC_BROADCAST(server), channel, id_entry->id);
5561 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
5562 SILC_STATUS_OK, 0, 2, tmp, len);
5564 /* Remove client from channel */
5565 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5567 /* If the channel does not exist anymore we won't send anything */
5570 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5571 /* Re-generate channel key */
5572 if (!silc_server_create_channel_key(server, channel, 0))
5575 /* Send the channel key */
5576 silc_server_send_channel_key(server, NULL, channel,
5577 server->server_type == SILC_ROUTER ?
5578 FALSE : !server->standalone);
5583 silc_server_command_free(cmd);
5586 /* Server side of command USERS. Resolves clients and their USERS currently
5587 joined on the requested channel. The list of Client ID's and their modes
5588 on the channel is sent back. */
5590 SILC_SERVER_CMD_FUNC(users)
5592 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5593 SilcServer server = cmd->server;
5594 SilcChannelEntry channel;
5595 SilcChannelID *id = NULL;
5596 SilcBuffer packet, idp;
5597 unsigned char *channel_id;
5598 SilcUInt32 channel_id_len;
5599 SilcBuffer client_id_list;
5600 SilcBuffer client_mode_list;
5601 unsigned char lc[4];
5602 SilcUInt32 list_count = 0;
5603 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5606 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5608 /* Get Channel ID */
5609 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5611 /* Get channel name */
5612 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5614 if (!channel_id && !channel_name) {
5615 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5616 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5621 id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
5623 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5624 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5629 /* If we are server and we don't know about this channel we will send
5630 the command to our router. If we know about the channel then we also
5631 have the list of users already. */
5633 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5635 channel = silc_idlist_find_channel_by_name(server->local_list,
5636 channel_name, NULL);
5638 if (!channel || (!server->standalone && (channel->disabled ||
5639 !channel->users_resolved))) {
5640 if (server->server_type != SILC_ROUTER && !server->standalone &&
5644 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5645 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5647 /* Send USERS command */
5648 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5649 SILC_PACKET_COMMAND, cmd->packet->flags,
5650 tmpbuf->data, tmpbuf->len, TRUE);
5652 /* Reprocess this packet after received reply */
5653 silc_server_command_pending(server, SILC_COMMAND_USERS,
5654 silc_command_get_ident(cmd->payload),
5655 silc_server_command_users,
5656 silc_server_command_dup(cmd));
5657 cmd->pending = TRUE;
5658 silc_command_set_ident(cmd->payload, ident);
5659 silc_buffer_free(tmpbuf);
5664 /* Check the global list as well. */
5666 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5668 channel = silc_idlist_find_channel_by_name(server->global_list,
5669 channel_name, NULL);
5671 /* Channel really does not exist */
5672 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5673 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5679 /* If the channel is private or secret do not send anything, unless the
5680 user requesting this command is on the channel or is server */
5681 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5682 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5683 && !silc_server_client_on_channel(cmd->sock->user_data, channel,
5685 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5686 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5692 /* Get the users list */
5693 if (!silc_server_get_users_on_channel(server, channel, &client_id_list,
5694 &client_mode_list, &list_count)) {
5696 client_id_list = NULL;
5697 client_mode_list = NULL;
5701 SILC_PUT32_MSB(list_count, lc);
5704 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5705 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5706 SILC_STATUS_OK, 0, ident, 4,
5707 2, idp->data, idp->len,
5710 client_id_list->data : NULL,
5712 client_id_list->len : 0,
5713 5, client_mode_list ?
5714 client_mode_list->data : NULL,
5716 client_mode_list->len : 0);
5717 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5718 packet->data, packet->len, FALSE);
5720 silc_buffer_free(idp);
5721 silc_buffer_free(packet);
5723 silc_buffer_free(client_id_list);
5724 if (client_mode_list)
5725 silc_buffer_free(client_mode_list);
5729 silc_server_command_free(cmd);
5732 /* Server side of command GETKEY. This fetches the client's public key
5733 from the server where to the client is connected. */
5735 SILC_SERVER_CMD_FUNC(getkey)
5737 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5738 SilcServer server = cmd->server;
5740 SilcClientEntry client;
5741 SilcServerEntry server_entry;
5742 SilcClientID *client_id = NULL;
5743 SilcServerID *server_id = NULL;
5744 SilcIDPayload idp = NULL;
5745 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5746 unsigned char *tmp, *pkdata;
5747 SilcUInt32 tmp_len, pklen;
5748 SilcBuffer pk = NULL;
5750 SilcPublicKey public_key;
5752 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5754 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5755 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5759 idp = silc_id_payload_parse(tmp, tmp_len);
5761 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5762 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5767 id_type = silc_id_payload_get_type(idp);
5768 if (id_type == SILC_ID_CLIENT) {
5769 client_id = silc_id_payload_get_id(idp);
5771 /* If the client is not found from local list there is no chance it
5772 would be locally connected client so send the command further. */
5773 client = silc_idlist_find_client_by_id(server->local_list,
5774 client_id, TRUE, NULL);
5776 client = silc_idlist_find_client_by_id(server->global_list,
5777 client_id, TRUE, NULL);
5779 if ((!client && !cmd->pending && !server->standalone) ||
5780 (client && !client->connection && !cmd->pending &&
5781 !(client->mode & SILC_UMODE_DETACHED)) ||
5782 (client && !client->data.public_key && !cmd->pending)) {
5784 SilcUInt16 old_ident;
5785 SilcSocketConnection dest_sock;
5787 dest_sock = silc_server_get_client_route(server, NULL, 0,
5788 client_id, NULL, NULL);
5792 old_ident = silc_command_get_ident(cmd->payload);
5793 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5794 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5796 silc_server_packet_send(server, dest_sock,
5797 SILC_PACKET_COMMAND, cmd->packet->flags,
5798 tmpbuf->data, tmpbuf->len, TRUE);
5800 /* Reprocess this packet after received reply from router */
5801 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5802 silc_command_get_ident(cmd->payload),
5803 silc_server_command_getkey,
5804 silc_server_command_dup(cmd));
5805 cmd->pending = TRUE;
5806 silc_command_set_ident(cmd->payload, old_ident);
5807 silc_buffer_free(tmpbuf);
5812 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5813 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5818 /* The client is locally connected, just get the public key and
5819 send it back. If they key does not exist then do not send it,
5820 send just OK reply */
5821 public_key = client->data.public_key;
5826 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5827 pk = silc_buffer_alloc(4 + tmp_len);
5828 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5829 silc_buffer_format(pk,
5830 SILC_STR_UI_SHORT(tmp_len),
5831 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5832 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5838 } else if (id_type == SILC_ID_SERVER) {
5839 server_id = silc_id_payload_get_id(idp);
5841 /* If the server is not found from local list there is no chance it
5842 would be locally connected server so send the command further. */
5843 server_entry = silc_idlist_find_server_by_id(server->local_list,
5844 server_id, TRUE, NULL);
5846 server_entry = silc_idlist_find_server_by_id(server->global_list,
5847 server_id, TRUE, NULL);
5849 if (server_entry != server->id_entry &&
5850 ((!server_entry && !cmd->pending && !server->standalone) ||
5851 (server_entry && !server_entry->connection && !cmd->pending &&
5852 !server->standalone) ||
5853 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5854 !server->standalone))) {
5856 SilcUInt16 old_ident;
5858 old_ident = silc_command_get_ident(cmd->payload);
5859 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5860 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5862 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5863 SILC_PACKET_COMMAND, cmd->packet->flags,
5864 tmpbuf->data, tmpbuf->len, TRUE);
5866 /* Reprocess this packet after received reply from router */
5867 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5868 silc_command_get_ident(cmd->payload),
5869 silc_server_command_getkey,
5870 silc_server_command_dup(cmd));
5871 cmd->pending = TRUE;
5872 silc_command_set_ident(cmd->payload, old_ident);
5873 silc_buffer_free(tmpbuf);
5877 if (!server_entry) {
5878 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5879 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
5884 /* If they key does not exist then do not send it, send just OK reply */
5885 public_key = (!server_entry->data.public_key ?
5886 (server_entry == server->id_entry ? server->public_key :
5887 NULL) : server_entry->data.public_key);
5892 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5893 pk = silc_buffer_alloc(4 + tmp_len);
5894 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5895 silc_buffer_format(pk,
5896 SILC_STR_UI_SHORT(tmp_len),
5897 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5898 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5908 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5909 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5910 SILC_STATUS_OK, 0, ident,
5914 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5915 packet->data, packet->len, FALSE);
5916 silc_buffer_free(packet);
5919 silc_buffer_free(pk);
5923 silc_id_payload_free(idp);
5924 silc_free(client_id);
5925 silc_free(server_id);
5926 silc_server_command_free(cmd);
5930 /* Private range commands, specific to this implementation */
5932 /* Server side command of CONNECT. Connects us to the specified remote
5933 server or router. */
5935 SILC_SERVER_CMD_FUNC(connect)
5937 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5938 SilcServer server = cmd->server;
5939 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5940 unsigned char *tmp, *host;
5942 SilcUInt32 port = SILC_PORT;
5944 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
5947 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
5949 /* Check whether client has the permissions. */
5950 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5951 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5952 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5953 SILC_STATUS_ERR_NO_SERVER_PRIV, 0);
5957 if (server->server_type == SILC_ROUTER &&
5958 client->mode & SILC_UMODE_SERVER_OPERATOR) {
5959 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5960 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
5964 /* Get the remote server */
5965 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5967 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5968 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5974 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5976 SILC_GET32_MSB(port, tmp);
5978 /* Create the connection. It is done with timeout and is async. */
5979 silc_server_create_connection(server, host, port);
5981 /* Send reply to the sender */
5982 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5986 silc_server_command_free(cmd);
5989 /* Server side command of CLOSE. Closes connection to a specified server. */
5991 SILC_SERVER_CMD_FUNC(close)
5993 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5994 SilcServer server = cmd->server;
5995 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5996 SilcServerEntry server_entry;
5997 SilcSocketConnection sock;
6000 unsigned char *name;
6001 SilcUInt32 port = SILC_PORT;
6003 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
6006 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
6008 /* Check whether client has the permissions. */
6009 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
6010 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
6011 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
6012 SILC_STATUS_ERR_NO_SERVER_PRIV,
6017 /* Get the remote server */
6018 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
6020 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
6021 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
6027 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
6029 SILC_GET32_MSB(port, tmp);
6031 server_entry = silc_idlist_find_server_by_conn(server->local_list,
6032 name, port, FALSE, NULL);
6034 server_entry = silc_idlist_find_server_by_conn(server->global_list,
6035 name, port, FALSE, NULL);
6036 if (!server_entry) {
6037 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
6038 SILC_STATUS_ERR_NO_SERVER_ID, 0);
6042 if (server_entry == server->id_entry) {
6043 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
6044 SILC_STATUS_ERR_NO_SERVER_ID, 0);
6048 /* Send reply to the sender */
6049 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
6052 /* Close the connection to the server */
6053 sock = (SilcSocketConnection)server_entry->connection;
6055 /* If we shutdown primary router connection manually then don't trigger
6056 any reconnect or backup router connections, by setting the router
6058 if (server->router == server_entry) {
6059 server->id_entry->router = NULL;
6060 server->router = NULL;
6061 server->standalone = TRUE;
6063 silc_server_free_sock_user_data(server, sock, NULL);
6064 silc_server_close_connection(server, sock);
6067 silc_server_command_free(cmd);
6070 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
6071 active connections. */
6073 SILC_SERVER_CMD_FUNC(shutdown)
6075 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
6076 SilcServer server = cmd->server;
6077 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
6079 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
6082 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
6084 /* Check whether client has the permission. */
6085 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
6086 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
6087 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
6088 SILC_STATUS_ERR_NO_SERVER_PRIV,
6093 /* Send reply to the sender */
6094 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
6097 /* Then, gracefully, or not, bring the server down. */
6098 silc_server_stop(server);
6102 silc_server_command_free(cmd);