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 = silc_calloc(1, sizeof(*timeout));
243 if (client->last_command && (time(NULL) - client->last_command) < 2) {
244 client->fast_command++;
247 if (client->fast_command - 2 <= 0)
248 client->fast_command = 0;
250 client->fast_command -= 2;
254 if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
255 (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
256 silc_schedule_task_add(server->schedule, sock->sock,
257 silc_server_command_process_timeout, timeout,
258 (client->fast_command < 3 ? 0 :
259 2 - (time(NULL) - client->last_command)),
260 (client->fast_command < 3 ? 200000 : 0),
261 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
263 silc_schedule_task_add(server->schedule, sock->sock,
264 silc_server_command_process_timeout, timeout,
265 0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
269 /* Execute for server */
271 if (!(cmd->flags & SILC_CF_REG)) {
272 SILC_LOG_DEBUG(("Calling %s command", silc_get_command_name(cmd->cmd)));
274 } else if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) {
275 SILC_LOG_DEBUG(("Calling %s command", silc_get_command_name(cmd->cmd)));
278 SILC_LOG_DEBUG(("Server is not registered"));
279 silc_server_command_free(ctx);
283 /* Allocate Command Context */
285 SilcServerCommandContext silc_server_command_alloc()
287 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
292 /* Free's the command context allocated before executing the command */
294 void silc_server_command_free(SilcServerCommandContext ctx)
297 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
299 if (ctx->users < 1) {
301 silc_command_payload_free(ctx->payload);
303 silc_packet_context_free(ctx->packet);
305 silc_socket_free(ctx->sock); /* Decrease reference counter */
310 /* Duplicate Command Context by adding reference counter. The context won't
311 be free'd untill it hits zero. */
313 SilcServerCommandContext
314 silc_server_command_dup(SilcServerCommandContext ctx)
317 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
322 /* Add new pending command to be executed when reply to a command has been
323 received. The `reply_cmd' is the command that will call the `callback'
324 with `context' when reply has been received. It can be SILC_COMMAND_NONE
325 to match any command with the `ident'. If `ident' is non-zero
326 the `callback' will be executed when received reply with command
327 identifier `ident'. If there already exists pending command for the
328 specified command, ident, callback and context this function has no
331 bool silc_server_command_pending(SilcServer server,
332 SilcCommand reply_cmd,
334 SilcCommandCb callback,
337 SilcServerCommandPending *reply;
339 /* Check whether identical pending already exists for same command,
340 ident, callback and callback context. If it does then it would be
341 error to register it again. */
342 silc_dlist_start(server->pending_commands);
343 while ((reply = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
344 if (reply->reply_cmd == reply_cmd && reply->ident == ident &&
345 reply->callback == callback && reply->context == context)
349 reply = silc_calloc(1, sizeof(*reply));
350 reply->reply_cmd = reply_cmd;
351 reply->ident = ident;
352 reply->context = context;
353 reply->callback = callback;
354 silc_dlist_add(server->pending_commands, reply);
359 /* Deletes pending command by reply command type. */
361 void silc_server_command_pending_del(SilcServer server,
362 SilcCommand reply_cmd,
365 SilcServerCommandPending *r;
367 silc_dlist_start(server->pending_commands);
368 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
369 if (r->reply_cmd == reply_cmd && r->ident == ident) {
370 silc_dlist_del(server->pending_commands, r);
377 /* Checks for pending commands and marks callbacks to be called from
378 the command reply function. Returns TRUE if there were pending command. */
380 SilcServerCommandPendingCallbacks
381 silc_server_command_pending_check(SilcServer server,
382 SilcServerCommandReplyContext ctx,
385 SilcUInt32 *callbacks_count)
387 SilcServerCommandPending *r;
388 SilcServerCommandPendingCallbacks callbacks = NULL;
391 silc_dlist_start(server->pending_commands);
392 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
393 if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE)
394 && r->ident == ident) {
395 callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
396 callbacks[i].context = r->context;
397 callbacks[i].callback = r->callback;
403 *callbacks_count = i;
407 /* Sends simple status message as command reply packet */
410 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
417 SILC_LOG_DEBUG(("Sending command status %d", status));
420 silc_command_reply_payload_encode_va(command, status, error,
421 silc_command_get_ident(cmd->payload),
423 silc_server_packet_send(cmd->server, cmd->sock,
424 SILC_PACKET_COMMAND_REPLY, 0,
425 buffer->data, buffer->len, FALSE);
426 silc_buffer_free(buffer);
429 /* Sends command status reply with one extra argument. The argument
430 type must be sent as argument. */
433 silc_server_command_send_status_data(SilcServerCommandContext cmd,
438 const unsigned char *arg,
443 SILC_LOG_DEBUG(("Sending command status %d", status));
446 silc_command_reply_payload_encode_va(command, status, 0,
447 silc_command_get_ident(cmd->payload),
448 1, arg_type, arg, arg_len);
449 silc_server_packet_send(cmd->server, cmd->sock,
450 SILC_PACKET_COMMAND_REPLY, 0,
451 buffer->data, buffer->len, FALSE);
452 silc_buffer_free(buffer);
455 /* This function can be called to check whether in the command reply
456 an error occurred. This function has no effect if this is called
457 when the command function was not called as pending command callback.
458 This returns TRUE if error had occurred. */
461 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
462 SilcServerCommandReplyContext cmdr,
465 if (!cmd->pending || !cmdr)
468 if (!silc_command_get_status(cmdr->payload, NULL, NULL)) {
471 /* Send the same command reply payload */
472 silc_command_set_ident(cmdr->payload,
473 silc_command_get_ident(cmd->payload));
474 buffer = silc_command_payload_encode_payload(cmdr->payload);
475 silc_server_packet_send(cmd->server, cmd->sock,
476 SILC_PACKET_COMMAND_REPLY, 0,
477 buffer->data, buffer->len, FALSE);
478 silc_buffer_free(buffer);
485 /******************************************************************************
489 ******************************************************************************/
498 #define ADD_ERROR(errptr, errptr_count, _id, _id_type, _index, _status) \
500 errptr = silc_realloc(errptr, sizeof(*errptr) * (errptr_count + 1)); \
503 errptr[errptr_count].id = _id; \
504 errptr[errptr_count].id_type = _id_type; \
505 errptr[errptr_count].index = _index; \
506 errptr[errptr_count].error = _status; \
511 silc_server_command_whois_parse(SilcServerCommandContext cmd,
512 SilcClientID ***client_id,
513 SilcUInt32 *client_id_count,
517 ResolveError *error_client,
518 SilcUInt32 *error_client_count)
522 SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
526 /* If client ID is in the command it must be used instead of nickname */
527 tmp = silc_argument_get_arg_type(cmd->args, 4, &len);
529 /* No ID, get the nickname@server string and parse it. */
530 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
532 silc_parse_userfqdn(tmp, nickname, server_name);
534 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
535 SILC_STATUS_ERR_BAD_NICKNAME, 0);
539 /* Command includes ID, we must use that. Take all ID's from the
541 for (k = 0, i = 0; i < argc; i++) {
542 tmp = silc_argument_get_arg_type(cmd->args, i + 4, &len);
545 id = silc_id_payload_parse_id(tmp, len, NULL);
547 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
548 (*client_id_count + 1));
549 (*client_id)[k] = id;
550 (*client_id_count)++;
553 ADD_ERROR((*error_client), (*error_client_count), NULL, 0, i + 4,
554 SILC_STATUS_ERR_BAD_CLIENT_ID);
559 /* Get the max count of reply messages allowed */
560 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
562 SILC_GET32_MSB(*count, tmp);
569 /* Resolve context used by both WHOIS and IDENTIFY commands */
571 SilcServerEntry router;
573 unsigned char **res_argv;
574 SilcUInt32 *res_argv_lens;
575 SilcUInt32 *res_argv_types;
577 } *SilcServerResolveContext;
580 silc_server_command_whois_check(SilcServerCommandContext cmd,
581 SilcClientEntry *clients,
582 SilcUInt32 clients_count)
584 SilcServer server = cmd->server;
585 SilcClientEntry entry;
586 SilcServerResolveContext resolve = NULL, r = NULL;
587 SilcUInt32 resolve_count = 0;
591 SILC_LOG_DEBUG(("Start"));
593 for (i = 0; i < clients_count; i++) {
598 if ((entry->nickname && entry->username && entry->userinfo) ||
599 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
603 /* If we are normal server, and we've not resolved this client from
604 router and it is global client, we'll check whether it is on some
605 channel. If not then we cannot be sure about its validity, and
606 we'll resolve it from router. */
607 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
608 entry->connection || silc_hash_table_count(entry->channels))
612 /* We need to resolve this entry since it is not complete */
614 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
615 /* The entry is being resolved (and we are not the resolver) so attach
616 to the command reply and we're done with this one. */
617 silc_server_command_pending(server, SILC_COMMAND_NONE,
618 entry->resolve_cmd_ident,
619 silc_server_command_whois,
620 silc_server_command_dup(cmd));
623 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
624 /* We've resolved this and it still is not ready. We'll return
625 and are that this will be handled again after it is resolved. */
626 for (i = 0; i < resolve_count; i++) {
627 for (k = 0; k < r->res_argc; k++)
628 silc_free(r->res_argv[k]);
629 silc_free(r->res_argv);
630 silc_free(r->res_argv_lens);
631 silc_free(r->res_argv_types);
636 /* We'll resolve this client */
640 for (k = 0; k < resolve_count; k++) {
641 if (resolve[k].router == entry->router) {
648 resolve = silc_realloc(resolve, sizeof(*resolve) *
649 (resolve_count + 1));
650 r = &resolve[resolve_count];
651 memset(r, 0, sizeof(*r));
652 r->router = entry->router;
653 r->ident = ++server->cmd_ident;
657 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
659 r->res_argv_lens = silc_realloc(r->res_argv_lens,
660 sizeof(*r->res_argv_lens) *
662 r->res_argv_types = silc_realloc(r->res_argv_types,
663 sizeof(*r->res_argv_types) *
665 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
666 r->res_argv[r->res_argc] = silc_calloc(idp->len,
667 sizeof(**r->res_argv));
668 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
669 r->res_argv_lens[r->res_argc] = idp->len;
670 r->res_argv_types[r->res_argc] = r->res_argc + 4;
672 silc_buffer_free(idp);
674 entry->resolve_cmd_ident = r->ident;
675 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
676 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
681 /* Do the resolving */
682 for (i = 0; i < resolve_count; i++) {
687 /* Send WHOIS request. We send WHOIS since we're doing the requesting
688 now anyway so make it a good one. */
689 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
690 r->res_argc, r->res_argv,
694 silc_server_packet_send(server, r->router->connection,
695 SILC_PACKET_COMMAND, cmd->packet->flags,
696 res_cmd->data, res_cmd->len, FALSE);
698 /* Reprocess this packet after received reply */
699 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
701 silc_server_command_whois,
702 silc_server_command_dup(cmd));
705 silc_buffer_free(res_cmd);
706 for (k = 0; k < r->res_argc; k++)
707 silc_free(r->res_argv[k]);
708 silc_free(r->res_argv);
709 silc_free(r->res_argv_lens);
710 silc_free(r->res_argv_types);
719 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
720 SilcClientEntry *clients,
721 SilcUInt32 clients_count,
723 SilcUInt32 errors_count,
724 int count, const char *nickname,
725 SilcClientID **client_ids)
727 SilcServer server = cmd->server;
729 int i, k, valid_count = clients_count;
731 SilcBuffer packet, idp, channels, umode_list = NULL;
732 SilcClientEntry entry;
734 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
735 char nh[256], uh[256];
736 unsigned char idle[4], mode[4];
737 unsigned char *fingerprint;
738 SilcSocketConnection hsock;
741 /* Process only valid clients and ignore those that are not registered.
742 This is checked with nickname only because when resolved client IDs
743 we check that they are registered earlier. */
745 for (i = 0; i < clients_count; i++)
746 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
752 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
753 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
754 3, nickname, strlen(nickname));
759 /* Start processing found clients. */
760 status = SILC_STATUS_OK;
762 status = SILC_STATUS_LIST_START;
764 for (i = 0, k = 0; i < clients_count; i++) {
770 status = SILC_STATUS_LIST_ITEM;
771 if (valid_count > 1 && k == valid_count - 1 && !errors_count)
772 status = SILC_STATUS_LIST_END;
773 if (count && k - 1 == count)
774 status = SILC_STATUS_LIST_END;
776 /* Send WHOIS reply */
777 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
778 tmp = silc_argument_get_first_arg(cmd->args, NULL);
780 memset(uh, 0, sizeof(uh));
781 memset(nh, 0, sizeof(nh));
782 memset(idle, 0, sizeof(idle));
784 strncat(nh, entry->nickname, strlen(entry->nickname));
785 if (!strchr(entry->nickname, '@')) {
787 if (entry->servername) {
788 strncat(nh, entry->servername, strlen(entry->servername));
790 len = entry->router ? strlen(entry->router->server_name) :
791 strlen(server->server_name);
792 strncat(nh, entry->router ? entry->router->server_name :
793 server->server_name, len);
797 strncat(uh, entry->username, strlen(entry->username));
798 if (!strchr(entry->username, '@') && entry->connection) {
800 hsock = (SilcSocketConnection)entry->connection;
801 len = strlen(hsock->hostname);
802 strncat(uh, hsock->hostname, len);
805 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
806 channels = silc_server_get_client_channel_list(server, entry, FALSE,
809 channels = silc_server_get_client_channel_list(server, entry, TRUE,
812 if (entry->data.fingerprint[0] != 0 && entry->data.fingerprint[1] != 0)
813 fingerprint = entry->data.fingerprint;
817 SILC_PUT32_MSB(entry->mode, mode);
818 if (entry->connection)
819 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
822 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
824 2, idp->data, idp->len,
828 strlen(entry->userinfo),
829 6, channels ? channels->data : NULL,
830 channels ? channels->len : 0,
834 fingerprint ? 20 : 0,
835 10, umode_list ? umode_list->data :
836 NULL, umode_list ? umode_list->len :
839 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
840 0, packet->data, packet->len, FALSE);
842 silc_buffer_free(packet);
843 silc_buffer_free(idp);
845 silc_buffer_free(channels);
847 silc_buffer_free(umode_list);
851 if (status == SILC_STATUS_LIST_END)
856 /* Send error replies */
857 if (status == SILC_STATUS_OK && errors_count > 1)
858 status = SILC_STATUS_LIST_START;
861 for (i = 0, k = 0; i < errors_count; i++) {
863 idp = silc_id_payload_encode(errors[i].id, SILC_ID_CLIENT);
867 tmp = silc_argument_get_arg_type(cmd->args, errors[i].index, &len);
871 status = SILC_STATUS_LIST_ITEM;
872 if (errors_count > 1 && k == errors_count - 1)
873 status = SILC_STATUS_LIST_END;
874 if (count && k - 1 == count)
875 status = SILC_STATUS_LIST_END;
878 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
879 (status == SILC_STATUS_OK ?
880 errors[i].error : status),
881 (status == SILC_STATUS_OK ?
882 0 : errors[i].error),
884 silc_buffer_free(idp);
887 if (status == SILC_STATUS_LIST_END)
894 silc_server_command_whois_send_router(SilcServerCommandContext cmd)
896 SilcServer server = cmd->server;
898 SilcUInt16 old_ident;
900 old_ident = silc_command_get_ident(cmd->payload);
901 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
902 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
904 /* Send WHOIS command to our router */
905 silc_server_packet_send(server, (SilcSocketConnection)
906 SILC_PRIMARY_ROUTE(server),
907 SILC_PACKET_COMMAND, cmd->packet->flags,
908 tmpbuf->data, tmpbuf->len, TRUE);
910 /* Reprocess this packet after received reply from router */
911 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
912 silc_command_get_ident(cmd->payload),
913 silc_server_command_whois,
914 silc_server_command_dup(cmd));
916 silc_command_set_ident(cmd->payload, old_ident);
917 silc_buffer_free(tmpbuf);
921 silc_server_command_whois_process(SilcServerCommandContext cmd)
923 SilcServer server = cmd->server;
924 char *nick = NULL, *server_name = NULL;
926 SilcClientEntry *clients = NULL, entry;
927 SilcClientID **client_id = NULL;
928 SilcUInt32 client_id_count = 0, clients_count = 0, error_client_count = 0;
929 ResolveError error_client = NULL;
931 bool check_global = FALSE;
933 /* Parse the whois request */
934 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
935 &nick, &server_name, &count,
936 &error_client, &error_client_count))
939 /* Send the WHOIS request to the router only if it included nickname.
940 Since nicknames can be expanded into many clients we need to send it
941 to router. If the WHOIS included only client ID's we will check them
942 first locally since we just might have them. */
943 if (nick && !client_id_count && cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
944 server->server_type == SILC_SERVER && !cmd->pending &&
945 !server->standalone) {
946 silc_server_command_whois_send_router(cmd);
951 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
953 else if (server->server_type != SILC_SERVER)
956 /* Get all clients matching that ID or nickname from local list */
957 if (client_id_count) {
958 /* Check all Client ID's received in the command packet */
959 for (i = 0; i < client_id_count; i++) {
960 entry = silc_idlist_find_client_by_id(server->local_list,
961 client_id[i], TRUE, NULL);
962 if (!entry && check_global)
963 entry = silc_idlist_find_client_by_id(server->global_list,
964 client_id[i], TRUE, NULL);
966 clients = silc_realloc(clients, sizeof(*clients) *
967 (clients_count + 1));
968 clients[clients_count++] = entry;
970 /* If we are normal server and did not send the request first to router
971 do it now, since we do not have the Client ID information. */
972 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
973 server->server_type == SILC_SERVER && !cmd->pending &&
974 !server->standalone) {
975 silc_server_command_whois_send_router(cmd);
980 ADD_ERROR(error_client, error_client_count, client_id[i],
981 SILC_ID_CLIENT, 0, SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
985 /* Find by nickname */
986 if (!silc_idlist_get_clients_by_hash(server->local_list,
987 nick, server->md5hash,
988 &clients, &clients_count))
989 silc_idlist_get_clients_by_nickname(server->local_list,
991 &clients, &clients_count);
993 if (!silc_idlist_get_clients_by_hash(server->global_list,
994 nick, server->md5hash,
995 &clients, &clients_count))
996 silc_idlist_get_clients_by_nickname(server->global_list,
998 &clients, &clients_count);
1002 if (!clients && (client_id_count || nick)) {
1003 /* If we are normal server and did not send the request first to router
1004 do it now, since we do not have the information. */
1005 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1006 server->server_type == SILC_SERVER && !cmd->pending &&
1007 !server->standalone) {
1008 silc_server_command_whois_send_router(cmd);
1013 /* Such client(s) really does not exist in the SILC network. */
1014 if (!client_id_count)
1015 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
1016 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1017 3, nick, strlen(nick));
1019 silc_server_command_whois_send_reply(cmd, NULL, 0,
1020 error_client, error_client_count,
1025 /* Router always finds the client entry if it exists in the SILC network.
1026 However, it might be incomplete entry and does not include all the
1027 mandatory fields that WHOIS command reply requires. Check for these and
1028 make query from the server who owns the client if some fields are
1030 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
1035 /* Send the command reply */
1036 silc_server_command_whois_send_reply(cmd, clients, clients_count,
1037 error_client, error_client_count,
1038 count, nick, client_id);
1041 if (client_id_count) {
1042 for (i = 0; i < client_id_count; i++)
1043 silc_free(client_id[i]);
1044 silc_free(client_id);
1047 silc_free(error_client);
1049 silc_free(server_name);
1054 /* Server side of command WHOIS. Processes user's query and sends found
1055 results as command replies back to the client. */
1057 SILC_SERVER_CMD_FUNC(whois)
1059 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1062 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 3328);
1064 ret = silc_server_command_whois_process(cmd);
1065 silc_server_command_free(cmd);
1068 /******************************************************************************
1072 ******************************************************************************/
1075 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
1083 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1085 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
1086 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1091 /* Get the nickname@server string and parse it. */
1092 silc_parse_userfqdn(tmp, nickname, server_name);
1094 /* Get the max count of reply messages allowed */
1095 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1097 SILC_GET32_MSB(*count, tmp);
1105 silc_server_command_whowas_check(SilcServerCommandContext cmd,
1106 SilcClientEntry *clients,
1107 SilcUInt32 clients_count)
1109 SilcServer server = cmd->server;
1111 SilcClientEntry entry;
1113 for (i = 0; i < clients_count; i++) {
1116 if (!entry->nickname || !entry->username) {
1118 SilcUInt16 old_ident;
1123 old_ident = silc_command_get_ident(cmd->payload);
1124 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1125 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1127 /* Send WHOWAS command */
1128 silc_server_packet_send(server, entry->router->connection,
1129 SILC_PACKET_COMMAND, cmd->packet->flags,
1130 tmpbuf->data, tmpbuf->len, TRUE);
1132 /* Reprocess this packet after received reply */
1133 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1134 silc_command_get_ident(cmd->payload),
1135 silc_server_command_whowas,
1136 silc_server_command_dup(cmd));
1137 cmd->pending = TRUE;
1138 silc_command_set_ident(cmd->payload, old_ident);
1140 silc_buffer_free(tmpbuf);
1149 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1150 SilcClientEntry *clients,
1151 SilcUInt32 clients_count)
1153 SilcServer server = cmd->server;
1155 int i, k, count = 0, len;
1156 SilcBuffer packet, idp;
1157 SilcClientEntry entry = NULL;
1159 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1160 char nh[256], uh[256];
1163 status = SILC_STATUS_OK;
1165 /* Process only entries that are not registered anymore. */
1167 for (i = 0; i < clients_count; i++) {
1168 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1175 /* No valid entries found at all, just send error */
1176 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1177 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1178 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1179 3, tmp, tmp ? strlen(tmp) : 0);
1183 if (valid_count > 1)
1184 status = SILC_STATUS_LIST_START;
1186 for (i = 0, k = 0; i < clients_count; i++) {
1192 status = SILC_STATUS_LIST_ITEM;
1193 if (valid_count > 1 && k == valid_count - 1)
1194 status = SILC_STATUS_LIST_END;
1195 if (count && k - 1 == count)
1196 status = SILC_STATUS_LIST_END;
1198 /* Send WHOWAS reply */
1199 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1200 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1201 memset(uh, 0, sizeof(uh));
1202 memset(nh, 0, sizeof(nh));
1204 strncat(nh, entry->nickname, strlen(entry->nickname));
1205 if (!strchr(entry->nickname, '@')) {
1206 strncat(nh, "@", 1);
1207 if (entry->servername) {
1208 strncat(nh, entry->servername, strlen(entry->servername));
1210 len = entry->router ? strlen(entry->router->server_name) :
1211 strlen(server->server_name);
1212 strncat(nh, entry->router ? entry->router->server_name :
1213 server->server_name, len);
1217 strncat(uh, entry->username, strlen(entry->username));
1218 if (!strchr(entry->username, '@')) {
1219 strncat(uh, "@", 1);
1220 strcat(uh, "*private*");
1224 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1225 status, 0, ident, 4,
1226 2, idp->data, idp->len,
1231 strlen(entry->userinfo) : 0);
1232 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1233 0, packet->data, packet->len, FALSE);
1235 silc_buffer_free(packet);
1236 silc_buffer_free(idp);
1238 if (status == SILC_STATUS_LIST_END)
1245 silc_server_command_whowas_process(SilcServerCommandContext cmd)
1247 SilcServer server = cmd->server;
1248 char *nick = NULL, *server_name = NULL;
1250 SilcClientEntry *clients = NULL;
1251 SilcUInt32 clients_count = 0;
1253 bool check_global = FALSE;
1255 /* Protocol dictates that we must always send the received WHOWAS request
1256 to our router if we are normal server, so let's do it now unless we
1257 are standalone. We will not send any replies to the client until we
1258 have received reply from the router. */
1259 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1260 server->server_type == SILC_SERVER && !cmd->pending &&
1261 !server->standalone) {
1263 SilcUInt16 old_ident;
1265 old_ident = silc_command_get_ident(cmd->payload);
1266 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1267 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1269 /* Send WHOWAS command to our router */
1270 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
1271 SILC_PACKET_COMMAND, cmd->packet->flags,
1272 tmpbuf->data, tmpbuf->len, TRUE);
1274 /* Reprocess this packet after received reply from router */
1275 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1276 silc_command_get_ident(cmd->payload),
1277 silc_server_command_whowas,
1278 silc_server_command_dup(cmd));
1279 cmd->pending = TRUE;
1280 silc_command_set_ident(cmd->payload, old_ident);
1282 silc_buffer_free(tmpbuf);
1287 /* We are ready to process the command request. Let's search for the
1288 requested client and send reply to the requesting client. */
1290 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1291 check_global = TRUE;
1292 else if (server->server_type != SILC_SERVER)
1293 check_global = TRUE;
1295 /* Parse the whowas request */
1296 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1299 /* Get all clients matching that nickname from local list */
1300 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1302 &clients, &clients_count))
1303 silc_idlist_get_clients_by_hash(server->local_list,
1304 nick, server->md5hash,
1305 &clients, &clients_count);
1307 /* Check global list as well */
1309 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1311 &clients, &clients_count))
1312 silc_idlist_get_clients_by_hash(server->global_list,
1313 nick, server->md5hash,
1314 &clients, &clients_count);
1318 /* Such a client really does not exist in the SILC network. */
1319 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1320 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1321 3, nick, strlen(nick));
1325 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1330 /* Send the command reply to the client */
1331 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1336 silc_free(server_name);
1340 /* Server side of command WHOWAS. */
1342 SILC_SERVER_CMD_FUNC(whowas)
1344 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1347 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1349 ret = silc_server_command_whowas_process(cmd);
1350 silc_server_command_free(cmd);
1353 /******************************************************************************
1357 ******************************************************************************/
1360 silc_server_command_identify_send_router(SilcServerCommandContext cmd)
1362 SilcServer server = cmd->server;
1364 SilcUInt16 old_ident;
1366 old_ident = silc_command_get_ident(cmd->payload);
1367 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1368 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1370 /* Send IDENTIFY command to our router */
1371 silc_server_packet_send(server, (SilcSocketConnection)
1372 SILC_PRIMARY_ROUTE(server),
1373 SILC_PACKET_COMMAND, cmd->packet->flags,
1374 tmpbuf->data, tmpbuf->len, TRUE);
1376 /* Reprocess this packet after received reply from router */
1377 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1378 silc_command_get_ident(cmd->payload),
1379 silc_server_command_identify,
1380 silc_server_command_dup(cmd));
1381 cmd->pending = TRUE;
1382 silc_command_set_ident(cmd->payload, old_ident);
1383 silc_buffer_free(tmpbuf);
1387 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1388 SilcClientEntry **clients,
1389 SilcUInt32 *clients_count,
1390 SilcServerEntry **servers,
1391 SilcUInt32 *servers_count,
1392 SilcChannelEntry **channels,
1393 SilcUInt32 *channels_count,
1395 ResolveError *error_id,
1396 SilcUInt32 *error_id_count)
1398 SilcServer server = cmd->server;
1401 SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
1403 bool check_global = FALSE;
1407 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1408 check_global = TRUE;
1409 else if (server->server_type != SILC_SERVER)
1410 check_global = TRUE;
1412 /* If ID Payload is in the command it must be used instead of names */
1413 tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1415 /* No ID, get the names. */
1417 /* If we are normal server and have not resolved information from
1418 router yet, do so now. */
1419 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1420 server->server_type == SILC_SERVER && !cmd->pending &&
1421 !server->standalone) {
1422 silc_server_command_identify_send_router(cmd);
1426 /* Try to get nickname@server. */
1427 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1430 char *nick_server = NULL;
1432 silc_parse_userfqdn(tmp, &nick, &nick_server);
1434 if (!silc_idlist_get_clients_by_hash(server->local_list,
1435 nick, server->md5hash,
1436 clients, clients_count))
1437 silc_idlist_get_clients_by_nickname(server->local_list,
1439 clients, clients_count);
1441 if (!silc_idlist_get_clients_by_hash(server->global_list,
1442 nick, server->md5hash,
1443 clients, clients_count))
1444 silc_idlist_get_clients_by_nickname(server->global_list,
1446 clients, clients_count);
1450 silc_free(nick_server);
1453 /* the nickname does not exist, send error reply */
1454 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1455 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1456 3, tmp, strlen(tmp));
1461 /* Try to get server name */
1462 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1464 entry = silc_idlist_find_server_by_name(server->local_list,
1466 if (!entry && check_global)
1467 entry = silc_idlist_find_server_by_name(server->global_list,
1470 *servers = silc_realloc(*servers, sizeof(**servers) *
1471 (*servers_count + 1));
1472 (*servers)[(*servers_count)++] = entry;
1476 /* the server does not exist, send error reply */
1477 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1478 SILC_STATUS_ERR_NO_SUCH_SERVER,
1479 0, 3, tmp, strlen(tmp));
1484 /* Try to get channel name */
1485 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1487 entry = silc_idlist_find_channel_by_name(server->local_list,
1489 if (!entry && check_global)
1490 entry = silc_idlist_find_channel_by_name(server->global_list,
1493 *channels = silc_realloc(*channels, sizeof(**channels) *
1494 (*channels_count + 1));
1495 (*channels)[(*channels_count)++] = entry;
1499 /* The channel does not exist, send error reply */
1500 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1501 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1502 0, 3, tmp, strlen(tmp));
1507 if (!(*clients) && !(*servers) && !(*channels)) {
1508 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1509 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1514 /* Command includes ID, we must use that. Also check whether the command
1515 has more than one ID set - take them all. */
1517 /* Take all ID's from the command packet */
1518 for (i = 0; i < argc; i++) {
1521 tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
1525 idp = silc_id_payload_parse(tmp, len);
1527 ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1528 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1530 id = silc_id_payload_get_id(idp);
1531 switch (silc_id_payload_get_type(idp)) {
1533 case SILC_ID_CLIENT:
1534 entry = silc_idlist_find_client_by_id(server->local_list,
1536 if (!entry && check_global)
1537 entry = silc_idlist_find_client_by_id(server->global_list,
1540 *clients = silc_realloc(*clients, sizeof(**clients) *
1541 (*clients_count + 1));
1542 (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
1544 /* If we are normal server and have not resolved information from
1545 router yet, do so now. */
1546 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1547 server->server_type == SILC_SERVER && !cmd->pending &&
1548 !server->standalone) {
1549 silc_server_command_identify_send_router(cmd);
1550 silc_free(*clients);
1551 silc_free(*servers);
1552 silc_free(*channels);
1553 silc_free(*error_id);
1557 ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1558 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
1563 case SILC_ID_SERVER:
1564 entry = silc_idlist_find_server_by_id(server->local_list,
1566 if (!entry && check_global)
1567 entry = silc_idlist_find_server_by_id(server->global_list,
1570 *servers = silc_realloc(*servers, sizeof(**servers) *
1571 (*servers_count + 1));
1572 (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
1574 /* If we are normal server and have not resolved information from
1575 router yet, do so now. */
1576 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1577 server->server_type == SILC_SERVER && !cmd->pending &&
1578 !server->standalone) {
1579 silc_server_command_identify_send_router(cmd);
1580 silc_free(*clients);
1581 silc_free(*servers);
1582 silc_free(*channels);
1583 silc_free(*error_id);
1587 ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1588 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
1592 case SILC_ID_CHANNEL:
1593 entry = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
1594 if (!entry && check_global)
1595 entry = silc_idlist_find_channel_by_id(server->global_list, id,
1598 *channels = silc_realloc(*channels, sizeof(**channels) *
1599 (*channels_count + 1));
1600 (*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
1602 /* If we are normal server and have not resolved information from
1603 router yet, do so now. */
1604 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1605 server->server_type == SILC_SERVER && !cmd->pending &&
1606 !server->standalone) {
1607 silc_server_command_identify_send_router(cmd);
1608 silc_free(*clients);
1609 silc_free(*servers);
1610 silc_free(*channels);
1611 silc_free(*error_id);
1615 ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1616 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID);
1621 silc_id_payload_free(idp);
1626 /* Get the max count of reply messages allowed */
1627 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1629 SILC_GET32_MSB(*count, tmp);
1636 /* Checks that all mandatory fields in client entry are present. If not
1637 then send WHOIS request to the server who owns the client. We use
1638 WHOIS because we want to get as much information as possible at once. */
1641 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1642 SilcClientEntry *clients,
1643 SilcUInt32 clients_count)
1645 SilcServer server = cmd->server;
1646 SilcClientEntry entry;
1647 SilcServerResolveContext resolve = NULL, r = NULL;
1648 SilcUInt32 resolve_count = 0;
1652 for (i = 0; i < clients_count; i++) {
1657 if (entry->nickname ||
1658 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1662 /* If we are normal server, and we've not resolved this client from
1663 router and it is global client, we'll check whether it is on some
1664 channel. If not then we cannot be sure about its validity, and
1665 we'll resolve it from router. */
1666 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
1667 entry->connection || silc_hash_table_count(entry->channels))
1671 /* We need to resolve this entry since it is not complete */
1673 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1674 /* The entry is being resolved (and we are not the resolver) so attach
1675 to the command reply and we're done with this one. */
1676 silc_server_command_pending(server, SILC_COMMAND_NONE,
1677 entry->resolve_cmd_ident,
1678 silc_server_command_identify,
1679 silc_server_command_dup(cmd));
1682 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1683 /* We've resolved this and it still is not ready. We'll return
1684 and are that this will be handled again after it is resolved. */
1685 for (i = 0; i < resolve_count; i++) {
1686 for (k = 0; k < r->res_argc; k++)
1687 silc_free(r->res_argv[k]);
1688 silc_free(r->res_argv);
1689 silc_free(r->res_argv_lens);
1690 silc_free(r->res_argv_types);
1695 /* We'll resolve this client */
1699 for (k = 0; k < resolve_count; k++) {
1700 if (resolve[k].router == entry->router) {
1707 resolve = silc_realloc(resolve, sizeof(*resolve) *
1708 (resolve_count + 1));
1709 r = &resolve[resolve_count];
1710 memset(r, 0, sizeof(*r));
1711 r->router = entry->router;
1712 r->ident = ++server->cmd_ident;
1716 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1718 r->res_argv_lens = silc_realloc(r->res_argv_lens,
1719 sizeof(*r->res_argv_lens) *
1721 r->res_argv_types = silc_realloc(r->res_argv_types,
1722 sizeof(*r->res_argv_types) *
1724 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1725 r->res_argv[r->res_argc] = silc_calloc(idp->len,
1726 sizeof(**r->res_argv));
1727 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1728 r->res_argv_lens[r->res_argc] = idp->len;
1729 r->res_argv_types[r->res_argc] = r->res_argc + 4;
1731 silc_buffer_free(idp);
1733 entry->resolve_cmd_ident = r->ident;
1734 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1735 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1740 /* Do the resolving */
1741 for (i = 0; i < resolve_count; i++) {
1746 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1747 now anyway so make it a good one. */
1748 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1749 r->res_argc, r->res_argv,
1753 silc_server_packet_send(server, r->router->connection,
1754 SILC_PACKET_COMMAND, cmd->packet->flags,
1755 res_cmd->data, res_cmd->len, FALSE);
1757 /* Reprocess this packet after received reply */
1758 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1760 silc_server_command_identify,
1761 silc_server_command_dup(cmd));
1762 cmd->pending = TRUE;
1764 silc_buffer_free(res_cmd);
1765 for (k = 0; k < r->res_argc; k++)
1766 silc_free(r->res_argv[k]);
1767 silc_free(r->res_argv);
1768 silc_free(r->res_argv_lens);
1769 silc_free(r->res_argv_types);
1778 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1779 SilcClientEntry *clients,
1780 SilcUInt32 clients_count,
1781 SilcServerEntry *servers,
1782 SilcUInt32 servers_count,
1783 SilcChannelEntry *channels,
1784 SilcUInt32 channels_count,
1785 ResolveError errors,
1786 SilcUInt32 errors_count,
1789 SilcServer server = cmd->server;
1790 int i, k, valid_count;
1792 SilcBuffer packet, idp;
1794 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1795 char nh[256], uh[256];
1796 SilcSocketConnection hsock;
1799 status = SILC_STATUS_OK;
1802 SilcClientEntry entry;
1803 valid_count = clients_count;
1805 if (silc_argument_get_arg_type(cmd->args, 1, NULL)) {
1806 /* Process only valid clients and ignore those that are not registered.
1807 This is checked with nickname only because when resolved client IDs
1808 we check that they are registered earlier. */
1810 for (i = 0; i < clients_count; i++) {
1811 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1818 /* No valid entries found at all, just send error */
1819 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1820 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1821 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1822 3, tmp, tmp ? strlen(tmp) : 0);
1827 /* Process all valid client entries and send command replies */
1829 if (valid_count > 1)
1830 status = SILC_STATUS_LIST_START;
1832 for (i = 0, k = 0; i < clients_count; i++) {
1838 status = SILC_STATUS_LIST_ITEM;
1839 if (valid_count > 1 && k == valid_count - 1
1840 && !servers_count && !channels_count && !errors_count)
1841 status = SILC_STATUS_LIST_END;
1842 if (count && k - 1 == count)
1843 status = SILC_STATUS_LIST_END;
1845 /* Send IDENTIFY reply */
1847 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1848 memset(uh, 0, sizeof(uh));
1849 memset(nh, 0, sizeof(nh));
1850 strncat(nh, entry->nickname, strlen(entry->nickname));
1851 if (!strchr(entry->nickname, '@')) {
1852 strncat(nh, "@", 1);
1853 if (entry->servername) {
1854 strncat(nh, entry->servername, strlen(entry->servername));
1856 len = entry->router ? strlen(entry->router->server_name) :
1857 strlen(server->server_name);
1858 strncat(nh, entry->router ? entry->router->server_name :
1859 server->server_name, len);
1863 if (!entry->username) {
1864 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1865 status, 0, ident, 2,
1866 2, idp->data, idp->len,
1869 strncat(uh, entry->username, strlen(entry->username));
1870 if (!strchr(entry->username, '@') && entry->connection) {
1871 strncat(uh, "@", 1);
1872 hsock = (SilcSocketConnection)entry->connection;
1873 len = strlen(hsock->hostname);
1874 strncat(uh, hsock->hostname, len);
1877 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1878 status, 0, ident, 3,
1879 2, idp->data, idp->len,
1884 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1885 0, packet->data, packet->len, FALSE);
1887 silc_buffer_free(packet);
1888 silc_buffer_free(idp);
1890 if (status == SILC_STATUS_LIST_END)
1897 SilcServerEntry entry;
1899 if (status == SILC_STATUS_OK && servers_count > 1)
1900 status = SILC_STATUS_LIST_START;
1902 for (i = 0, k = 0; i < servers_count; i++) {
1906 status = SILC_STATUS_LIST_ITEM;
1907 if (servers_count > 1 && k == servers_count - 1 && !channels_count &&
1909 status = SILC_STATUS_LIST_END;
1910 if (count && k - 1 == count)
1911 status = SILC_STATUS_LIST_END;
1913 /* Send IDENTIFY reply */
1914 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1916 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1917 status, 0, ident, 2,
1918 2, idp->data, idp->len,
1919 3, entry->server_name,
1920 entry->server_name ?
1921 strlen(entry->server_name) : 0);
1922 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1923 0, packet->data, packet->len, FALSE);
1925 silc_buffer_free(packet);
1926 silc_buffer_free(idp);
1928 if (status == SILC_STATUS_LIST_END)
1935 SilcChannelEntry entry;
1937 if (status == SILC_STATUS_OK && channels_count > 1)
1938 status = SILC_STATUS_LIST_START;
1940 for (i = 0, k = 0; i < channels_count; i++) {
1941 entry = channels[i];
1944 status = SILC_STATUS_LIST_ITEM;
1945 if (channels_count > 1 && k == channels_count - 1 && !errors_count)
1946 status = SILC_STATUS_LIST_END;
1947 if (count && k - 1 == count)
1948 status = SILC_STATUS_LIST_END;
1950 /* Send IDENTIFY reply */
1951 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1953 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1954 status, 0, ident, 2,
1955 2, idp->data, idp->len,
1956 3, entry->channel_name,
1957 entry->channel_name ?
1958 strlen(entry->channel_name): 0);
1959 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1960 0, packet->data, packet->len, FALSE);
1962 silc_buffer_free(packet);
1963 silc_buffer_free(idp);
1965 if (status == SILC_STATUS_LIST_END)
1971 /* Send error replies */
1973 if (status == SILC_STATUS_OK && errors_count > 1)
1974 status = SILC_STATUS_LIST_START;
1977 for (i = 0, k = 0; i < errors_count; i++) {
1979 idp = silc_id_payload_encode(errors[i].id, SILC_ID_CLIENT);
1983 tmp = silc_argument_get_arg_type(cmd->args, errors[i].index, &len);
1987 status = SILC_STATUS_LIST_ITEM;
1988 if (errors_count > 1 && k == errors_count - 1)
1989 status = SILC_STATUS_LIST_END;
1990 if (count && k - 1 == count)
1991 status = SILC_STATUS_LIST_END;
1994 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1995 (status == SILC_STATUS_OK ?
1996 errors[i].error : status),
1997 (status == SILC_STATUS_OK ?
1998 0 : errors[i].error),
2000 silc_buffer_free(idp);
2003 if (status == SILC_STATUS_LIST_END)
2011 silc_server_command_identify_process(SilcServerCommandContext cmd)
2013 SilcUInt32 count = 0;
2015 SilcClientEntry *clients = NULL;
2016 SilcServerEntry *servers = NULL;
2017 SilcChannelEntry *channels = NULL;
2018 SilcUInt32 clients_count = 0, servers_count = 0, channels_count = 0;
2019 SilcUInt32 errors_count = 0;
2020 ResolveError errors = NULL;
2022 /* Parse the IDENTIFY request */
2023 ret = silc_server_command_identify_parse(cmd,
2024 &clients, &clients_count,
2025 &servers, &servers_count,
2026 &channels, &channels_count,
2027 &count, &errors, &errors_count);
2032 /* Check that all mandatory fields are present and request those data
2033 from the server who owns the client if necessary. */
2034 if (!silc_server_command_identify_check_client(cmd, clients,
2040 /* Send the command reply to the client */
2041 silc_server_command_identify_send_reply(cmd,
2042 clients, clients_count,
2043 servers, servers_count,
2044 channels, channels_count,
2045 errors, errors_count,
2051 silc_free(channels);
2056 SILC_SERVER_CMD_FUNC(identify)
2058 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2061 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
2063 ret = silc_server_command_identify_process(cmd);
2064 silc_server_command_free(cmd);
2067 /* Server side of command NICK. Sets nickname for user. Setting
2068 nickname causes generation of a new client ID for the client. The
2069 new client ID is sent to the client after changing the nickname. */
2071 SILC_SERVER_CMD_FUNC(nick)
2073 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2074 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2075 SilcServer server = cmd->server;
2076 SilcBuffer packet, nidp, oidp = NULL;
2077 SilcClientID *new_id;
2078 SilcUInt32 nick_len;
2080 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2083 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2086 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
2088 /* Check nickname */
2089 nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
2092 if (silc_server_name_bad_chars(nick, nick_len) == TRUE) {
2093 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2094 SILC_STATUS_ERR_BAD_NICKNAME, 0);
2098 /* Check for same nickname */
2099 if (!strcmp(client->nickname, nick)) {
2100 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2104 /* Create new Client ID */
2105 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
2107 cmd->server->md5hash, nick,
2111 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2112 SILC_STATUS_ERR_BAD_NICKNAME, 0);
2115 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2118 /* Send notify about nickname change to our router. We send the new
2119 ID and ask to replace it with the old one. If we are router the
2120 packet is broadcasted. Send NICK_CHANGE notify. */
2121 silc_server_send_notify_nick_change(server, SILC_PRIMARY_ROUTE(server),
2122 SILC_BROADCAST(server), client->id,
2125 /* Check if anyone is watching the old nickname */
2126 if (server->server_type == SILC_ROUTER)
2127 silc_server_check_watcher_list(server, client, nick,
2128 SILC_NOTIFY_TYPE_NICK_CHANGE);
2130 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2132 /* Remove old cache entry */
2133 silc_idcache_del_by_context(server->local_list->clients, client);
2135 silc_free(client->id);
2136 client->id = new_id;
2138 silc_free(client->nickname);
2139 client->nickname = strdup(nick);
2141 /* Update client cache */
2142 silc_idcache_add(server->local_list->clients, client->nickname,
2143 client->id, (void *)client, 0, NULL);
2145 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2147 /* Send NICK_CHANGE notify to the client's channels */
2148 silc_server_send_notify_on_channels(server, NULL, client,
2149 SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
2150 oidp->data, oidp->len,
2151 nidp->data, nidp->len,
2153 strlen(client->nickname));
2155 /* Check if anyone is watching the new nickname */
2156 if (server->server_type == SILC_ROUTER)
2157 silc_server_check_watcher_list(server, client, NULL,
2158 SILC_NOTIFY_TYPE_NICK_CHANGE);
2161 /* Send the new Client ID as reply command back to client */
2162 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
2163 SILC_STATUS_OK, 0, ident, 2,
2164 2, nidp->data, nidp->len,
2165 3, nick, strlen(nick));
2166 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2167 0, packet->data, packet->len, FALSE);
2169 silc_buffer_free(packet);
2170 silc_buffer_free(nidp);
2172 silc_buffer_free(oidp);
2175 silc_server_command_free(cmd);
2178 /* Sends the LIST command reply */
2181 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2182 SilcChannelEntry *lch,
2183 SilcUInt32 lch_count,
2184 SilcChannelEntry *gch,
2185 SilcUInt32 gch_count)
2188 SilcBuffer packet, idp;
2189 SilcChannelEntry entry;
2191 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2193 unsigned char usercount[4];
2195 int valid_lcount = 0, valid_rcount = 0;
2197 for (i = 0; i < lch_count; i++) {
2198 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2203 for (i = 0; i < gch_count; i++) {
2204 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2210 status = SILC_STATUS_OK;
2211 if ((lch_count + gch_count) > 1)
2212 status = SILC_STATUS_LIST_START;
2215 for (i = 0, k = 0; i < lch_count; i++) {
2221 status = SILC_STATUS_LIST_ITEM;
2222 if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
2223 status = SILC_STATUS_LIST_END;
2225 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2227 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2228 topic = "*private*";
2229 memset(usercount, 0, sizeof(usercount));
2231 topic = entry->topic;
2232 users = silc_hash_table_count(entry->user_list);
2233 SILC_PUT32_MSB(users, usercount);
2236 /* Send the reply */
2238 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2239 status, 0, ident, 4,
2240 2, idp->data, idp->len,
2241 3, entry->channel_name,
2242 strlen(entry->channel_name),
2243 4, topic, topic ? strlen(topic) : 0,
2245 silc_server_packet_send(cmd->server, cmd->sock,
2246 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2247 packet->len, FALSE);
2248 silc_buffer_free(packet);
2249 silc_buffer_free(idp);
2254 for (i = 0, k = 0; i < gch_count; i++) {
2260 status = SILC_STATUS_LIST_ITEM;
2261 if (valid_rcount > 1 && k == valid_rcount - 1)
2262 status = SILC_STATUS_LIST_END;
2264 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2266 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2267 topic = "*private*";
2268 memset(usercount, 0, sizeof(usercount));
2270 topic = entry->topic;
2271 users = entry->user_count;
2272 SILC_PUT32_MSB(users, usercount);
2275 /* Send the reply */
2277 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2278 status, 0, ident, 4,
2279 2, idp->data, idp->len,
2280 3, entry->channel_name,
2281 strlen(entry->channel_name),
2282 4, topic, topic ? strlen(topic) : 0,
2284 silc_server_packet_send(cmd->server, cmd->sock,
2285 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2286 packet->len, FALSE);
2287 silc_buffer_free(packet);
2288 silc_buffer_free(idp);
2293 /* Server side of LIST command. This lists the channel of the requested
2294 server. Secret channels are not listed. */
2296 SILC_SERVER_CMD_FUNC(list)
2298 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2299 SilcServer server = cmd->server;
2300 SilcChannelID *channel_id = NULL;
2303 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2304 SilcUInt32 lch_count = 0, gch_count = 0;
2306 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2308 /* If we are normal server, send the command to router, since we
2309 want to know all channels in the network. */
2310 if (!cmd->pending && server->server_type == SILC_SERVER &&
2311 !server->standalone) {
2313 SilcUInt16 old_ident;
2315 old_ident = silc_command_get_ident(cmd->payload);
2316 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2317 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2318 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
2319 SILC_PACKET_COMMAND, cmd->packet->flags,
2320 tmpbuf->data, tmpbuf->len, TRUE);
2322 /* Reprocess this packet after received reply from router */
2323 silc_server_command_pending(server, SILC_COMMAND_LIST,
2324 silc_command_get_ident(cmd->payload),
2325 silc_server_command_list,
2326 silc_server_command_dup(cmd));
2327 cmd->pending = TRUE;
2328 silc_command_set_ident(cmd->payload, old_ident);
2329 silc_buffer_free(tmpbuf);
2333 /* Get Channel ID */
2334 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2336 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2338 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2339 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2344 /* Get the channels from local list */
2345 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2348 /* Get the channels from global list */
2349 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2352 /* Send the reply */
2353 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2354 gchannels, gch_count);
2356 silc_free(lchannels);
2357 silc_free(gchannels);
2360 silc_server_command_free(cmd);
2363 /* Server side of TOPIC command. Sets topic for channel and/or returns
2364 current topic to client. */
2366 SILC_SERVER_CMD_FUNC(topic)
2368 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2369 SilcServer server = cmd->server;
2370 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2371 SilcChannelID *channel_id;
2372 SilcChannelEntry channel;
2373 SilcChannelClientEntry chl;
2374 SilcBuffer packet, idp;
2376 SilcUInt32 argc, tmp_len;
2377 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2379 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2381 argc = silc_argument_get_arg_num(cmd->args);
2383 /* Get Channel ID */
2384 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2386 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2387 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2390 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2392 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2393 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2397 /* Check whether the channel exists */
2398 channel = silc_idlist_find_channel_by_id(server->local_list,
2401 channel = silc_idlist_find_channel_by_id(server->global_list,
2404 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2405 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
2413 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2415 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2416 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2421 if (strlen(tmp) > 256) {
2422 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2423 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2428 /* See whether the client is on channel and has rights to change topic */
2429 if (!silc_server_client_on_channel(client, channel, &chl)) {
2430 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2431 SILC_STATUS_ERR_NOT_ON_CHANNEL,
2436 if (channel->mode & SILC_CHANNEL_MODE_TOPIC &&
2437 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
2438 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
2439 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2440 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
2445 if (!channel->topic || strcmp(channel->topic, tmp)) {
2446 /* Set the topic for channel */
2447 silc_free(channel->topic);
2448 channel->topic = strdup(tmp);
2450 /* Send TOPIC_SET notify type to the network */
2451 silc_server_send_notify_topic_set(server, SILC_PRIMARY_ROUTE(server),
2452 SILC_BROADCAST(server), channel,
2453 client->id, SILC_ID_CLIENT,
2456 /* Send notify about topic change to all clients on the channel */
2457 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2458 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2459 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2460 idp->data, idp->len,
2462 strlen(channel->topic));
2463 silc_buffer_free(idp);
2467 /* Send the topic to client as reply packet */
2468 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2469 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2470 SILC_STATUS_OK, 0, ident, 2,
2471 2, idp->data, idp->len,
2474 strlen(channel->topic) : 0);
2475 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2476 0, packet->data, packet->len, FALSE);
2478 silc_buffer_free(packet);
2479 silc_buffer_free(idp);
2480 silc_free(channel_id);
2483 silc_server_command_free(cmd);
2486 /* Server side of INVITE command. Invites some client to join some channel.
2487 This command is also used to manage the invite list of the channel. */
2489 SILC_SERVER_CMD_FUNC(invite)
2491 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2492 SilcServer server = cmd->server;
2493 SilcSocketConnection sock = cmd->sock, dest_sock;
2494 SilcChannelClientEntry chl;
2495 SilcClientEntry sender, dest;
2496 SilcClientID *dest_id = NULL;
2497 SilcChannelEntry channel;
2498 SilcChannelID *channel_id = NULL;
2499 SilcIDListData idata;
2500 SilcBuffer idp, idp2, packet;
2501 unsigned char *tmp, *add, *del;
2503 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2505 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2507 /* Get Channel ID */
2508 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2510 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2511 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2514 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
2516 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2517 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2521 /* Get the channel entry */
2522 channel = silc_idlist_find_channel_by_id(server->local_list,
2525 channel = silc_idlist_find_channel_by_id(server->global_list,
2528 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2529 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
2535 /* Check whether the sender of this command is on the channel. */
2536 sender = (SilcClientEntry)sock->user_data;
2537 if (!silc_server_client_on_channel(sender, channel, &chl)) {
2538 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2539 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
2543 /* Check whether the channel is invite-only channel. If yes then the
2544 sender of this command must be at least channel operator. */
2545 if (channel->mode & SILC_CHANNEL_MODE_INVITE &&
2546 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
2547 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
2548 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2549 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
2554 /* Get destination client ID */
2555 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2560 dest_id = silc_id_payload_parse_id(tmp, len, NULL);
2562 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2563 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
2567 /* Get the client entry */
2568 dest = silc_server_get_client_resolve(server, dest_id, FALSE, &resolve);
2570 if (server->server_type != SILC_SERVER || !resolve) {
2571 silc_server_command_send_status_reply(
2572 cmd, SILC_COMMAND_INVITE,
2573 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0);
2577 /* The client info is being resolved. Reprocess this packet after
2578 receiving the reply to the query. */
2579 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2581 silc_server_command_invite,
2582 silc_server_command_dup(cmd));
2583 cmd->pending = TRUE;
2584 silc_free(channel_id);
2589 /* Check whether the requested client is already on the channel. */
2590 if (silc_server_client_on_channel(dest, channel, NULL)) {
2591 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2592 SILC_STATUS_ERR_USER_ON_CHANNEL,
2597 /* Get route to the client */
2598 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id,
2601 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2602 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2607 memset(invite, 0, sizeof(invite));
2608 strncat(invite, dest->nickname, strlen(dest->nickname));
2609 strncat(invite, "!", 1);
2610 strncat(invite, dest->username, strlen(dest->username));
2611 if (!strchr(dest->username, '@')) {
2612 strncat(invite, "@", 1);
2613 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2616 len = strlen(invite);
2617 if (!channel->invite_list)
2618 channel->invite_list = silc_calloc(len + 2,
2619 sizeof(*channel->invite_list));
2621 channel->invite_list = silc_realloc(channel->invite_list,
2622 sizeof(*channel->invite_list) *
2624 strlen(channel->invite_list) + 2));
2625 strncat(channel->invite_list, invite, len);
2626 strncat(channel->invite_list, ",", 1);
2628 if (!(dest->mode & SILC_UMODE_BLOCK_INVITE)) {
2629 /* Send notify to the client that is invited to the channel */
2630 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2631 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2632 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2634 SILC_NOTIFY_TYPE_INVITE, 3,
2635 idp->data, idp->len,
2636 channel->channel_name,
2637 strlen(channel->channel_name),
2638 idp2->data, idp2->len);
2639 silc_buffer_free(idp);
2640 silc_buffer_free(idp2);
2644 /* Add the client to the invite list of the channel */
2645 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2647 if (!channel->invite_list)
2648 channel->invite_list = silc_calloc(len + 2,
2649 sizeof(*channel->invite_list));
2651 channel->invite_list = silc_realloc(channel->invite_list,
2652 sizeof(*channel->invite_list) *
2654 strlen(channel->invite_list) + 2));
2655 if (add[len - 1] == ',')
2656 add[len - 1] = '\0';
2658 strncat(channel->invite_list, add, len);
2659 strncat(channel->invite_list, ",", 1);
2662 /* Get the invite to be removed and remove it from the list */
2663 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2664 if (del && channel->invite_list) {
2665 char *start, *end, *n;
2667 if (!strncmp(channel->invite_list, del,
2668 strlen(channel->invite_list) - 1)) {
2669 silc_free(channel->invite_list);
2670 channel->invite_list = NULL;
2672 start = strstr(channel->invite_list, del);
2673 if (start && strlen(start) >= len) {
2675 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2676 strncat(n, channel->invite_list, start - channel->invite_list);
2677 strncat(n, end + 1, ((channel->invite_list +
2678 strlen(channel->invite_list)) - end) - 1);
2679 silc_free(channel->invite_list);
2680 channel->invite_list = n;
2685 /* Send notify to the primary router */
2686 silc_server_send_notify_invite(server, SILC_PRIMARY_ROUTE(server),
2687 SILC_BROADCAST(server), channel,
2688 sender->id, add, del);
2690 /* Send command reply */
2691 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2695 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2696 SILC_STATUS_OK, 0, ident, 2,
2698 3, channel->invite_list,
2699 channel->invite_list ?
2700 strlen(channel->invite_list) : 0);
2703 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2704 SILC_STATUS_OK, 0, ident, 1,
2706 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2707 packet->data, packet->len, FALSE);
2708 silc_buffer_free(packet);
2712 silc_free(channel_id);
2713 silc_server_command_free(cmd);
2718 SilcSocketConnection sock;
2722 /* Quits connection to client. This gets called if client won't
2723 close the connection even when it has issued QUIT command. */
2725 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2727 QuitInternal q = (QuitInternal)context;
2729 /* Free all client specific data, such as client entry and entires
2730 on channels this client may be on. */
2731 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2733 q->sock->user_data = NULL;
2735 /* Close the connection on our side */
2736 silc_server_close_connection(q->server, q->sock);
2738 silc_free(q->signoff);
2742 /* Quits SILC session. This is the normal way to disconnect client. */
2744 SILC_SERVER_CMD_FUNC(quit)
2746 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2747 SilcServer server = cmd->server;
2748 SilcSocketConnection sock = cmd->sock;
2750 unsigned char *tmp = NULL;
2753 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2755 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2759 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2763 q = silc_calloc(1, sizeof(*q));
2766 q->signoff = tmp ? strdup(tmp) : NULL;
2768 /* We quit the connection with little timeout */
2769 silc_schedule_task_add(server->schedule, sock->sock,
2770 silc_server_command_quit_cb, (void *)q,
2771 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2774 silc_server_command_free(cmd);
2777 /* Server side of command KILL. This command is used by router operator
2778 to remove an client from the SILC Network temporarily. */
2780 SILC_SERVER_CMD_FUNC(kill)
2782 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2783 SilcServer server = cmd->server;
2784 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2785 SilcClientEntry remote_client;
2786 SilcClientID *client_id;
2787 unsigned char *tmp, *comment;
2788 SilcUInt32 tmp_len, tmp_len2;
2791 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2793 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2796 /* KILL command works only on router */
2797 if (server->server_type != SILC_ROUTER) {
2798 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2799 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
2803 /* Check whether client has the permissions. */
2804 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2805 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2806 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
2810 /* Get the client ID */
2811 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2813 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2814 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2818 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2820 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2821 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2826 /* Get the client entry */
2827 remote_client = silc_idlist_find_client_by_id(server->local_list,
2828 client_id, TRUE, NULL);
2830 if (!remote_client) {
2831 remote_client = silc_idlist_find_client_by_id(server->global_list,
2832 client_id, TRUE, NULL);
2834 if (!remote_client) {
2835 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2836 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2843 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2847 /* Send reply to the sender */
2848 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2851 /* Check if anyone is watching this nickname */
2852 if (server->server_type == SILC_ROUTER)
2853 silc_server_check_watcher_list(server, client, NULL,
2854 SILC_NOTIFY_TYPE_KILLED);
2856 /* Now do the killing */
2857 silc_server_kill_client(server, remote_client, comment, client->id,
2861 silc_server_command_free(cmd);
2864 /* Server side of command INFO. This sends information about us to
2865 the client. If client requested specific server we will send the
2866 command to that server. */
2868 SILC_SERVER_CMD_FUNC(info)
2870 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2871 SilcServer server = cmd->server;
2872 SilcBuffer packet, idp;
2875 char *dest_server, *server_info = NULL, *server_name;
2876 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2877 SilcServerEntry entry = NULL;
2878 SilcServerID *server_id = NULL;
2880 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2882 /* Get server name */
2883 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2886 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2888 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2890 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2891 SILC_STATUS_ERR_NO_SERVER_ID, 0);
2897 /* Check whether we have this server cached */
2898 entry = silc_idlist_find_server_by_id(server->local_list,
2899 server_id, TRUE, NULL);
2901 entry = silc_idlist_find_server_by_id(server->global_list,
2902 server_id, TRUE, NULL);
2903 if (!entry && server->server_type != SILC_SERVER) {
2904 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2905 SILC_STATUS_ERR_NO_SUCH_SERVER,
2912 /* Some buggy servers has sent request to router about themselves. */
2913 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2916 if ((!dest_server && !server_id && !entry) || (entry &&
2917 entry == server->id_entry) ||
2918 (dest_server && !cmd->pending &&
2919 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2920 /* Send our reply */
2921 char info_string[256];
2923 memset(info_string, 0, sizeof(info_string));
2924 snprintf(info_string, sizeof(info_string),
2925 "location: %s server: %s admin: %s <%s>",
2926 server->config->server_info->location,
2927 server->config->server_info->server_type,
2928 server->config->server_info->admin,
2929 server->config->server_info->email);
2931 server_info = info_string;
2932 entry = server->id_entry;
2934 /* Check whether we have this server cached */
2935 if (!entry && dest_server) {
2936 entry = silc_idlist_find_server_by_name(server->global_list,
2937 dest_server, TRUE, NULL);
2939 entry = silc_idlist_find_server_by_name(server->local_list,
2940 dest_server, TRUE, NULL);
2944 if (!cmd->pending &&
2945 server->server_type != SILC_SERVER && entry && !entry->server_info) {
2946 /* Send to the server */
2948 SilcUInt16 old_ident;
2950 old_ident = silc_command_get_ident(cmd->payload);
2951 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2952 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2954 silc_server_packet_send(server, entry->connection,
2955 SILC_PACKET_COMMAND, cmd->packet->flags,
2956 tmpbuf->data, tmpbuf->len, TRUE);
2958 /* Reprocess this packet after received reply from router */
2959 silc_server_command_pending(server, SILC_COMMAND_INFO,
2960 silc_command_get_ident(cmd->payload),
2961 silc_server_command_info,
2962 silc_server_command_dup(cmd));
2963 cmd->pending = TRUE;
2964 silc_command_set_ident(cmd->payload, old_ident);
2965 silc_buffer_free(tmpbuf);
2969 if (!entry && !cmd->pending && !server->standalone) {
2970 /* Send to the primary router */
2972 SilcUInt16 old_ident;
2974 old_ident = silc_command_get_ident(cmd->payload);
2975 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2976 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2978 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
2979 SILC_PACKET_COMMAND, cmd->packet->flags,
2980 tmpbuf->data, tmpbuf->len, TRUE);
2982 /* Reprocess this packet after received reply from router */
2983 silc_server_command_pending(server, SILC_COMMAND_INFO,
2984 silc_command_get_ident(cmd->payload),
2985 silc_server_command_info,
2986 silc_server_command_dup(cmd));
2987 cmd->pending = TRUE;
2988 silc_command_set_ident(cmd->payload, old_ident);
2989 silc_buffer_free(tmpbuf);
2994 silc_free(server_id);
2997 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2998 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3002 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
3004 server_info = entry->server_info;
3005 server_name = entry->server_name;
3007 /* Send the reply */
3008 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
3009 SILC_STATUS_OK, 0, ident, 3,
3010 2, idp->data, idp->len,
3012 strlen(server_name),
3015 strlen(server_info) : 0);
3016 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3017 packet->data, packet->len, FALSE);
3019 silc_buffer_free(packet);
3020 silc_buffer_free(idp);
3023 silc_server_command_free(cmd);
3026 /* Server side of command PING. This just replies to the ping. */
3028 SILC_SERVER_CMD_FUNC(ping)
3030 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3031 SilcServer server = cmd->server;
3036 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
3039 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
3041 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3042 SILC_STATUS_ERR_NO_SERVER_ID, 0);
3045 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
3049 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
3050 /* Send our reply */
3051 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3054 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3055 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3062 silc_server_command_free(cmd);
3065 /* Server side of command STATS. */
3067 SILC_SERVER_CMD_FUNC(stats)
3069 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3070 SilcServer server = cmd->server;
3071 SilcServerID *server_id;
3074 SilcBuffer packet, stats;
3075 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3078 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1);
3081 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3083 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3084 SILC_STATUS_ERR_NO_SERVER_ID, 0);
3087 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3091 /* The ID must be ours */
3092 if (!SILC_ID_SERVER_COMPARE(server->id, server_id)) {
3093 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3094 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3095 silc_free(server_id);
3098 silc_free(server_id);
3100 /* If we are router then just send everything we got. If we are normal
3101 server then we'll send this to our router to get all the latest
3102 statistical information. */
3103 if (!cmd->pending && server->server_type != SILC_ROUTER &&
3104 !server->standalone) {
3105 /* Send request to our router */
3106 SilcBuffer idp = silc_id_payload_encode(server->router->id,
3108 packet = silc_command_payload_encode_va(SILC_COMMAND_STATS,
3109 ++server->cmd_ident, 1,
3110 1, idp->data, idp->len);
3111 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
3112 SILC_PACKET_COMMAND, 0, packet->data,
3113 packet->len, FALSE);
3115 /* Reprocess this packet after received reply from router */
3116 silc_server_command_pending(server, SILC_COMMAND_STATS,
3118 silc_server_command_stats,
3119 silc_server_command_dup(cmd));
3120 cmd->pending = TRUE;
3121 silc_buffer_free(packet);
3122 silc_buffer_free(idp);
3126 /* Send our reply to sender */
3127 uptime = time(NULL) - server->starttime;
3129 stats = silc_buffer_alloc_size(60);
3130 silc_buffer_format(stats,
3131 SILC_STR_UI_INT(server->starttime),
3132 SILC_STR_UI_INT(uptime),
3133 SILC_STR_UI_INT(server->stat.my_clients),
3134 SILC_STR_UI_INT(server->stat.my_channels),
3135 SILC_STR_UI_INT(server->stat.my_server_ops),
3136 SILC_STR_UI_INT(server->stat.my_router_ops),
3137 SILC_STR_UI_INT(server->stat.cell_clients),
3138 SILC_STR_UI_INT(server->stat.cell_channels),
3139 SILC_STR_UI_INT(server->stat.cell_servers),
3140 SILC_STR_UI_INT(server->stat.clients),
3141 SILC_STR_UI_INT(server->stat.channels),
3142 SILC_STR_UI_INT(server->stat.servers),
3143 SILC_STR_UI_INT(server->stat.routers),
3144 SILC_STR_UI_INT(server->stat.server_ops),
3145 SILC_STR_UI_INT(server->stat.router_ops),
3148 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_STATS,
3149 SILC_STATUS_OK, 0, ident, 2,
3151 3, stats->data, stats->len);
3152 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
3153 0, packet->data, packet->len, FALSE);
3154 silc_buffer_free(packet);
3155 silc_buffer_free(stats);
3158 silc_server_command_free(cmd);
3161 /* Internal routine to join channel. The channel sent to this function
3162 has been either created or resolved from ID lists. This joins the sent
3163 client to the channel. */
3165 static void silc_server_command_join_channel(SilcServer server,
3166 SilcServerCommandContext cmd,
3167 SilcChannelEntry channel,
3168 SilcClientID *client_id,
3172 const unsigned char *auth,
3173 SilcUInt32 auth_len)
3175 SilcSocketConnection sock = cmd->sock;
3177 SilcUInt32 tmp_len, user_count;
3178 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
3179 SilcClientEntry client;
3180 SilcChannelClientEntry chl;
3181 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
3182 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3183 char check[512], check2[512];
3184 bool founder = FALSE;
3186 unsigned char *fkey = NULL;
3187 SilcUInt32 fkey_len = 0;
3189 SILC_LOG_DEBUG(("Joining client to channel"));
3194 /* Get the client entry */
3195 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3196 client = (SilcClientEntry)sock->user_data;
3198 client = silc_server_get_client_resolve(server, client_id, FALSE,
3205 silc_server_command_send_status_reply(
3206 cmd, SILC_COMMAND_JOIN,
3207 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3211 /* The client info is being resolved. Reprocess this packet after
3212 receiving the reply to the query. */
3213 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
3215 silc_server_command_join,
3216 silc_server_command_dup(cmd));
3217 cmd->pending = TRUE;
3221 cmd->pending = FALSE;
3225 * Check founder auth payload if provided. If client can gain founder
3226 * privileges it can override various conditions on joining the channel,
3227 * and can have directly the founder mode set on the channel.
3229 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3230 SilcIDListData idata = (SilcIDListData)client;
3231 SilcChannelClientEntry chl2;
3232 SilcHashTableList htl;
3234 if (channel->founder_key && idata->public_key &&
3235 silc_pkcs_public_key_compare(channel->founder_key,
3236 idata->public_key)) {
3237 /* Check whether the client is to become founder */
3238 if (silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
3239 channel->founder_key, 0, server->sha1hash,
3240 client->id, SILC_ID_CLIENT)) {
3242 /* There cannot be anyone else as founder on the channel now. This
3243 client is definitely the founder due to this authentication */
3244 silc_hash_table_list(channel->user_list, &htl);
3245 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
3246 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
3247 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3248 silc_server_force_cumode_change(server, NULL, channel, chl2,
3252 silc_hash_table_list_reset(&htl);
3254 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3261 * Check channel modes
3265 memset(check, 0, sizeof(check));
3266 memset(check2, 0, sizeof(check2));
3267 strncat(check, client->nickname, strlen(client->nickname));
3268 strncat(check, "!", 1);
3269 strncat(check, client->username, strlen(client->username));
3270 if (!strchr(client->username, '@')) {
3271 strncat(check, "@", 1);
3272 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3275 strncat(check2, client->nickname, strlen(client->nickname));
3276 if (!strchr(client->nickname, '@')) {
3277 strncat(check2, "@", 1);
3278 strncat(check2, server->server_name, strlen(server->server_name));
3280 strncat(check2, "!", 1);
3281 strncat(check2, client->username, strlen(client->username));
3282 if (!strchr(client->username, '@')) {
3283 strncat(check2, "@", 1);
3284 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3287 /* Check invite list if channel is invite-only channel */
3288 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3289 if (!channel->invite_list ||
3290 (!silc_string_match(channel->invite_list, check) &&
3291 !silc_string_match(channel->invite_list, check2))) {
3292 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3293 SILC_STATUS_ERR_NOT_INVITED, 0);
3298 /* Check ban list if it exists. If the client's nickname, server,
3299 username and/or hostname is in the ban list the access to the
3300 channel is denied. */
3301 if (channel->ban_list) {
3302 if (silc_string_match(channel->ban_list, check) ||
3303 silc_string_match(channel->ban_list, check2)) {
3304 silc_server_command_send_status_reply(
3305 cmd, SILC_COMMAND_JOIN,
3306 SILC_STATUS_ERR_BANNED_FROM_CHANNEL, 0);
3311 /* Check user count limit if set. */
3312 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3313 if (silc_hash_table_count(channel->user_list) + 1 >
3314 channel->user_limit) {
3315 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3316 SILC_STATUS_ERR_CHANNEL_IS_FULL,
3323 /* Check the channel passphrase if set. */
3324 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3325 /* Get passphrase */
3326 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3328 passphrase = silc_memdup(tmp, tmp_len);
3330 if (!passphrase || !channel->passphrase ||
3331 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3332 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3333 SILC_STATUS_ERR_BAD_PASSWORD, 0);
3339 * Client is allowed to join to the channel. Make it happen.
3342 /* Check whether the client already is on the channel */
3343 if (silc_server_client_on_channel(client, channel, NULL)) {
3344 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3345 SILC_STATUS_ERR_USER_ON_CHANNEL, 0);
3349 /* Generate new channel key as protocol dictates */
3351 if (!silc_server_create_channel_key(server, channel, 0))
3354 /* Send the channel key. This is broadcasted to the channel but is not
3355 sent to the client who is joining to the channel. */
3356 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3357 silc_server_send_channel_key(server, NULL, channel,
3358 server->server_type == SILC_ROUTER ?
3359 FALSE : !server->standalone);
3362 /* Join the client to the channel by adding it to channel's user list.
3363 Add also the channel to client entry's channels list for fast cross-
3365 chl = silc_calloc(1, sizeof(*chl));
3367 chl->client = client;
3368 chl->channel = channel;
3369 silc_hash_table_add(channel->user_list, client, chl);
3370 silc_hash_table_add(client->channels, channel, chl);
3371 channel->user_count++;
3372 channel->disabled = FALSE;
3374 /* Get users on the channel */
3375 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3378 /* Encode Client ID Payload of the original client who wants to join */
3379 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3381 /* Encode command reply packet */
3382 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3383 SILC_PUT32_MSB(channel->mode, mode);
3384 SILC_PUT32_MSB(created, tmp2);
3385 SILC_PUT32_MSB(user_count, tmp3);
3387 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3388 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3389 keyp = silc_channel_key_payload_encode(silc_id_get_len(channel->id,
3392 strlen(channel->channel_key->
3394 channel->channel_key->cipher->name,
3395 channel->key_len / 8, channel->key);
3399 if (channel->founder_key)
3400 fkey = silc_pkcs_public_key_encode(channel->founder_key, &fkey_len);
3403 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3404 SILC_STATUS_OK, 0, ident, 14,
3405 2, channel->channel_name,
3406 strlen(channel->channel_name),
3407 3, chidp->data, chidp->len,
3408 4, clidp->data, clidp->len,
3411 7, keyp ? keyp->data : NULL,
3412 keyp ? keyp->len : 0,
3413 8, channel->ban_list,
3415 strlen(channel->ban_list) : 0,
3416 9, channel->invite_list,
3417 channel->invite_list ?
3418 strlen(channel->invite_list) : 0,
3421 strlen(channel->topic) : 0,
3422 11, silc_hmac_get_name(channel->hmac),
3423 strlen(silc_hmac_get_name(channel->
3426 13, user_list->data, user_list->len,
3427 14, mode_list->data,
3429 15, fkey, fkey_len);
3431 /* Send command reply */
3432 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3433 reply->data, reply->len, FALSE);
3435 /* Send JOIN notify to locally connected clients on the channel. If
3436 we are normal server then router will send or have sent JOIN notify
3437 already. However since we've added the client already to our channel
3438 we'll ignore it (in packet_receive.c) so we must send it here. If
3439 we are router then this will send it to local clients and local
3441 SILC_LOG_DEBUG(("Send JOIN notify to channel"));
3442 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3443 SILC_NOTIFY_TYPE_JOIN, 2,
3444 clidp->data, clidp->len,
3445 chidp->data, chidp->len);
3447 /* Update statistics */
3448 server->stat.my_chanclients++;
3449 if (server->server_type == SILC_ROUTER) {
3450 server->stat.cell_chanclients++;
3451 server->stat.chanclients++;
3454 if (!cmd->pending) {
3455 /* Send JOIN notify packet to our primary router */
3456 silc_server_send_notify_join(server, SILC_PRIMARY_ROUTE(server),
3457 SILC_BROADCAST(server), channel, client->id);
3460 /* Distribute the channel key to all backup routers. */
3461 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3462 keyp->data, keyp->len, FALSE, TRUE);
3464 /* If client became founder by providing correct founder auth data
3465 notify the mode change to the channel. */
3467 SILC_PUT32_MSB(chl->mode, mode);
3468 SILC_LOG_DEBUG(("Send CUMODE_CHANGE notify to channel"));
3469 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3470 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
3471 clidp->data, clidp->len,
3472 mode, 4, clidp->data, clidp->len,
3477 /* Set CUMODE notify type to network */
3479 silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
3480 SILC_BROADCAST(server), channel,
3481 chl->mode, client->id, SILC_ID_CLIENT,
3482 client->id, channel->founder_key);
3484 silc_buffer_free(reply);
3485 silc_buffer_free(clidp);
3486 silc_buffer_free(chidp);
3487 silc_buffer_free(keyp);
3488 silc_buffer_free(user_list);
3489 silc_buffer_free(mode_list);
3493 silc_free(passphrase);
3496 /* Server side of command JOIN. Joins client into requested channel. If
3497 the channel does not exist it will be created. */
3499 SILC_SERVER_CMD_FUNC(join)
3501 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3502 SilcServer server = cmd->server;
3503 unsigned char *auth;
3504 SilcUInt32 tmp_len, auth_len;
3505 char *tmp, *channel_name = NULL, *cipher, *hmac;
3506 SilcChannelEntry channel;
3507 SilcUInt32 umode = 0;
3508 bool created = FALSE, create_key = TRUE;
3509 SilcClientID *client_id;
3511 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3513 /* Get channel name */
3514 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3516 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3517 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3524 channel_name[255] = '\0';
3526 if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
3527 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3528 SILC_STATUS_ERR_BAD_CHANNEL, 0);
3532 /* Get Client ID of the client who is joining to the channel */
3533 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3535 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3536 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3540 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3542 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3543 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3548 /* Get cipher, hmac name and auth payload */
3549 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3550 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3551 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3553 /* See if the channel exists */
3554 channel = silc_idlist_find_channel_by_name(server->local_list,
3555 channel_name, NULL);
3557 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3558 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3559 silc_free(client_id);
3560 client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
3563 (channel->disabled && server->server_type != SILC_ROUTER)) {
3564 /* Channel not found */
3566 /* If we are standalone server we don't have a router, we just create
3567 the channel by ourselves. */
3568 if (server->standalone) {
3569 channel = silc_server_create_new_channel(server, server->id, cipher,
3570 hmac, channel_name, TRUE);
3572 silc_server_command_send_status_reply(
3573 cmd, SILC_COMMAND_JOIN,
3574 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
3576 silc_free(client_id);
3580 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3586 /* The channel does not exist on our server. If we are normal server
3587 we will send JOIN command to our router which will handle the
3588 joining procedure (either creates the channel if it doesn't exist
3589 or joins the client to it). */
3590 if (server->server_type != SILC_ROUTER) {
3592 SilcUInt16 old_ident;
3594 /* If this is pending command callback then we've resolved
3595 it and it didn't work, return since we've notified the
3596 client already in the command reply callback. */
3598 silc_free(client_id);
3602 old_ident = silc_command_get_ident(cmd->payload);
3603 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3604 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3606 /* Send JOIN command to our router */
3607 silc_server_packet_send(server, (SilcSocketConnection)
3608 SILC_PRIMARY_ROUTE(server),
3609 SILC_PACKET_COMMAND, cmd->packet->flags,
3610 tmpbuf->data, tmpbuf->len, TRUE);
3612 /* Reprocess this packet after received reply from router */
3613 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3614 silc_command_get_ident(cmd->payload),
3615 silc_server_command_join,
3616 silc_server_command_dup(cmd));
3617 cmd->pending = TRUE;
3618 silc_command_set_ident(cmd->payload, old_ident);
3619 silc_buffer_free(tmpbuf);
3620 silc_free(client_id);
3624 /* We are router and the channel does not seem exist so we will check
3625 our global list as well for the channel. */
3626 channel = silc_idlist_find_channel_by_name(server->global_list,
3627 channel_name, NULL);
3629 /* Channel really does not exist, create it */
3630 channel = silc_server_create_new_channel(server, server->id, cipher,
3631 hmac, channel_name, TRUE);
3633 silc_server_command_send_status_reply(
3634 cmd, SILC_COMMAND_JOIN,
3635 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
3636 silc_free(client_id);
3640 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3648 /* Channel not found */
3650 /* If the command came from router and we are normal server then
3651 something went wrong with the joining as the channel was not found.
3652 We can't do anything else but ignore this. */
3653 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3654 server->server_type != SILC_ROUTER) {
3655 silc_free(client_id);
3659 /* We are router and the channel does not seem exist so we will check
3660 our global list as well for the channel. */
3661 channel = silc_idlist_find_channel_by_name(server->global_list,
3662 channel_name, NULL);
3664 /* Channel really does not exist, create it */
3665 channel = silc_server_create_new_channel(server, server->id, cipher,
3666 hmac, channel_name, TRUE);
3668 silc_server_command_send_status_reply(
3669 cmd, SILC_COMMAND_JOIN,
3670 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
3671 silc_free(client_id);
3675 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3682 /* Check whether the channel was created by our router */
3683 if (cmd->pending && context2) {
3684 SilcServerCommandReplyContext reply = context2;
3686 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3687 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3688 SILC_GET32_MSB(created, tmp);
3689 if (silc_argument_get_arg_type(reply->args, 7, NULL))
3690 create_key = FALSE; /* Router returned the key already */
3692 if (silc_command_get_status(reply->payload, NULL, NULL) &&
3693 channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3694 /* Save channel passphrase, if user provided it successfully */
3697 pa = silc_argument_get_arg_type(cmd->args, 3, &pa_len);
3699 silc_free(channel->passphrase);
3700 channel->passphrase = silc_memdup(pa, pa_len);
3705 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
3706 !channel->disabled && !silc_hash_table_count(channel->user_list))
3710 /* If the channel does not have global users and is also empty the client
3711 will be the channel founder and operator. */
3712 if (!channel->disabled &&
3713 !channel->global_users && !silc_hash_table_count(channel->user_list))
3714 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3716 /* Join to the channel */
3717 silc_server_command_join_channel(server, cmd, channel, client_id,
3718 created, create_key, umode,
3721 silc_free(client_id);
3724 silc_server_command_free(cmd);
3727 /* Server side of command MOTD. Sends server's current "message of the
3728 day" to the client. */
3730 SILC_SERVER_CMD_FUNC(motd)
3732 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3733 SilcServer server = cmd->server;
3734 SilcBuffer packet, idp;
3735 char *motd, *dest_server;
3736 SilcUInt32 motd_len;
3737 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3739 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3741 /* Get server name */
3742 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3744 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3745 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3749 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3752 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3754 if (server->config && server->config->server_info &&
3755 server->config->server_info->motd_file) {
3757 motd = silc_file_readfile(server->config->server_info->motd_file,
3763 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3770 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3776 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3777 packet->data, packet->len, FALSE);
3778 silc_buffer_free(packet);
3779 silc_buffer_free(idp);
3781 SilcServerEntry entry;
3783 /* Check whether we have this server cached */
3784 entry = silc_idlist_find_server_by_name(server->global_list,
3785 dest_server, TRUE, NULL);
3787 entry = silc_idlist_find_server_by_name(server->local_list,
3788 dest_server, TRUE, NULL);
3791 if (server->server_type != SILC_SERVER && !cmd->pending &&
3792 entry && !entry->motd) {
3793 /* Send to the server */
3795 SilcUInt16 old_ident;
3797 old_ident = silc_command_get_ident(cmd->payload);
3798 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3799 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3801 silc_server_packet_send(server, entry->connection,
3802 SILC_PACKET_COMMAND, cmd->packet->flags,
3803 tmpbuf->data, tmpbuf->len, TRUE);
3805 /* Reprocess this packet after received reply from router */
3806 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3807 silc_command_get_ident(cmd->payload),
3808 silc_server_command_motd,
3809 silc_server_command_dup(cmd));
3810 cmd->pending = TRUE;
3811 silc_command_set_ident(cmd->payload, old_ident);
3812 silc_buffer_free(tmpbuf);
3816 if (!entry && !cmd->pending && !server->standalone) {
3817 /* Send to the primary router */
3819 SilcUInt16 old_ident;
3821 old_ident = silc_command_get_ident(cmd->payload);
3822 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3823 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3825 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
3826 SILC_PACKET_COMMAND, cmd->packet->flags,
3827 tmpbuf->data, tmpbuf->len, TRUE);
3829 /* Reprocess this packet after received reply from router */
3830 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3831 silc_command_get_ident(cmd->payload),
3832 silc_server_command_motd,
3833 silc_server_command_dup(cmd));
3834 cmd->pending = TRUE;
3835 silc_command_set_ident(cmd->payload, old_ident);
3836 silc_buffer_free(tmpbuf);
3841 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3842 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3846 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3847 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3848 SILC_STATUS_OK, 0, ident, 2,
3852 strlen(entry->motd) : 0);
3853 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3854 packet->data, packet->len, FALSE);
3855 silc_buffer_free(packet);
3856 silc_buffer_free(idp);
3860 silc_server_command_free(cmd);
3863 /* Server side of command UMODE. Client can use this command to set/unset
3864 user mode. Client actually cannot set itself to be as server/router
3865 operator so this can be used only to unset the modes. */
3867 SILC_SERVER_CMD_FUNC(umode)
3869 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3870 SilcServer server = cmd->server;
3871 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3873 unsigned char *tmp_mask, m[4];
3874 SilcUInt32 mask = 0;
3875 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3876 bool set_mask = FALSE;
3878 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3881 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2);
3883 /* Get the client's mode mask */
3884 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3886 SILC_GET32_MSB(mask, tmp_mask);
3891 /* Check that mode changing is allowed. */
3892 if (!silc_server_check_umode_rights(server, client, mask)) {
3893 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3894 SILC_STATUS_ERR_PERM_DENIED, 0);
3898 /* Anonymous mode cannot be set by client */
3899 if (mask & SILC_UMODE_ANONYMOUS) {
3900 if (!(client->mode & SILC_UMODE_ANONYMOUS)) {
3901 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3902 SILC_STATUS_ERR_PERM_DENIED, 0);
3906 if (client->mode & SILC_UMODE_ANONYMOUS) {
3907 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3908 SILC_STATUS_ERR_PERM_DENIED, 0);
3913 /* Update statistics */
3914 if (mask & SILC_UMODE_GONE) {
3915 if (!(client->mode & SILC_UMODE_GONE))
3916 server->stat.my_aways++;
3918 if (client->mode & SILC_UMODE_GONE)
3919 server->stat.my_aways--;
3922 /* Change the mode */
3923 client->mode = mask;
3925 /* Send UMODE change to primary router */
3926 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
3927 SILC_BROADCAST(server), client->id,
3930 /* Check if anyone is watching this nickname */
3931 if (server->server_type == SILC_ROUTER)
3932 silc_server_check_watcher_list(server, client, NULL,
3933 SILC_NOTIFY_TYPE_UMODE_CHANGE);
3936 /* Send command reply to sender */
3937 SILC_PUT32_MSB(client->mode, m);
3938 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3939 SILC_STATUS_OK, 0, ident, 1,
3941 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3942 packet->data, packet->len, FALSE);
3943 silc_buffer_free(packet);
3946 silc_server_command_free(cmd);
3949 /* Server side command of CMODE. Changes channel mode */
3951 SILC_SERVER_CMD_FUNC(cmode)
3953 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3954 SilcServer server = cmd->server;
3955 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3956 SilcIDListData idata = (SilcIDListData)client;
3957 SilcChannelID *channel_id = NULL;
3958 SilcChannelEntry channel;
3959 SilcChannelClientEntry chl;
3960 SilcBuffer packet, cidp;
3961 unsigned char *tmp, *tmp_id, *tmp_mask;
3962 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3963 SilcUInt32 mode_mask = 0, old_mask = 0, tmp_len, tmp_len2;
3964 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3965 bool set_mask = FALSE;
3966 SilcPublicKey founder_key = NULL;
3967 unsigned char *fkey = NULL;
3968 SilcUInt32 fkey_len = 0;
3970 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 7);
3972 /* Get Channel ID */
3973 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3975 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3976 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3977 silc_server_command_free(cmd);
3980 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
3982 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3983 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3984 silc_server_command_free(cmd);
3988 /* Get channel entry */
3989 channel = silc_idlist_find_channel_by_id(server->local_list,
3992 channel = silc_idlist_find_channel_by_id(server->global_list,
3995 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3996 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
3998 silc_free(channel_id);
3999 silc_server_command_free(cmd);
4003 old_mask = channel->mode;
4005 /* Get the channel mode mask */
4006 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4008 SILC_GET32_MSB(mode_mask, tmp_mask);
4012 /* Check whether this client is on the channel */
4013 if (!silc_server_client_on_channel(client, channel, &chl)) {
4014 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4015 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4019 /* Check that client has rights to change any requested channel modes */
4020 if (set_mask && !silc_server_check_cmode_rights(server, channel, chl,
4022 SILC_LOG_DEBUG(("Client does not have rights to change mode"));
4023 silc_server_command_send_status_reply(
4024 cmd, SILC_COMMAND_CMODE,
4025 (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) ?
4026 SILC_STATUS_ERR_NO_CHANNEL_PRIV :
4027 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV), 0);
4031 /* If mode mask was not sent as argument then merely return the current
4032 mode mask to the sender. */
4035 SILC_PUT32_MSB(channel->mode, m);
4036 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4037 SILC_STATUS_OK, 0, ident, 2,
4038 2, tmp_id, tmp_len2,
4040 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4041 packet->data, packet->len, FALSE);
4042 silc_buffer_free(packet);
4047 * Check the modes. Modes that requires nothing special operation are
4051 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
4052 /* Channel uses private keys to protect traffic. Client(s) has set the
4053 key locally they want to use, server does not know that key. */
4054 /* Nothing interesting to do here */
4056 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
4057 /* The mode is removed and we need to generate and distribute
4058 new channel key. Clients are not using private channel keys
4059 anymore after this. */
4061 /* Re-generate channel key */
4062 if (!silc_server_create_channel_key(server, channel, 0))
4065 /* Send the channel key. This sends it to our local clients and if
4066 we are normal server to our router as well. */
4067 silc_server_send_channel_key(server, NULL, channel,
4068 server->server_type == SILC_ROUTER ?
4069 FALSE : !server->standalone);
4071 cipher = channel->channel_key->cipher->name;
4072 hmac = (char *)silc_hmac_get_name(channel->hmac);
4076 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
4077 /* User limit is set on channel */
4078 SilcUInt32 user_limit;
4080 /* Get user limit */
4081 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
4083 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
4084 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4085 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4089 SILC_GET32_MSB(user_limit, tmp);
4090 channel->user_limit = user_limit;
4093 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
4094 /* User limit mode is unset. Remove user limit */
4095 channel->user_limit = 0;
4098 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
4099 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
4100 /* Passphrase has been set to channel */
4102 /* Get the passphrase */
4103 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
4105 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4106 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4110 /* Save the passphrase */
4111 passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
4114 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
4115 /* Passphrase mode is unset. remove the passphrase */
4116 silc_free(channel->passphrase);
4117 channel->passphrase = NULL;
4121 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
4122 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
4123 /* Cipher to use protect the traffic */
4124 SilcCipher newkey, oldkey;
4127 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
4129 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4130 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4134 /* Delete old cipher and allocate the new one */
4135 if (!silc_cipher_alloc(cipher, &newkey)) {
4136 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4137 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4141 oldkey = channel->channel_key;
4142 channel->channel_key = newkey;
4144 /* Re-generate channel key */
4145 if (!silc_server_create_channel_key(server, channel, 0)) {
4146 /* We don't have new key, revert to old one */
4147 channel->channel_key = oldkey;
4151 /* Remove old channel key for good */
4152 silc_cipher_free(oldkey);
4154 /* Send the channel key. This sends it to our local clients and if
4155 we are normal server to our router as well. */
4156 silc_server_send_channel_key(server, NULL, channel,
4157 server->server_type == SILC_ROUTER ?
4158 FALSE : !server->standalone);
4161 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
4162 /* Cipher mode is unset. Remove the cipher and revert back to
4164 SilcCipher newkey, oldkey;
4165 cipher = channel->cipher;
4167 /* Delete old cipher and allocate default one */
4168 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
4169 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4170 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4174 oldkey = channel->channel_key;
4175 channel->channel_key = newkey;
4177 /* Re-generate channel key */
4178 if (!silc_server_create_channel_key(server, channel, 0)) {
4179 /* We don't have new key, revert to old one */
4180 channel->channel_key = oldkey;
4184 /* Remove old channel key for good */
4185 silc_cipher_free(oldkey);
4187 /* Send the channel key. This sends it to our local clients and if
4188 we are normal server to our router as well. */
4189 silc_server_send_channel_key(server, NULL, channel,
4190 server->server_type == SILC_ROUTER ?
4191 FALSE : !server->standalone);
4195 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
4196 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
4197 /* HMAC to use protect the traffic */
4198 unsigned char hash[32];
4202 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4204 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4205 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4209 /* Delete old hmac and allocate the new one */
4210 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4211 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4212 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4216 silc_hmac_free(channel->hmac);
4217 channel->hmac = newhmac;
4219 /* Set the HMAC key out of current channel key. The client must do
4221 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4222 channel->key_len / 8, hash);
4223 silc_hmac_set_key(channel->hmac, hash,
4224 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4225 memset(hash, 0, sizeof(hash));
4228 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4229 /* Hmac mode is unset. Remove the hmac and revert back to
4232 unsigned char hash[32];
4233 hmac = channel->hmac_name;
4235 /* Delete old hmac and allocate default one */
4236 silc_hmac_free(channel->hmac);
4237 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4238 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4239 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4243 silc_hmac_free(channel->hmac);
4244 channel->hmac = newhmac;
4246 /* Set the HMAC key out of current channel key. The client must do
4248 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4249 channel->key_len / 8,
4251 silc_hmac_set_key(channel->hmac, hash,
4252 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4253 memset(hash, 0, sizeof(hash));
4257 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4258 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4259 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4260 /* Set the founder authentication */
4261 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4263 silc_server_command_send_status_reply(
4264 cmd, SILC_COMMAND_CMODE,
4265 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4269 /* Verify the payload before setting the mode */
4270 if (!silc_auth_verify_data(tmp, tmp_len, SILC_AUTH_PUBLIC_KEY,
4271 idata->public_key, 0, server->sha1hash,
4272 client->id, SILC_ID_CLIENT)) {
4273 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4274 SILC_STATUS_ERR_AUTH_FAILED,
4279 /* Save the public key */
4280 channel->founder_key = silc_pkcs_public_key_copy(idata->public_key);
4281 if (!channel->founder_key) {
4282 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4283 SILC_STATUS_ERR_AUTH_FAILED,
4288 founder_key = channel->founder_key;
4289 fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
4291 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4292 SILC_STATUS_ERR_AUTH_FAILED,
4294 silc_pkcs_public_key_free(channel->founder_key);
4295 channel->founder_key = NULL;
4301 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4302 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4303 if (channel->founder_key)
4304 silc_pkcs_public_key_free(channel->founder_key);
4305 channel->founder_key = NULL;
4310 /* Finally, set the mode */
4311 old_mask = channel->mode = mode_mask;
4313 /* Send CMODE_CHANGE notify. */
4314 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4315 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4316 SILC_NOTIFY_TYPE_CMODE_CHANGE, 6,
4317 cidp->data, cidp->len,
4319 cipher, cipher ? strlen(cipher) : 0,
4320 hmac, hmac ? strlen(hmac) : 0,
4321 passphrase, passphrase ?
4322 strlen(passphrase) : 0,
4325 /* Set CMODE notify type to network */
4326 silc_server_send_notify_cmode(server, SILC_PRIMARY_ROUTE(server),
4327 SILC_BROADCAST(server), channel,
4328 mode_mask, client->id, SILC_ID_CLIENT,
4329 cipher, hmac, passphrase, founder_key);
4331 /* Send command reply to sender */
4332 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4333 SILC_STATUS_OK, 0, ident, 2,
4334 2, tmp_id, tmp_len2,
4336 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4337 packet->data, packet->len, FALSE);
4339 silc_buffer_free(packet);
4340 silc_buffer_free(cidp);
4343 channel->mode = old_mask;
4345 silc_free(channel_id);
4346 silc_server_command_free(cmd);
4349 /* Server side of CUMODE command. Changes client's mode on a channel. */
4351 SILC_SERVER_CMD_FUNC(cumode)
4353 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4354 SilcServer server = cmd->server;
4355 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4356 SilcIDListData idata = (SilcIDListData)client;
4357 SilcChannelID *channel_id;
4358 SilcClientID *client_id;
4359 SilcChannelEntry channel;
4360 SilcClientEntry target_client;
4361 SilcChannelClientEntry chl;
4362 SilcBuffer packet, idp;
4363 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4364 SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4366 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4367 SilcPublicKey founder_key = NULL;
4368 unsigned char *fkey = NULL;
4369 SilcUInt32 fkey_len = 0;
4371 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4373 /* Get Channel ID */
4374 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4376 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4377 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4380 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
4382 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4383 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4387 /* Get channel entry */
4388 channel = silc_idlist_find_channel_by_id(server->local_list,
4391 channel = silc_idlist_find_channel_by_id(server->global_list,
4394 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4395 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4401 /* Check whether sender is on the channel */
4402 if (!silc_server_client_on_channel(client, channel, &chl)) {
4403 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4404 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4407 sender_mask = chl->mode;
4409 /* Get the target client's channel mode mask */
4410 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4412 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4413 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4417 SILC_GET32_MSB(target_mask, tmp_mask);
4419 /* Get target Client ID */
4420 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4422 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4423 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4426 client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
4428 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4429 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4433 /* Get target client's entry */
4434 target_client = silc_idlist_find_client_by_id(server->local_list,
4435 client_id, TRUE, NULL);
4436 if (!target_client) {
4437 target_client = silc_idlist_find_client_by_id(server->global_list,
4438 client_id, TRUE, NULL);
4441 if (target_client != client &&
4442 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4443 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4444 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4445 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
4449 /* Check whether target client is on the channel */
4450 if (target_client != client) {
4451 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4452 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4453 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL, 0);
4462 /* If the target client is founder, no one else can change their mode
4464 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4465 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4466 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
4471 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4472 if (target_client != client) {
4473 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4474 SILC_STATUS_ERR_NOT_YOU, 0);
4478 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4479 /* The client tries to claim the founder rights. */
4480 unsigned char *tmp_auth;
4481 SilcUInt32 tmp_auth_len;
4482 SilcChannelClientEntry chl2;
4483 SilcHashTableList htl;
4485 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4486 !channel->founder_key || !idata->public_key ||
4487 !silc_pkcs_public_key_compare(channel->founder_key,
4488 idata->public_key)) {
4489 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4490 SILC_STATUS_ERR_AUTH_FAILED, 0);
4494 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4496 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4497 SILC_STATUS_ERR_AUTH_FAILED, 0);
4501 /* Verify the authentication payload */
4502 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len, SILC_AUTH_PUBLIC_KEY,
4503 channel->founder_key, 0, server->sha1hash,
4504 client->id, SILC_ID_CLIENT)) {
4505 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4506 SILC_STATUS_ERR_AUTH_FAILED, 0);
4511 founder_key = channel->founder_key;
4512 fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
4514 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4515 SILC_STATUS_ERR_AUTH_FAILED, 0);
4519 /* There cannot be anyone else as founder on the channel now. This
4520 client is definitely the founder due to this authentication */
4521 silc_hash_table_list(channel->user_list, &htl);
4522 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
4523 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
4524 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4525 silc_server_force_cumode_change(server, NULL, channel, chl2,
4529 silc_hash_table_list_reset(&htl);
4531 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4534 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4535 if (target_client == client) {
4536 /* Remove channel founder rights from itself */
4537 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4540 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4541 SILC_STATUS_ERR_NOT_YOU, 0);
4547 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4548 /* Promote to operator */
4549 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4550 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4551 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4552 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4553 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
4558 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4562 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4563 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4564 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4565 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4566 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
4571 /* Demote to normal user */
4572 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4577 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4578 if (target_client != client) {
4579 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4580 SILC_STATUS_ERR_NOT_YOU, 0);
4584 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
4585 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4589 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4590 if (target_client != client) {
4591 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4592 SILC_STATUS_ERR_NOT_YOU, 0);
4596 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4601 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4602 if (target_client != client) {
4603 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4604 SILC_STATUS_ERR_NOT_YOU, 0);
4608 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)) {
4609 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4613 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4614 if (target_client != client) {
4615 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4616 SILC_STATUS_ERR_NOT_YOU, 0);
4620 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4625 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4626 if (target_client != client) {
4627 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4628 SILC_STATUS_ERR_NOT_YOU, 0);
4632 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)) {
4633 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4637 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4638 if (target_client != client) {
4639 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4640 SILC_STATUS_ERR_NOT_YOU, 0);
4644 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4649 if (target_mask & SILC_CHANNEL_UMODE_QUIET) {
4650 if (!(chl->mode & SILC_CHANNEL_UMODE_QUIET)) {
4651 if (client == target_client) {
4652 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4653 SILC_STATUS_ERR_PERM_DENIED, 0);
4656 chl->mode |= SILC_CHANNEL_UMODE_QUIET;
4660 if (chl->mode & SILC_CHANNEL_UMODE_QUIET) {
4661 if (client == target_client) {
4662 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4663 SILC_STATUS_ERR_PERM_DENIED, 0);
4666 chl->mode &= ~SILC_CHANNEL_UMODE_QUIET;
4671 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4672 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4674 /* Send notify to channel, notify only if mode was actually changed. */
4676 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4677 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
4678 idp->data, idp->len,
4683 /* Set CUMODE notify type to network */
4684 silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
4685 SILC_BROADCAST(server), channel,
4686 target_mask, client->id, SILC_ID_CLIENT,
4687 target_client->id, founder_key);
4690 /* Send command reply to sender */
4691 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4692 SILC_STATUS_OK, 0, ident, 3,
4694 3, tmp_ch_id, tmp_ch_len,
4695 4, tmp_id, tmp_len);
4696 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4697 packet->data, packet->len, FALSE);
4699 silc_buffer_free(packet);
4700 silc_free(channel_id);
4701 silc_free(client_id);
4702 silc_buffer_free(idp);
4706 silc_server_command_free(cmd);
4709 /* Server side of KICK command. Kicks client out of channel. */
4711 SILC_SERVER_CMD_FUNC(kick)
4713 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4714 SilcServer server = cmd->server;
4715 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4716 SilcClientEntry target_client;
4717 SilcChannelID *channel_id;
4718 SilcClientID *client_id;
4719 SilcChannelEntry channel;
4720 SilcChannelClientEntry chl;
4722 SilcUInt32 tmp_len, target_idp_len;
4723 unsigned char *tmp, *comment, *target_idp;
4725 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4727 /* Get Channel ID */
4728 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4730 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4731 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4734 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4736 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4737 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4741 /* Get channel entry */
4742 channel = silc_idlist_find_channel_by_id(server->local_list,
4745 channel = silc_idlist_find_channel_by_id(server->local_list,
4748 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4749 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4755 /* Check whether sender is on the channel */
4756 if (!silc_server_client_on_channel(client, channel, &chl)) {
4757 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4758 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4762 /* Check that the kicker is channel operator or channel founder */
4763 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
4764 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4765 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4766 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
4770 /* Get target Client ID */
4771 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4773 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4774 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4777 client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
4779 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4780 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4784 /* Get target client's entry */
4785 target_client = silc_idlist_find_client_by_id(server->local_list,
4786 client_id, TRUE, NULL);
4787 if (!target_client) {
4788 target_client = silc_idlist_find_client_by_id(server->global_list,
4789 client_id, TRUE, NULL);
4792 /* Check whether target client is on the channel */
4793 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4794 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4795 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL,
4800 /* Check that the target client is not channel founder. Channel founder
4801 cannot be kicked from the channel. */
4802 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4803 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4804 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
4811 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4815 /* Send command reply to sender */
4816 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4819 /* Send KICKED notify to local clients on the channel */
4820 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4821 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4822 SILC_NOTIFY_TYPE_KICKED, 3,
4823 target_idp, target_idp_len,
4824 comment, comment ? strlen(comment) : 0,
4825 idp->data, idp->len);
4826 silc_buffer_free(idp);
4828 /* Send KICKED notify to primary route */
4829 silc_server_send_notify_kicked(server, SILC_PRIMARY_ROUTE(server),
4830 SILC_BROADCAST(server), channel,
4831 target_client->id, client->id, comment);
4833 /* Remove the client from the channel. If the channel does not exist
4834 after removing the client then the client kicked itself off the channel
4835 and we don't have to send anything after that. */
4836 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4837 target_client, FALSE))
4840 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4841 /* Re-generate channel key */
4842 if (!silc_server_create_channel_key(server, channel, 0))
4845 /* Send the channel key to the channel. The key of course is not sent
4846 to the client who was kicked off the channel. */
4847 silc_server_send_channel_key(server, target_client->connection, channel,
4848 server->server_type == SILC_ROUTER ?
4849 FALSE : !server->standalone);
4853 silc_server_command_free(cmd);
4856 /* Server side of OPER command. Client uses this comand to obtain server
4857 operator privileges to this server/router. */
4859 SILC_SERVER_CMD_FUNC(oper)
4861 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4862 SilcServer server = cmd->server;
4863 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4864 unsigned char *username, *auth;
4866 SilcServerConfigAdmin *admin;
4867 SilcIDListData idata = (SilcIDListData)client;
4868 bool result = FALSE;
4869 SilcPublicKey cached_key;
4871 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4873 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4876 /* Get the username */
4877 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4879 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4880 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4885 /* Get the admin configuration */
4886 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4887 username, client->nickname);
4889 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4890 username, client->nickname);
4892 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4893 SILC_STATUS_ERR_AUTH_FAILED,
4899 /* Get the authentication payload */
4900 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4902 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4903 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4908 /* Verify the authentication data. If both passphrase and public key
4909 is set then try both of them. */
4910 if (admin->passphrase)
4911 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4912 admin->passphrase, admin->passphrase_len,
4913 idata->hash, client->id, SILC_ID_CLIENT);
4914 if (!result && admin->publickeys) {
4915 cached_key = silc_server_get_public_key(server, admin->publickeys);
4918 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4919 cached_key, 0, idata->hash,
4920 client->id, SILC_ID_CLIENT);
4923 /* Authentication failed */
4924 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4925 SILC_STATUS_ERR_AUTH_FAILED,
4930 /* Client is now server operator */
4931 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4933 /* Update statistics */
4934 if (SILC_IS_LOCAL(client))
4935 server->stat.my_server_ops++;
4936 if (server->server_type == SILC_ROUTER)
4937 server->stat.server_ops++;
4939 /* Send UMODE change to primary router */
4940 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
4941 SILC_BROADCAST(server), client->id,
4944 /* Check if anyone is watching this nickname */
4945 if (server->server_type == SILC_ROUTER)
4946 silc_server_check_watcher_list(server, client, NULL,
4947 SILC_NOTIFY_TYPE_UMODE_CHANGE);
4949 /* Send reply to the sender */
4950 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4954 silc_server_command_free(cmd);
4957 SILC_TASK_CALLBACK(silc_server_command_detach_cb)
4959 QuitInternal q = (QuitInternal)context;
4960 SilcClientID *client_id = (SilcClientID *)q->sock;
4961 SilcClientEntry client;
4962 SilcSocketConnection sock;
4964 client = silc_idlist_find_client_by_id(q->server->local_list, client_id,
4966 if (client && client->connection) {
4967 sock = client->connection;
4969 /* If there is pending outgoing data for the client then purge it
4970 to the network before closing connection. */
4971 silc_server_packet_queue_purge(q->server, sock);
4973 /* Close the connection on our side */
4974 client->router = NULL;
4975 client->connection = NULL;
4976 sock->user_data = NULL;
4977 silc_server_close_connection(q->server, sock);
4980 silc_free(client_id);
4984 SILC_TASK_CALLBACK(silc_server_command_detach_timeout)
4986 QuitInternal q = (QuitInternal)context;
4987 SilcClientID *client_id = (SilcClientID *)q->sock;
4988 SilcClientEntry client;
4990 client = silc_idlist_find_client_by_id(q->server->local_list, client_id,
4992 if (client && client->mode & SILC_UMODE_DETACHED) {
4993 SILC_LOG_DEBUG(("Detach timeout"));
4994 silc_server_free_client_data(q->server, NULL, client, TRUE,
4998 silc_free(client_id);
5002 /* Server side of DETACH command. Detached the client from the network
5003 by closing the connection but preserving the session. */
5005 SILC_SERVER_CMD_FUNC(detach)
5007 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5008 SilcServer server = cmd->server;
5009 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5012 if (server->config->detach_disabled) {
5013 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
5014 SILC_STATUS_ERR_UNKNOWN_COMMAND, 0);
5018 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5021 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
5023 /* Remove operator privileges, since the client may resume in some
5024 other server which to it does not have operator privileges. */
5025 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
5026 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
5028 /* Send the user mode notify to notify that client is detached */
5029 client->mode |= SILC_UMODE_DETACHED;
5030 client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
5031 client->last_command = 0;
5032 client->fast_command = 0;
5033 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
5034 SILC_BROADCAST(server), client->id,
5036 server->stat.my_detached++;
5038 /* Check if anyone is watching this nickname */
5039 if (server->server_type == SILC_ROUTER)
5040 silc_server_check_watcher_list(server, client, NULL,
5041 SILC_NOTIFY_TYPE_UMODE_CHANGE);
5043 q = silc_calloc(1, sizeof(*q));
5045 q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
5046 silc_schedule_task_add(server->schedule, 0, silc_server_command_detach_cb,
5047 q, 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
5049 if (server->config->detach_timeout) {
5050 q = silc_calloc(1, sizeof(*q));
5052 q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
5053 silc_schedule_task_add(server->schedule, 0,
5054 silc_server_command_detach_timeout,
5055 q, server->config->detach_timeout * 60,
5056 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
5059 /* Send reply to the sender */
5060 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
5064 silc_server_command_free(cmd);
5067 /* Server side of WATCH command. */
5069 SILC_SERVER_CMD_FUNC(watch)
5071 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5072 SilcServer server = cmd->server;
5073 char *add_nick, *del_nick;
5074 SilcUInt32 add_nick_len, del_nick_len, tmp_len;
5076 unsigned char hash[16], *tmp;
5077 SilcClientEntry client;
5078 SilcClientID *client_id = NULL;
5080 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WATCH, cmd, 1, 3);
5082 if (server->server_type == SILC_SERVER && !server->standalone) {
5083 if (!cmd->pending) {
5084 /* Send the command to router */
5086 SilcUInt16 old_ident;
5088 old_ident = silc_command_get_ident(cmd->payload);
5089 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5090 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5092 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5093 SILC_PACKET_COMMAND, cmd->packet->flags,
5094 tmpbuf->data, tmpbuf->len, TRUE);
5096 /* Reprocess this packet after received reply from router */
5097 silc_server_command_pending(server, SILC_COMMAND_WATCH,
5098 silc_command_get_ident(cmd->payload),
5099 silc_server_command_watch,
5100 silc_server_command_dup(cmd));
5101 cmd->pending = TRUE;
5102 silc_command_set_ident(cmd->payload, old_ident);
5103 silc_buffer_free(tmpbuf);
5104 } else if (context2) {
5105 /* Received reply from router, just send same data to the client. */
5106 SilcServerCommandReplyContext reply = context2;
5108 silc_command_get_status(reply->payload, &status, NULL);
5109 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, status,
5116 /* We are router and keep the watch list for local cell */
5118 /* Get the client ID */
5119 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5121 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5122 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5126 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
5128 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5129 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5134 /* Get the client entry which must be in local list */
5135 client = silc_idlist_find_client_by_id(server->local_list,
5136 client_id, TRUE, NULL);
5138 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5139 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5145 add_nick = silc_argument_get_arg_type(cmd->args, 2, &add_nick_len);
5146 del_nick = silc_argument_get_arg_type(cmd->args, 3, &del_nick_len);
5147 if (!add_nick && !del_nick) {
5148 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5149 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5154 if (add_nick && add_nick_len > 128)
5155 add_nick[128] = '\0';
5156 if (del_nick && del_nick_len > 128)
5157 del_nick[128] = '\0';
5159 memset(nick, 0, sizeof(nick));
5161 /* Add new nickname to be watched in our cell */
5163 if (silc_server_name_bad_chars(add_nick, strlen(add_nick)) == TRUE) {
5164 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5165 SILC_STATUS_ERR_BAD_NICKNAME, 0);
5169 /* Hash the nick, we have the hash saved, not nicks because we can
5170 do one to one mapping to the nick from Client ID hash this way. */
5171 silc_to_lower(add_nick, nick, sizeof(nick) - 1);
5172 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
5174 /* Check whether this client is already watching this nickname */
5175 if (silc_hash_table_find_by_context(server->watcher_list, hash,
5177 /* Nickname is alredy being watched for this client */
5178 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5179 SILC_STATUS_ERR_NICKNAME_IN_USE,
5184 /* Get the nickname from the watcher list and use the same key in
5185 new entries as well. If key doesn't exist then create it. */
5186 if (!silc_hash_table_find(server->watcher_list, hash, (void **)&tmp, NULL))
5187 tmp = silc_memdup(hash, CLIENTID_HASH_LEN);
5189 /* Add the client to the watcher list with the specified nickname hash. */
5190 silc_hash_table_add(server->watcher_list, tmp, client);
5193 /* Delete nickname from watch list */
5195 if (silc_server_name_bad_chars(del_nick, strlen(del_nick)) == TRUE) {
5196 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5197 SILC_STATUS_ERR_BAD_NICKNAME, 0);
5201 /* Hash the nick, we have the hash saved, not nicks because we can
5202 do one to one mapping to the nick from Client ID hash this way. */
5203 silc_to_lower(del_nick, nick, sizeof(nick) - 1);
5204 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
5206 /* Check that this client is watching for this nickname */
5207 if (!silc_hash_table_find_by_context(server->watcher_list, hash,
5208 client, (void **)&tmp)) {
5209 /* Nickname is alredy being watched for this client */
5210 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5211 SILC_STATUS_ERR_NO_SUCH_NICK, 0);
5215 /* Delete the nickname from the watcher list. */
5216 silc_hash_table_del_by_context(server->watcher_list, hash, client);
5218 /* Now check whether there still exists entries with this key, if not
5219 then free the key to not leak memory. */
5220 if (!silc_hash_table_find(server->watcher_list, hash, NULL, NULL))
5224 /* Distribute the watch list to backup routers too */
5225 if (server->backup) {
5227 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5228 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5229 silc_server_backup_send(server, NULL, SILC_PACKET_COMMAND,
5230 cmd->packet->flags, tmpbuf->data, tmpbuf->len,
5232 silc_buffer_free(tmpbuf);
5235 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5239 silc_free(client_id);
5240 silc_server_command_free(cmd);
5243 /* Server side of SILCOPER command. Client uses this comand to obtain router
5244 operator privileges to this router. */
5246 SILC_SERVER_CMD_FUNC(silcoper)
5248 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5249 SilcServer server = cmd->server;
5250 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5251 unsigned char *username, *auth;
5253 SilcServerConfigAdmin *admin;
5254 SilcIDListData idata = (SilcIDListData)client;
5255 bool result = FALSE;
5256 SilcPublicKey cached_key;
5258 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
5260 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5263 if (server->server_type != SILC_ROUTER) {
5264 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5265 SILC_STATUS_ERR_AUTH_FAILED, 0);
5269 /* Get the username */
5270 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5272 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5273 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5278 /* Get the admin configuration */
5279 admin = silc_server_config_find_admin(server, cmd->sock->ip,
5280 username, client->nickname);
5282 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
5283 username, client->nickname);
5285 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5286 SILC_STATUS_ERR_AUTH_FAILED, 0);
5291 /* Get the authentication payload */
5292 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5294 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5295 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5300 /* Verify the authentication data. If both passphrase and public key
5301 is set then try both of them. */
5302 if (admin->passphrase)
5303 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
5304 admin->passphrase, admin->passphrase_len,
5305 idata->hash, client->id, SILC_ID_CLIENT);
5306 if (!result && admin->publickeys) {
5307 cached_key = silc_server_get_public_key(server, admin->publickeys);
5310 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
5311 cached_key, 0, idata->hash,
5312 client->id, SILC_ID_CLIENT);
5315 /* Authentication failed */
5316 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
5317 SILC_STATUS_ERR_AUTH_FAILED, 0);
5321 /* Client is now router operator */
5322 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
5324 /* Update statistics */
5325 if (SILC_IS_LOCAL(client))
5326 server->stat.my_router_ops++;
5327 if (server->server_type == SILC_ROUTER)
5328 server->stat.router_ops++;
5330 /* Send UMODE change to primary router */
5331 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
5332 SILC_BROADCAST(server), client->id,
5335 /* Check if anyone is watching this nickname */
5336 if (server->server_type == SILC_ROUTER)
5337 silc_server_check_watcher_list(server, client, NULL,
5338 SILC_NOTIFY_TYPE_UMODE_CHANGE);
5340 /* Send reply to the sender */
5341 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5345 silc_server_command_free(cmd);
5348 /* Server side of command BAN. This is used to manage the ban list of the
5349 channel. To add clients and remove clients from the ban list. */
5351 SILC_SERVER_CMD_FUNC(ban)
5353 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5354 SilcServer server = cmd->server;
5355 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5357 SilcChannelEntry channel;
5358 SilcChannelClientEntry chl;
5359 SilcChannelID *channel_id = NULL;
5360 unsigned char *id, *add, *del;
5361 SilcUInt32 id_len, tmp_len;
5362 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5364 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5367 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
5369 /* Get Channel ID */
5370 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
5372 channel_id = silc_id_payload_parse_id(id, id_len, NULL);
5374 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5375 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5380 /* Get channel entry. The server must know about the channel since the
5381 client is expected to be on the channel. */
5382 channel = silc_idlist_find_channel_by_id(server->local_list,
5385 channel = silc_idlist_find_channel_by_id(server->global_list,
5388 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5389 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5395 /* Check whether this client is on the channel */
5396 if (!silc_server_client_on_channel(client, channel, &chl)) {
5397 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5398 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5402 /* The client must be at least channel operator. */
5403 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
5404 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5405 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
5409 /* Get the new ban and add it to the ban list */
5410 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5412 if (!channel->ban_list)
5413 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
5415 channel->ban_list = silc_realloc(channel->ban_list,
5416 sizeof(*channel->ban_list) *
5418 strlen(channel->ban_list) + 2));
5419 if (add[tmp_len - 1] == ',')
5420 add[tmp_len - 1] = '\0';
5422 strncat(channel->ban_list, add, tmp_len);
5423 strncat(channel->ban_list, ",", 1);
5426 /* Get the ban to be removed and remove it from the list */
5427 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
5428 if (del && channel->ban_list) {
5429 char *start, *end, *n;
5431 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
5432 silc_free(channel->ban_list);
5433 channel->ban_list = NULL;
5435 start = strstr(channel->ban_list, del);
5436 if (start && strlen(start) >= tmp_len) {
5437 end = start + tmp_len;
5438 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
5439 strncat(n, channel->ban_list, start - channel->ban_list);
5440 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
5442 silc_free(channel->ban_list);
5443 channel->ban_list = n;
5448 /* Send the BAN notify type to our primary router. */
5450 silc_server_send_notify_ban(server, SILC_PRIMARY_ROUTE(server),
5451 SILC_BROADCAST(server), channel, add, del);
5453 /* Send the reply back to the client */
5455 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
5456 SILC_STATUS_OK, 0, ident, 2,
5458 3, channel->ban_list,
5460 strlen(channel->ban_list) -1 : 0);
5461 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5462 packet->data, packet->len, FALSE);
5464 silc_buffer_free(packet);
5467 silc_free(channel_id);
5468 silc_server_command_free(cmd);
5471 /* Server side command of LEAVE. Removes client from a channel. */
5473 SILC_SERVER_CMD_FUNC(leave)
5475 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5476 SilcServer server = cmd->server;
5477 SilcSocketConnection sock = cmd->sock;
5478 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
5479 SilcChannelID *id = NULL;
5480 SilcChannelEntry channel;
5484 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
5486 /* Get Channel ID */
5487 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
5489 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5490 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5493 id = silc_id_payload_parse_id(tmp, len, NULL);
5495 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5496 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5500 /* Get channel entry */
5501 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5503 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5505 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5506 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5512 /* Check whether this client is on the channel */
5513 if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
5514 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5515 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5519 /* Notify routers that they should remove this client from their list
5520 of clients on the channel. Send LEAVE notify type. */
5521 silc_server_send_notify_leave(server, SILC_PRIMARY_ROUTE(server),
5522 SILC_BROADCAST(server), channel, id_entry->id);
5524 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
5525 SILC_STATUS_OK, 0, 2, tmp, len);
5527 /* Remove client from channel */
5528 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5530 /* If the channel does not exist anymore we won't send anything */
5533 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5534 /* Re-generate channel key */
5535 if (!silc_server_create_channel_key(server, channel, 0))
5538 /* Send the channel key */
5539 silc_server_send_channel_key(server, NULL, channel,
5540 server->server_type == SILC_ROUTER ?
5541 FALSE : !server->standalone);
5546 silc_server_command_free(cmd);
5549 /* Server side of command USERS. Resolves clients and their USERS currently
5550 joined on the requested channel. The list of Client ID's and their modes
5551 on the channel is sent back. */
5553 SILC_SERVER_CMD_FUNC(users)
5555 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5556 SilcServer server = cmd->server;
5557 SilcChannelEntry channel;
5558 SilcChannelID *id = NULL;
5559 SilcBuffer packet, idp;
5560 unsigned char *channel_id;
5561 SilcUInt32 channel_id_len;
5562 SilcBuffer client_id_list;
5563 SilcBuffer client_mode_list;
5564 unsigned char lc[4];
5565 SilcUInt32 list_count = 0;
5566 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5569 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5571 /* Get Channel ID */
5572 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5574 /* Get channel name */
5575 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5577 if (!channel_id && !channel_name) {
5578 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5579 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5584 id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
5586 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5587 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5592 /* If we are server and we don't know about this channel we will send
5593 the command to our router. If we know about the channel then we also
5594 have the list of users already. */
5596 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5598 channel = silc_idlist_find_channel_by_name(server->local_list,
5599 channel_name, NULL);
5601 if (!channel || (!server->standalone && (channel->disabled ||
5602 !channel->users_resolved))) {
5603 if (server->server_type != SILC_ROUTER && !server->standalone &&
5607 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5608 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5610 /* Send USERS command */
5611 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5612 SILC_PACKET_COMMAND, cmd->packet->flags,
5613 tmpbuf->data, tmpbuf->len, TRUE);
5615 /* Reprocess this packet after received reply */
5616 silc_server_command_pending(server, SILC_COMMAND_USERS,
5617 silc_command_get_ident(cmd->payload),
5618 silc_server_command_users,
5619 silc_server_command_dup(cmd));
5620 cmd->pending = TRUE;
5621 silc_command_set_ident(cmd->payload, ident);
5622 silc_buffer_free(tmpbuf);
5627 /* Check the global list as well. */
5629 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5631 channel = silc_idlist_find_channel_by_name(server->global_list,
5632 channel_name, NULL);
5634 /* Channel really does not exist */
5635 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5636 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5642 /* If the channel is private or secret do not send anything, unless the
5643 user requesting this command is on the channel or is server */
5644 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5645 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5646 && !silc_server_client_on_channel(cmd->sock->user_data, channel,
5648 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5649 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5655 /* Get the users list */
5656 if (!silc_server_get_users_on_channel(server, channel, &client_id_list,
5657 &client_mode_list, &list_count)) {
5659 client_id_list = NULL;
5660 client_mode_list = NULL;
5664 SILC_PUT32_MSB(list_count, lc);
5667 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5668 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5669 SILC_STATUS_OK, 0, ident, 4,
5670 2, idp->data, idp->len,
5673 client_id_list->data : NULL,
5675 client_id_list->len : 0,
5676 5, client_mode_list ?
5677 client_mode_list->data : NULL,
5679 client_mode_list->len : 0);
5680 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5681 packet->data, packet->len, FALSE);
5683 silc_buffer_free(idp);
5684 silc_buffer_free(packet);
5686 silc_buffer_free(client_id_list);
5687 if (client_mode_list)
5688 silc_buffer_free(client_mode_list);
5692 silc_server_command_free(cmd);
5695 /* Server side of command GETKEY. This fetches the client's public key
5696 from the server where to the client is connected. */
5698 SILC_SERVER_CMD_FUNC(getkey)
5700 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5701 SilcServer server = cmd->server;
5703 SilcClientEntry client;
5704 SilcServerEntry server_entry;
5705 SilcClientID *client_id = NULL;
5706 SilcServerID *server_id = NULL;
5707 SilcIDPayload idp = NULL;
5708 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5709 unsigned char *tmp, *pkdata;
5710 SilcUInt32 tmp_len, pklen;
5711 SilcBuffer pk = NULL;
5713 SilcPublicKey public_key;
5715 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5717 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5718 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5722 idp = silc_id_payload_parse(tmp, tmp_len);
5724 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5725 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5730 id_type = silc_id_payload_get_type(idp);
5731 if (id_type == SILC_ID_CLIENT) {
5732 client_id = silc_id_payload_get_id(idp);
5734 /* If the client is not found from local list there is no chance it
5735 would be locally connected client so send the command further. */
5736 client = silc_idlist_find_client_by_id(server->local_list,
5737 client_id, TRUE, NULL);
5739 client = silc_idlist_find_client_by_id(server->global_list,
5740 client_id, TRUE, NULL);
5742 if ((!client && !cmd->pending && !server->standalone) ||
5743 (client && !client->connection && !cmd->pending &&
5744 !(client->mode & SILC_UMODE_DETACHED)) ||
5745 (client && !client->data.public_key && !cmd->pending)) {
5747 SilcUInt16 old_ident;
5748 SilcSocketConnection dest_sock;
5750 dest_sock = silc_server_get_client_route(server, NULL, 0,
5751 client_id, NULL, NULL);
5755 old_ident = silc_command_get_ident(cmd->payload);
5756 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5757 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5759 silc_server_packet_send(server, dest_sock,
5760 SILC_PACKET_COMMAND, cmd->packet->flags,
5761 tmpbuf->data, tmpbuf->len, TRUE);
5763 /* Reprocess this packet after received reply from router */
5764 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5765 silc_command_get_ident(cmd->payload),
5766 silc_server_command_getkey,
5767 silc_server_command_dup(cmd));
5768 cmd->pending = TRUE;
5769 silc_command_set_ident(cmd->payload, old_ident);
5770 silc_buffer_free(tmpbuf);
5775 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5776 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5781 /* The client is locally connected, just get the public key and
5782 send it back. If they key does not exist then do not send it,
5783 send just OK reply */
5784 public_key = client->data.public_key;
5789 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5790 pk = silc_buffer_alloc(4 + tmp_len);
5791 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5792 silc_buffer_format(pk,
5793 SILC_STR_UI_SHORT(tmp_len),
5794 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5795 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5801 } else if (id_type == SILC_ID_SERVER) {
5802 server_id = silc_id_payload_get_id(idp);
5804 /* If the server is not found from local list there is no chance it
5805 would be locally connected server so send the command further. */
5806 server_entry = silc_idlist_find_server_by_id(server->local_list,
5807 server_id, TRUE, NULL);
5809 server_entry = silc_idlist_find_server_by_id(server->global_list,
5810 server_id, TRUE, NULL);
5812 if (server_entry != server->id_entry &&
5813 ((!server_entry && !cmd->pending && !server->standalone) ||
5814 (server_entry && !server_entry->connection && !cmd->pending &&
5815 !server->standalone) ||
5816 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5817 !server->standalone))) {
5819 SilcUInt16 old_ident;
5821 old_ident = silc_command_get_ident(cmd->payload);
5822 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5823 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5825 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5826 SILC_PACKET_COMMAND, cmd->packet->flags,
5827 tmpbuf->data, tmpbuf->len, TRUE);
5829 /* Reprocess this packet after received reply from router */
5830 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5831 silc_command_get_ident(cmd->payload),
5832 silc_server_command_getkey,
5833 silc_server_command_dup(cmd));
5834 cmd->pending = TRUE;
5835 silc_command_set_ident(cmd->payload, old_ident);
5836 silc_buffer_free(tmpbuf);
5840 if (!server_entry) {
5841 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5842 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
5847 /* If they key does not exist then do not send it, send just OK reply */
5848 public_key = (!server_entry->data.public_key ?
5849 (server_entry == server->id_entry ? server->public_key :
5850 NULL) : server_entry->data.public_key);
5855 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5856 pk = silc_buffer_alloc(4 + tmp_len);
5857 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5858 silc_buffer_format(pk,
5859 SILC_STR_UI_SHORT(tmp_len),
5860 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5861 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5871 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5872 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5873 SILC_STATUS_OK, 0, ident,
5877 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5878 packet->data, packet->len, FALSE);
5879 silc_buffer_free(packet);
5882 silc_buffer_free(pk);
5886 silc_id_payload_free(idp);
5887 silc_free(client_id);
5888 silc_free(server_id);
5889 silc_server_command_free(cmd);
5893 /* Private range commands, specific to this implementation */
5895 /* Server side command of CONNECT. Connects us to the specified remote
5896 server or router. */
5898 SILC_SERVER_CMD_FUNC(connect)
5900 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5901 SilcServer server = cmd->server;
5902 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5903 unsigned char *tmp, *host;
5905 SilcUInt32 port = SILC_PORT;
5907 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
5909 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5912 /* Check whether client has the permissions. */
5913 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5914 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5915 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5916 SILC_STATUS_ERR_NO_SERVER_PRIV, 0);
5920 if (server->server_type == SILC_ROUTER &&
5921 client->mode & SILC_UMODE_SERVER_OPERATOR) {
5922 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5923 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
5927 /* Get the remote server */
5928 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5930 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5931 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5937 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5939 SILC_GET32_MSB(port, tmp);
5941 /* Create the connection. It is done with timeout and is async. */
5942 silc_server_create_connection(server, host, port);
5944 /* Send reply to the sender */
5945 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5949 silc_server_command_free(cmd);
5952 /* Server side command of CLOSE. Closes connection to a specified server. */
5954 SILC_SERVER_CMD_FUNC(close)
5956 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5957 SilcServer server = cmd->server;
5958 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5959 SilcServerEntry server_entry;
5960 SilcSocketConnection sock;
5963 unsigned char *name;
5964 SilcUInt32 port = SILC_PORT;
5966 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
5968 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5971 /* Check whether client has the permissions. */
5972 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5973 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5974 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5975 SILC_STATUS_ERR_NO_SERVER_PRIV,
5980 /* Get the remote server */
5981 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5983 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5984 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5990 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5992 SILC_GET32_MSB(port, tmp);
5994 server_entry = silc_idlist_find_server_by_conn(server->local_list,
5995 name, port, FALSE, NULL);
5997 server_entry = silc_idlist_find_server_by_conn(server->global_list,
5998 name, port, FALSE, NULL);
5999 if (!server_entry) {
6000 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
6001 SILC_STATUS_ERR_NO_SERVER_ID, 0);
6005 /* Send reply to the sender */
6006 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
6009 /* Close the connection to the server */
6010 sock = (SilcSocketConnection)server_entry->connection;
6012 /* If we shutdown primary router connection manually then don't trigger
6013 any reconnect or backup router connections, by setting the router
6015 if (server->router == server_entry) {
6016 server->id_entry->router = NULL;
6017 server->router = NULL;
6018 server->standalone = TRUE;
6020 silc_server_free_sock_user_data(server, sock, NULL);
6021 silc_server_close_connection(server, sock);
6024 silc_server_command_free(cmd);
6027 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
6028 active connections. */
6030 SILC_SERVER_CMD_FUNC(shutdown)
6032 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
6033 SilcServer server = cmd->server;
6034 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
6036 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
6038 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
6041 /* Check whether client has the permission. */
6042 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
6043 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
6044 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
6045 SILC_STATUS_ERR_NO_SERVER_PRIV,
6050 /* Send reply to the sender */
6051 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
6054 /* Then, gracefully, or not, bring the server down. */
6055 silc_server_stop(server);
6059 silc_server_command_free(cmd);