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);
376 /* Checks for pending commands and marks callbacks to be called from
377 the command reply function. Returns TRUE if there were pending command. */
379 SilcServerCommandPendingCallbacks
380 silc_server_command_pending_check(SilcServer server,
381 SilcServerCommandReplyContext ctx,
384 SilcUInt32 *callbacks_count)
386 SilcServerCommandPending *r;
387 SilcServerCommandPendingCallbacks callbacks = NULL;
390 silc_dlist_start(server->pending_commands);
391 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
392 if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE)
393 && r->ident == ident) {
394 callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
395 callbacks[i].context = r->context;
396 callbacks[i].callback = r->callback;
402 *callbacks_count = i;
406 /* Sends simple status message as command reply packet */
409 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
416 SILC_LOG_DEBUG(("Sending command status %d", status));
419 silc_command_reply_payload_encode_va(command, status, error,
420 silc_command_get_ident(cmd->payload),
422 silc_server_packet_send(cmd->server, cmd->sock,
423 SILC_PACKET_COMMAND_REPLY, 0,
424 buffer->data, buffer->len, FALSE);
425 silc_buffer_free(buffer);
428 /* Sends command status reply with one extra argument. The argument
429 type must be sent as argument. */
432 silc_server_command_send_status_data(SilcServerCommandContext cmd,
437 const unsigned char *arg,
442 SILC_LOG_DEBUG(("Sending command status %d", status));
445 silc_command_reply_payload_encode_va(command, status, 0,
446 silc_command_get_ident(cmd->payload),
447 1, arg_type, arg, arg_len);
448 silc_server_packet_send(cmd->server, cmd->sock,
449 SILC_PACKET_COMMAND_REPLY, 0,
450 buffer->data, buffer->len, FALSE);
451 silc_buffer_free(buffer);
454 /* This function can be called to check whether in the command reply
455 an error occurred. This function has no effect if this is called
456 when the command function was not called as pending command callback.
457 This returns TRUE if error had occurred. */
460 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
461 SilcServerCommandReplyContext cmdr,
464 if (!cmd->pending || !cmdr)
467 if (!silc_command_get_status(cmdr->payload, NULL, NULL)) {
470 /* Send the same command reply payload */
471 silc_command_set_ident(cmdr->payload,
472 silc_command_get_ident(cmd->payload));
473 buffer = silc_command_payload_encode_payload(cmdr->payload);
474 silc_server_packet_send(cmd->server, cmd->sock,
475 SILC_PACKET_COMMAND_REPLY, 0,
476 buffer->data, buffer->len, FALSE);
477 silc_buffer_free(buffer);
484 /******************************************************************************
488 ******************************************************************************/
497 #define ADD_ERROR(errptr, errptr_count, _id, _id_type, _index, _status) \
499 errptr = silc_realloc(errptr, sizeof(*errptr) * (errptr_count + 1)); \
502 errptr[errptr_count].id = _id; \
503 errptr[errptr_count].id_type = _id_type; \
504 errptr[errptr_count].index = _index; \
505 errptr[errptr_count].error = _status; \
510 silc_server_command_whois_parse(SilcServerCommandContext cmd,
511 SilcClientID ***client_id,
512 SilcUInt32 *client_id_count,
516 ResolveError *error_client,
517 SilcUInt32 *error_client_count)
521 SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
525 /* If client ID is in the command it must be used instead of nickname */
526 tmp = silc_argument_get_arg_type(cmd->args, 4, &len);
528 /* No ID, get the nickname@server string and parse it. */
529 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
531 silc_parse_userfqdn(tmp, nickname, server_name);
533 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
534 SILC_STATUS_ERR_BAD_NICKNAME, 0);
538 /* Command includes ID, we must use that. Take all ID's from the
540 for (k = 0, i = 0; i < argc; i++) {
541 tmp = silc_argument_get_arg_type(cmd->args, i + 4, &len);
544 id = silc_id_payload_parse_id(tmp, len, NULL);
546 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
547 (*client_id_count + 1));
548 (*client_id)[k] = id;
549 (*client_id_count)++;
552 ADD_ERROR((*error_client), (*error_client_count), NULL, 0, i + 4,
553 SILC_STATUS_ERR_BAD_CLIENT_ID);
558 /* Get the max count of reply messages allowed */
559 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
561 SILC_GET32_MSB(*count, tmp);
568 /* Resolve context used by both WHOIS and IDENTIFY commands */
570 SilcServerEntry router;
572 unsigned char **res_argv;
573 SilcUInt32 *res_argv_lens;
574 SilcUInt32 *res_argv_types;
576 } *SilcServerResolveContext;
579 silc_server_command_whois_check(SilcServerCommandContext cmd,
580 SilcClientEntry *clients,
581 SilcUInt32 clients_count)
583 SilcServer server = cmd->server;
584 SilcClientEntry entry;
585 SilcServerResolveContext resolve = NULL, r = NULL;
586 SilcUInt32 resolve_count = 0;
590 SILC_LOG_DEBUG(("Start"));
592 for (i = 0; i < clients_count; i++) {
597 if ((entry->nickname && entry->username && entry->userinfo) ||
598 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
602 /* If we are normal server, and we've not resolved this client from
603 router and it is global client, we'll check whether it is on some
604 channel. If not then we cannot be sure about its validity, and
605 we'll resolve it from router. */
606 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
607 entry->connection || silc_hash_table_count(entry->channels))
611 /* We need to resolve this entry since it is not complete */
613 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
614 /* The entry is being resolved (and we are not the resolver) so attach
615 to the command reply and we're done with this one. */
616 silc_server_command_pending(server, SILC_COMMAND_NONE,
617 entry->resolve_cmd_ident,
618 silc_server_command_whois,
619 silc_server_command_dup(cmd));
622 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
623 /* We've resolved this and it still is not ready. We'll return
624 and are that this will be handled again after it is resolved. */
625 for (i = 0; i < resolve_count; i++) {
626 for (k = 0; k < r->res_argc; k++)
627 silc_free(r->res_argv[k]);
628 silc_free(r->res_argv);
629 silc_free(r->res_argv_lens);
630 silc_free(r->res_argv_types);
635 /* We'll resolve this client */
639 for (k = 0; k < resolve_count; k++) {
640 if (resolve[k].router == entry->router) {
647 resolve = silc_realloc(resolve, sizeof(*resolve) *
648 (resolve_count + 1));
649 r = &resolve[resolve_count];
650 memset(r, 0, sizeof(*r));
651 r->router = entry->router;
652 r->ident = ++server->cmd_ident;
656 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
658 r->res_argv_lens = silc_realloc(r->res_argv_lens,
659 sizeof(*r->res_argv_lens) *
661 r->res_argv_types = silc_realloc(r->res_argv_types,
662 sizeof(*r->res_argv_types) *
664 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
665 r->res_argv[r->res_argc] = silc_calloc(idp->len,
666 sizeof(**r->res_argv));
667 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
668 r->res_argv_lens[r->res_argc] = idp->len;
669 r->res_argv_types[r->res_argc] = r->res_argc + 4;
671 silc_buffer_free(idp);
673 entry->resolve_cmd_ident = r->ident;
674 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
675 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
680 /* Do the resolving */
681 for (i = 0; i < resolve_count; i++) {
686 /* Send WHOIS request. We send WHOIS since we're doing the requesting
687 now anyway so make it a good one. */
688 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
689 r->res_argc, r->res_argv,
693 silc_server_packet_send(server, r->router->connection,
694 SILC_PACKET_COMMAND, cmd->packet->flags,
695 res_cmd->data, res_cmd->len, FALSE);
697 /* Reprocess this packet after received reply */
698 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
700 silc_server_command_whois,
701 silc_server_command_dup(cmd));
704 silc_buffer_free(res_cmd);
705 for (k = 0; k < r->res_argc; k++)
706 silc_free(r->res_argv[k]);
707 silc_free(r->res_argv);
708 silc_free(r->res_argv_lens);
709 silc_free(r->res_argv_types);
718 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
719 SilcClientEntry *clients,
720 SilcUInt32 clients_count,
722 SilcUInt32 errors_count,
723 int count, const char *nickname,
724 SilcClientID **client_ids)
726 SilcServer server = cmd->server;
728 int i, k, valid_count = clients_count;
730 SilcBuffer packet, idp, channels, umode_list = NULL;
731 SilcClientEntry entry;
733 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
734 char nh[256], uh[256];
735 unsigned char idle[4], mode[4];
736 unsigned char *fingerprint;
737 SilcSocketConnection hsock;
740 /* Process only valid clients and ignore those that are not registered.
741 This is checked with nickname only because when resolved client IDs
742 we check that they are registered earlier. */
744 for (i = 0; i < clients_count; i++)
745 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
751 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
752 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
753 3, nickname, strlen(nickname));
758 /* Start processing found clients. */
759 status = SILC_STATUS_OK;
761 status = SILC_STATUS_LIST_START;
763 for (i = 0, k = 0; i < clients_count; i++) {
769 status = SILC_STATUS_LIST_ITEM;
770 if (valid_count > 1 && k == valid_count - 1 && !errors_count)
771 status = SILC_STATUS_LIST_END;
772 if (count && k - 1 == count)
773 status = SILC_STATUS_LIST_END;
775 /* Send WHOIS reply */
776 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
777 tmp = silc_argument_get_first_arg(cmd->args, NULL);
779 memset(uh, 0, sizeof(uh));
780 memset(nh, 0, sizeof(nh));
781 memset(idle, 0, sizeof(idle));
783 strncat(nh, entry->nickname, strlen(entry->nickname));
784 if (!strchr(entry->nickname, '@')) {
786 if (entry->servername) {
787 strncat(nh, entry->servername, strlen(entry->servername));
789 len = entry->router ? strlen(entry->router->server_name) :
790 strlen(server->server_name);
791 strncat(nh, entry->router ? entry->router->server_name :
792 server->server_name, len);
796 strncat(uh, entry->username, strlen(entry->username));
797 if (!strchr(entry->username, '@') && entry->connection) {
799 hsock = (SilcSocketConnection)entry->connection;
800 len = strlen(hsock->hostname);
801 strncat(uh, hsock->hostname, len);
804 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
805 channels = silc_server_get_client_channel_list(server, entry, FALSE,
808 channels = silc_server_get_client_channel_list(server, entry, TRUE,
811 if (entry->data.fingerprint[0] != 0 && entry->data.fingerprint[1] != 0)
812 fingerprint = entry->data.fingerprint;
816 SILC_PUT32_MSB(entry->mode, mode);
817 if (entry->connection)
818 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
821 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
823 2, idp->data, idp->len,
827 strlen(entry->userinfo),
828 6, channels ? channels->data : NULL,
829 channels ? channels->len : 0,
833 fingerprint ? 20 : 0,
834 10, umode_list ? umode_list->data :
835 NULL, umode_list ? umode_list->len :
838 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
839 0, packet->data, packet->len, FALSE);
841 silc_buffer_free(packet);
842 silc_buffer_free(idp);
844 silc_buffer_free(channels);
846 silc_buffer_free(umode_list);
850 if (status == SILC_STATUS_LIST_END)
855 /* Send error replies */
856 if (status == SILC_STATUS_OK && errors_count > 1)
857 status = SILC_STATUS_LIST_START;
860 for (i = 0, k = 0; i < errors_count; i++) {
862 idp = silc_id_payload_encode(errors[i].id, SILC_ID_CLIENT);
866 tmp = silc_argument_get_arg_type(cmd->args, errors[i].index, &len);
870 status = SILC_STATUS_LIST_ITEM;
871 if (errors_count > 1 && k == errors_count - 1)
872 status = SILC_STATUS_LIST_END;
873 if (count && k - 1 == count)
874 status = SILC_STATUS_LIST_END;
877 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
878 (status == SILC_STATUS_OK ?
879 errors[i].error : status),
880 (status == SILC_STATUS_OK ?
881 0 : errors[i].error),
883 silc_buffer_free(idp);
886 if (status == SILC_STATUS_LIST_END)
893 silc_server_command_whois_send_router(SilcServerCommandContext cmd)
895 SilcServer server = cmd->server;
897 SilcUInt16 old_ident;
899 old_ident = silc_command_get_ident(cmd->payload);
900 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
901 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
903 /* Send WHOIS command to our router */
904 silc_server_packet_send(server, (SilcSocketConnection)
905 SILC_PRIMARY_ROUTE(server),
906 SILC_PACKET_COMMAND, cmd->packet->flags,
907 tmpbuf->data, tmpbuf->len, TRUE);
909 /* Reprocess this packet after received reply from router */
910 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
911 silc_command_get_ident(cmd->payload),
912 silc_server_command_whois,
913 silc_server_command_dup(cmd));
915 silc_command_set_ident(cmd->payload, old_ident);
916 silc_buffer_free(tmpbuf);
920 silc_server_command_whois_process(SilcServerCommandContext cmd)
922 SilcServer server = cmd->server;
923 char *nick = NULL, *server_name = NULL;
925 SilcClientEntry *clients = NULL, entry;
926 SilcClientID **client_id = NULL;
927 SilcUInt32 client_id_count = 0, clients_count = 0, error_client_count = 0;
928 ResolveError error_client = NULL;
930 bool check_global = FALSE;
932 /* Parse the whois request */
933 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
934 &nick, &server_name, &count,
935 &error_client, &error_client_count))
938 /* Send the WHOIS request to the router only if it included nickname.
939 Since nicknames can be expanded into many clients we need to send it
940 to router. If the WHOIS included only client ID's we will check them
941 first locally since we just might have them. */
942 if (nick && !client_id_count && cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
943 server->server_type == SILC_SERVER && !cmd->pending &&
944 !server->standalone) {
945 silc_server_command_whois_send_router(cmd);
950 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
952 else if (server->server_type != SILC_SERVER)
955 /* Get all clients matching that ID or nickname from local list */
956 if (client_id_count) {
957 /* Check all Client ID's received in the command packet */
958 for (i = 0; i < client_id_count; i++) {
959 entry = silc_idlist_find_client_by_id(server->local_list,
960 client_id[i], TRUE, NULL);
961 if (!entry && check_global)
962 entry = silc_idlist_find_client_by_id(server->global_list,
963 client_id[i], TRUE, NULL);
965 clients = silc_realloc(clients, sizeof(*clients) *
966 (clients_count + 1));
967 clients[clients_count++] = entry;
969 /* If we are normal server and did not send the request first to router
970 do it now, since we do not have the Client ID information. */
971 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
972 server->server_type == SILC_SERVER && !cmd->pending &&
973 !server->standalone) {
974 silc_server_command_whois_send_router(cmd);
979 ADD_ERROR(error_client, error_client_count, client_id[i],
980 SILC_ID_CLIENT, 0, SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
984 /* Find by nickname */
985 if (!silc_idlist_get_clients_by_hash(server->local_list,
986 nick, server->md5hash,
987 &clients, &clients_count))
988 silc_idlist_get_clients_by_nickname(server->local_list,
990 &clients, &clients_count);
992 if (!silc_idlist_get_clients_by_hash(server->global_list,
993 nick, server->md5hash,
994 &clients, &clients_count))
995 silc_idlist_get_clients_by_nickname(server->global_list,
997 &clients, &clients_count);
1001 if (!clients && (client_id_count || nick)) {
1002 /* If we are normal server and did not send the request first to router
1003 do it now, since we do not have the information. */
1004 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1005 server->server_type == SILC_SERVER && !cmd->pending &&
1006 !server->standalone) {
1007 silc_server_command_whois_send_router(cmd);
1012 /* Such client(s) really does not exist in the SILC network. */
1013 if (!client_id_count)
1014 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
1015 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1016 3, nick, strlen(nick));
1018 silc_server_command_whois_send_reply(cmd, NULL, 0,
1019 error_client, error_client_count,
1024 /* Router always finds the client entry if it exists in the SILC network.
1025 However, it might be incomplete entry and does not include all the
1026 mandatory fields that WHOIS command reply requires. Check for these and
1027 make query from the server who owns the client if some fields are
1029 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
1034 /* Send the command reply */
1035 silc_server_command_whois_send_reply(cmd, clients, clients_count,
1036 error_client, error_client_count,
1037 count, nick, client_id);
1040 if (client_id_count) {
1041 for (i = 0; i < client_id_count; i++)
1042 silc_free(client_id[i]);
1043 silc_free(client_id);
1046 silc_free(error_client);
1048 silc_free(server_name);
1053 /* Server side of command WHOIS. Processes user's query and sends found
1054 results as command replies back to the client. */
1056 SILC_SERVER_CMD_FUNC(whois)
1058 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1061 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 3328);
1063 ret = silc_server_command_whois_process(cmd);
1064 silc_server_command_free(cmd);
1067 /******************************************************************************
1071 ******************************************************************************/
1074 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
1082 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1084 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
1085 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1090 /* Get the nickname@server string and parse it. */
1091 silc_parse_userfqdn(tmp, nickname, server_name);
1093 /* Get the max count of reply messages allowed */
1094 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1096 SILC_GET32_MSB(*count, tmp);
1104 silc_server_command_whowas_check(SilcServerCommandContext cmd,
1105 SilcClientEntry *clients,
1106 SilcUInt32 clients_count)
1108 SilcServer server = cmd->server;
1110 SilcClientEntry entry;
1112 for (i = 0; i < clients_count; i++) {
1115 if (!entry->nickname || !entry->username) {
1117 SilcUInt16 old_ident;
1122 old_ident = silc_command_get_ident(cmd->payload);
1123 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1124 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1126 /* Send WHOWAS command */
1127 silc_server_packet_send(server, entry->router->connection,
1128 SILC_PACKET_COMMAND, cmd->packet->flags,
1129 tmpbuf->data, tmpbuf->len, TRUE);
1131 /* Reprocess this packet after received reply */
1132 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1133 silc_command_get_ident(cmd->payload),
1134 silc_server_command_whowas,
1135 silc_server_command_dup(cmd));
1136 cmd->pending = TRUE;
1137 silc_command_set_ident(cmd->payload, old_ident);
1139 silc_buffer_free(tmpbuf);
1148 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1149 SilcClientEntry *clients,
1150 SilcUInt32 clients_count)
1152 SilcServer server = cmd->server;
1154 int i, k, count = 0, len;
1155 SilcBuffer packet, idp;
1156 SilcClientEntry entry = NULL;
1158 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1159 char nh[256], uh[256];
1162 status = SILC_STATUS_OK;
1164 /* Process only entries that are not registered anymore. */
1166 for (i = 0; i < clients_count; i++) {
1167 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1174 /* No valid entries found at all, just send error */
1175 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1176 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1177 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1178 3, tmp, tmp ? strlen(tmp) : 0);
1182 if (valid_count > 1)
1183 status = SILC_STATUS_LIST_START;
1185 for (i = 0, k = 0; i < clients_count; i++) {
1191 status = SILC_STATUS_LIST_ITEM;
1192 if (valid_count > 1 && k == valid_count - 1)
1193 status = SILC_STATUS_LIST_END;
1194 if (count && k - 1 == count)
1195 status = SILC_STATUS_LIST_END;
1197 /* Send WHOWAS reply */
1198 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1199 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1200 memset(uh, 0, sizeof(uh));
1201 memset(nh, 0, sizeof(nh));
1203 strncat(nh, entry->nickname, strlen(entry->nickname));
1204 if (!strchr(entry->nickname, '@')) {
1205 strncat(nh, "@", 1);
1206 if (entry->servername) {
1207 strncat(nh, entry->servername, strlen(entry->servername));
1209 len = entry->router ? strlen(entry->router->server_name) :
1210 strlen(server->server_name);
1211 strncat(nh, entry->router ? entry->router->server_name :
1212 server->server_name, len);
1216 strncat(uh, entry->username, strlen(entry->username));
1217 if (!strchr(entry->username, '@')) {
1218 strncat(uh, "@", 1);
1219 strcat(uh, "*private*");
1223 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1224 status, 0, ident, 4,
1225 2, idp->data, idp->len,
1230 strlen(entry->userinfo) : 0);
1231 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1232 0, packet->data, packet->len, FALSE);
1234 silc_buffer_free(packet);
1235 silc_buffer_free(idp);
1237 if (status == SILC_STATUS_LIST_END)
1244 silc_server_command_whowas_process(SilcServerCommandContext cmd)
1246 SilcServer server = cmd->server;
1247 char *nick = NULL, *server_name = NULL;
1249 SilcClientEntry *clients = NULL;
1250 SilcUInt32 clients_count = 0;
1252 bool check_global = FALSE;
1254 /* Protocol dictates that we must always send the received WHOWAS request
1255 to our router if we are normal server, so let's do it now unless we
1256 are standalone. We will not send any replies to the client until we
1257 have received reply from the router. */
1258 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1259 server->server_type == SILC_SERVER && !cmd->pending &&
1260 !server->standalone) {
1262 SilcUInt16 old_ident;
1264 old_ident = silc_command_get_ident(cmd->payload);
1265 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1266 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1268 /* Send WHOWAS command to our router */
1269 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
1270 SILC_PACKET_COMMAND, cmd->packet->flags,
1271 tmpbuf->data, tmpbuf->len, TRUE);
1273 /* Reprocess this packet after received reply from router */
1274 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1275 silc_command_get_ident(cmd->payload),
1276 silc_server_command_whowas,
1277 silc_server_command_dup(cmd));
1278 cmd->pending = TRUE;
1279 silc_command_set_ident(cmd->payload, old_ident);
1281 silc_buffer_free(tmpbuf);
1286 /* We are ready to process the command request. Let's search for the
1287 requested client and send reply to the requesting client. */
1289 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1290 check_global = TRUE;
1291 else if (server->server_type != SILC_SERVER)
1292 check_global = TRUE;
1294 /* Parse the whowas request */
1295 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1298 /* Get all clients matching that nickname from local list */
1299 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1301 &clients, &clients_count))
1302 silc_idlist_get_clients_by_hash(server->local_list,
1303 nick, server->md5hash,
1304 &clients, &clients_count);
1306 /* Check global list as well */
1308 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1310 &clients, &clients_count))
1311 silc_idlist_get_clients_by_hash(server->global_list,
1312 nick, server->md5hash,
1313 &clients, &clients_count);
1317 /* Such a client really does not exist in the SILC network. */
1318 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1319 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1320 3, nick, strlen(nick));
1324 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1329 /* Send the command reply to the client */
1330 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1335 silc_free(server_name);
1339 /* Server side of command WHOWAS. */
1341 SILC_SERVER_CMD_FUNC(whowas)
1343 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1346 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1348 ret = silc_server_command_whowas_process(cmd);
1349 silc_server_command_free(cmd);
1352 /******************************************************************************
1356 ******************************************************************************/
1359 silc_server_command_identify_send_router(SilcServerCommandContext cmd)
1361 SilcServer server = cmd->server;
1363 SilcUInt16 old_ident;
1365 old_ident = silc_command_get_ident(cmd->payload);
1366 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1367 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1369 /* Send IDENTIFY command to our router */
1370 silc_server_packet_send(server, (SilcSocketConnection)
1371 SILC_PRIMARY_ROUTE(server),
1372 SILC_PACKET_COMMAND, cmd->packet->flags,
1373 tmpbuf->data, tmpbuf->len, TRUE);
1375 /* Reprocess this packet after received reply from router */
1376 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1377 silc_command_get_ident(cmd->payload),
1378 silc_server_command_identify,
1379 silc_server_command_dup(cmd));
1380 cmd->pending = TRUE;
1381 silc_command_set_ident(cmd->payload, old_ident);
1382 silc_buffer_free(tmpbuf);
1386 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1387 SilcClientEntry **clients,
1388 SilcUInt32 *clients_count,
1389 SilcServerEntry **servers,
1390 SilcUInt32 *servers_count,
1391 SilcChannelEntry **channels,
1392 SilcUInt32 *channels_count,
1394 ResolveError *error_id,
1395 SilcUInt32 *error_id_count)
1397 SilcServer server = cmd->server;
1400 SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
1402 bool check_global = FALSE;
1406 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1407 check_global = TRUE;
1408 else if (server->server_type != SILC_SERVER)
1409 check_global = TRUE;
1411 /* If ID Payload is in the command it must be used instead of names */
1412 tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1414 /* No ID, get the names. */
1416 /* If we are normal server and have not resolved information from
1417 router yet, do so now. */
1418 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1419 server->server_type == SILC_SERVER && !cmd->pending &&
1420 !server->standalone) {
1421 silc_server_command_identify_send_router(cmd);
1425 /* Try to get nickname@server. */
1426 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1429 char *nick_server = NULL;
1431 silc_parse_userfqdn(tmp, &nick, &nick_server);
1433 if (!silc_idlist_get_clients_by_hash(server->local_list,
1434 nick, server->md5hash,
1435 clients, clients_count))
1436 silc_idlist_get_clients_by_nickname(server->local_list,
1438 clients, clients_count);
1440 if (!silc_idlist_get_clients_by_hash(server->global_list,
1441 nick, server->md5hash,
1442 clients, clients_count))
1443 silc_idlist_get_clients_by_nickname(server->global_list,
1445 clients, clients_count);
1449 silc_free(nick_server);
1452 /* the nickname does not exist, send error reply */
1453 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1454 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1455 3, tmp, strlen(tmp));
1460 /* Try to get server name */
1461 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1463 entry = silc_idlist_find_server_by_name(server->local_list,
1465 if (!entry && check_global)
1466 entry = silc_idlist_find_server_by_name(server->global_list,
1469 *servers = silc_realloc(*servers, sizeof(**servers) *
1470 (*servers_count + 1));
1471 (*servers)[(*servers_count)++] = entry;
1475 /* the server does not exist, send error reply */
1476 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1477 SILC_STATUS_ERR_NO_SUCH_SERVER,
1478 0, 3, tmp, strlen(tmp));
1483 /* Try to get channel name */
1484 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1486 entry = silc_idlist_find_channel_by_name(server->local_list,
1488 if (!entry && check_global)
1489 entry = silc_idlist_find_channel_by_name(server->global_list,
1492 *channels = silc_realloc(*channels, sizeof(**channels) *
1493 (*channels_count + 1));
1494 (*channels)[(*channels_count)++] = entry;
1498 /* The channel does not exist, send error reply */
1499 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1500 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1501 0, 3, tmp, strlen(tmp));
1506 if (!(*clients) && !(*servers) && !(*channels)) {
1507 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1508 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1513 /* Command includes ID, we must use that. Also check whether the command
1514 has more than one ID set - take them all. */
1516 /* Take all ID's from the command packet */
1517 for (i = 0; i < argc; i++) {
1520 tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
1524 idp = silc_id_payload_parse(tmp, len);
1526 ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1527 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1529 id = silc_id_payload_get_id(idp);
1530 switch (silc_id_payload_get_type(idp)) {
1532 case SILC_ID_CLIENT:
1533 entry = silc_idlist_find_client_by_id(server->local_list,
1535 if (!entry && check_global)
1536 entry = silc_idlist_find_client_by_id(server->global_list,
1539 *clients = silc_realloc(*clients, sizeof(**clients) *
1540 (*clients_count + 1));
1541 (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
1543 /* If we are normal server and have not resolved information from
1544 router yet, do so now. */
1545 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1546 server->server_type == SILC_SERVER && !cmd->pending &&
1547 !server->standalone) {
1548 silc_server_command_identify_send_router(cmd);
1549 silc_free(*clients);
1550 silc_free(*servers);
1551 silc_free(*channels);
1552 silc_free(*error_id);
1556 ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1557 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
1562 case SILC_ID_SERVER:
1563 entry = silc_idlist_find_server_by_id(server->local_list,
1565 if (!entry && check_global)
1566 entry = silc_idlist_find_server_by_id(server->global_list,
1569 *servers = silc_realloc(*servers, sizeof(**servers) *
1570 (*servers_count + 1));
1571 (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
1573 /* If we are normal server and have not resolved information from
1574 router yet, do so now. */
1575 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1576 server->server_type == SILC_SERVER && !cmd->pending &&
1577 !server->standalone) {
1578 silc_server_command_identify_send_router(cmd);
1579 silc_free(*clients);
1580 silc_free(*servers);
1581 silc_free(*channels);
1582 silc_free(*error_id);
1586 ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1587 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
1591 case SILC_ID_CHANNEL:
1592 entry = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
1593 if (!entry && check_global)
1594 entry = silc_idlist_find_channel_by_id(server->global_list, id,
1597 *channels = silc_realloc(*channels, sizeof(**channels) *
1598 (*channels_count + 1));
1599 (*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
1601 /* If we are normal server and have not resolved information from
1602 router yet, do so now. */
1603 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1604 server->server_type == SILC_SERVER && !cmd->pending &&
1605 !server->standalone) {
1606 silc_server_command_identify_send_router(cmd);
1607 silc_free(*clients);
1608 silc_free(*servers);
1609 silc_free(*channels);
1610 silc_free(*error_id);
1614 ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1615 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID);
1624 /* Get the max count of reply messages allowed */
1625 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1627 SILC_GET32_MSB(*count, tmp);
1634 /* Checks that all mandatory fields in client entry are present. If not
1635 then send WHOIS request to the server who owns the client. We use
1636 WHOIS because we want to get as much information as possible at once. */
1639 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1640 SilcClientEntry *clients,
1641 SilcUInt32 clients_count)
1643 SilcServer server = cmd->server;
1644 SilcClientEntry entry;
1645 SilcServerResolveContext resolve = NULL, r = NULL;
1646 SilcUInt32 resolve_count = 0;
1650 for (i = 0; i < clients_count; i++) {
1655 if (entry->nickname ||
1656 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1660 /* If we are normal server, and we've not resolved this client from
1661 router and it is global client, we'll check whether it is on some
1662 channel. If not then we cannot be sure about its validity, and
1663 we'll resolve it from router. */
1664 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
1665 entry->connection || silc_hash_table_count(entry->channels))
1669 /* We need to resolve this entry since it is not complete */
1671 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1672 /* The entry is being resolved (and we are not the resolver) so attach
1673 to the command reply and we're done with this one. */
1674 silc_server_command_pending(server, SILC_COMMAND_NONE,
1675 entry->resolve_cmd_ident,
1676 silc_server_command_identify,
1677 silc_server_command_dup(cmd));
1680 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1681 /* We've resolved this and it still is not ready. We'll return
1682 and are that this will be handled again after it is resolved. */
1683 for (i = 0; i < resolve_count; i++) {
1684 for (k = 0; k < r->res_argc; k++)
1685 silc_free(r->res_argv[k]);
1686 silc_free(r->res_argv);
1687 silc_free(r->res_argv_lens);
1688 silc_free(r->res_argv_types);
1693 /* We'll resolve this client */
1697 for (k = 0; k < resolve_count; k++) {
1698 if (resolve[k].router == entry->router) {
1705 resolve = silc_realloc(resolve, sizeof(*resolve) *
1706 (resolve_count + 1));
1707 r = &resolve[resolve_count];
1708 memset(r, 0, sizeof(*r));
1709 r->router = entry->router;
1710 r->ident = ++server->cmd_ident;
1714 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1716 r->res_argv_lens = silc_realloc(r->res_argv_lens,
1717 sizeof(*r->res_argv_lens) *
1719 r->res_argv_types = silc_realloc(r->res_argv_types,
1720 sizeof(*r->res_argv_types) *
1722 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1723 r->res_argv[r->res_argc] = silc_calloc(idp->len,
1724 sizeof(**r->res_argv));
1725 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1726 r->res_argv_lens[r->res_argc] = idp->len;
1727 r->res_argv_types[r->res_argc] = r->res_argc + 4;
1729 silc_buffer_free(idp);
1731 entry->resolve_cmd_ident = r->ident;
1732 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1733 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1738 /* Do the resolving */
1739 for (i = 0; i < resolve_count; i++) {
1744 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1745 now anyway so make it a good one. */
1746 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1747 r->res_argc, r->res_argv,
1751 silc_server_packet_send(server, r->router->connection,
1752 SILC_PACKET_COMMAND, cmd->packet->flags,
1753 res_cmd->data, res_cmd->len, FALSE);
1755 /* Reprocess this packet after received reply */
1756 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1758 silc_server_command_identify,
1759 silc_server_command_dup(cmd));
1760 cmd->pending = TRUE;
1762 silc_buffer_free(res_cmd);
1763 for (k = 0; k < r->res_argc; k++)
1764 silc_free(r->res_argv[k]);
1765 silc_free(r->res_argv);
1766 silc_free(r->res_argv_lens);
1767 silc_free(r->res_argv_types);
1776 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1777 SilcClientEntry *clients,
1778 SilcUInt32 clients_count,
1779 SilcServerEntry *servers,
1780 SilcUInt32 servers_count,
1781 SilcChannelEntry *channels,
1782 SilcUInt32 channels_count,
1783 ResolveError errors,
1784 SilcUInt32 errors_count,
1787 SilcServer server = cmd->server;
1788 int i, k, valid_count;
1790 SilcBuffer packet, idp;
1792 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1793 char nh[256], uh[256];
1794 SilcSocketConnection hsock;
1797 status = SILC_STATUS_OK;
1800 SilcClientEntry entry;
1801 valid_count = clients_count;
1803 if (silc_argument_get_arg_type(cmd->args, 1, NULL)) {
1804 /* Process only valid clients and ignore those that are not registered.
1805 This is checked with nickname only because when resolved client IDs
1806 we check that they are registered earlier. */
1808 for (i = 0; i < clients_count; i++) {
1809 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1816 /* No valid entries found at all, just send error */
1817 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1818 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1819 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1820 3, tmp, tmp ? strlen(tmp) : 0);
1825 /* Process all valid client entries and send command replies */
1827 if (valid_count > 1)
1828 status = SILC_STATUS_LIST_START;
1830 for (i = 0, k = 0; i < clients_count; i++) {
1836 status = SILC_STATUS_LIST_ITEM;
1837 if (valid_count > 1 && k == valid_count - 1
1838 && !servers_count && !channels_count && !errors_count)
1839 status = SILC_STATUS_LIST_END;
1840 if (count && k - 1 == count)
1841 status = SILC_STATUS_LIST_END;
1843 /* Send IDENTIFY reply */
1845 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1846 memset(uh, 0, sizeof(uh));
1847 memset(nh, 0, sizeof(nh));
1848 strncat(nh, entry->nickname, strlen(entry->nickname));
1849 if (!strchr(entry->nickname, '@')) {
1850 strncat(nh, "@", 1);
1851 if (entry->servername) {
1852 strncat(nh, entry->servername, strlen(entry->servername));
1854 len = entry->router ? strlen(entry->router->server_name) :
1855 strlen(server->server_name);
1856 strncat(nh, entry->router ? entry->router->server_name :
1857 server->server_name, len);
1861 if (!entry->username) {
1862 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1863 status, 0, ident, 2,
1864 2, idp->data, idp->len,
1867 strncat(uh, entry->username, strlen(entry->username));
1868 if (!strchr(entry->username, '@') && entry->connection) {
1869 strncat(uh, "@", 1);
1870 hsock = (SilcSocketConnection)entry->connection;
1871 len = strlen(hsock->hostname);
1872 strncat(uh, hsock->hostname, len);
1875 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1876 status, 0, ident, 3,
1877 2, idp->data, idp->len,
1882 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1883 0, packet->data, packet->len, FALSE);
1885 silc_buffer_free(packet);
1886 silc_buffer_free(idp);
1888 if (status == SILC_STATUS_LIST_END)
1895 SilcServerEntry entry;
1897 if (status == SILC_STATUS_OK && servers_count > 1)
1898 status = SILC_STATUS_LIST_START;
1900 for (i = 0, k = 0; i < servers_count; i++) {
1904 status = SILC_STATUS_LIST_ITEM;
1905 if (servers_count > 1 && k == servers_count - 1 && !channels_count &&
1907 status = SILC_STATUS_LIST_END;
1908 if (count && k - 1 == count)
1909 status = SILC_STATUS_LIST_END;
1911 /* Send IDENTIFY reply */
1912 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1914 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1915 status, 0, ident, 2,
1916 2, idp->data, idp->len,
1917 3, entry->server_name,
1918 entry->server_name ?
1919 strlen(entry->server_name) : 0);
1920 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1921 0, packet->data, packet->len, FALSE);
1923 silc_buffer_free(packet);
1924 silc_buffer_free(idp);
1926 if (status == SILC_STATUS_LIST_END)
1933 SilcChannelEntry entry;
1935 if (status == SILC_STATUS_OK && channels_count > 1)
1936 status = SILC_STATUS_LIST_START;
1938 for (i = 0, k = 0; i < channels_count; i++) {
1939 entry = channels[i];
1942 status = SILC_STATUS_LIST_ITEM;
1943 if (channels_count > 1 && k == channels_count - 1 && !errors_count)
1944 status = SILC_STATUS_LIST_END;
1945 if (count && k - 1 == count)
1946 status = SILC_STATUS_LIST_END;
1948 /* Send IDENTIFY reply */
1949 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1951 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1952 status, 0, ident, 2,
1953 2, idp->data, idp->len,
1954 3, entry->channel_name,
1955 entry->channel_name ?
1956 strlen(entry->channel_name): 0);
1957 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1958 0, packet->data, packet->len, FALSE);
1960 silc_buffer_free(packet);
1961 silc_buffer_free(idp);
1963 if (status == SILC_STATUS_LIST_END)
1969 /* Send error replies */
1971 if (status == SILC_STATUS_OK && errors_count > 1)
1972 status = SILC_STATUS_LIST_START;
1975 for (i = 0, k = 0; i < errors_count; i++) {
1977 idp = silc_id_payload_encode(errors[i].id, SILC_ID_CLIENT);
1981 tmp = silc_argument_get_arg_type(cmd->args, errors[i].index, &len);
1985 status = SILC_STATUS_LIST_ITEM;
1986 if (errors_count > 1 && k == errors_count - 1)
1987 status = SILC_STATUS_LIST_END;
1988 if (count && k - 1 == count)
1989 status = SILC_STATUS_LIST_END;
1992 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1993 (status == SILC_STATUS_OK ?
1994 errors[i].error : status),
1995 (status == SILC_STATUS_OK ?
1996 0 : errors[i].error),
1998 silc_buffer_free(idp);
2001 if (status == SILC_STATUS_LIST_END)
2009 silc_server_command_identify_process(SilcServerCommandContext cmd)
2011 SilcUInt32 count = 0;
2013 SilcClientEntry *clients = NULL;
2014 SilcServerEntry *servers = NULL;
2015 SilcChannelEntry *channels = NULL;
2016 SilcUInt32 clients_count = 0, servers_count = 0, channels_count = 0;
2017 SilcUInt32 errors_count = 0;
2018 ResolveError errors = NULL;
2020 /* Parse the IDENTIFY request */
2021 ret = silc_server_command_identify_parse(cmd,
2022 &clients, &clients_count,
2023 &servers, &servers_count,
2024 &channels, &channels_count,
2025 &count, &errors, &errors_count);
2030 /* Check that all mandatory fields are present and request those data
2031 from the server who owns the client if necessary. */
2032 if (!silc_server_command_identify_check_client(cmd, clients,
2038 /* Send the command reply to the client */
2039 silc_server_command_identify_send_reply(cmd,
2040 clients, clients_count,
2041 servers, servers_count,
2042 channels, channels_count,
2043 errors, errors_count,
2049 silc_free(channels);
2054 SILC_SERVER_CMD_FUNC(identify)
2056 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2059 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
2061 ret = silc_server_command_identify_process(cmd);
2062 silc_server_command_free(cmd);
2065 /* Server side of command NICK. Sets nickname for user. Setting
2066 nickname causes generation of a new client ID for the client. The
2067 new client ID is sent to the client after changing the nickname. */
2069 SILC_SERVER_CMD_FUNC(nick)
2071 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2072 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2073 SilcServer server = cmd->server;
2074 SilcBuffer packet, nidp, oidp = NULL;
2075 SilcClientID *new_id;
2076 SilcUInt32 nick_len;
2078 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2081 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2084 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
2086 /* Check nickname */
2087 nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
2090 if (silc_server_name_bad_chars(nick, nick_len) == TRUE) {
2091 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2092 SILC_STATUS_ERR_BAD_NICKNAME, 0);
2096 /* Check for same nickname */
2097 if (!strcmp(client->nickname, nick)) {
2098 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2102 /* Create new Client ID */
2103 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
2105 cmd->server->md5hash, nick,
2109 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2110 SILC_STATUS_ERR_BAD_NICKNAME, 0);
2113 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2116 /* Send notify about nickname change to our router. We send the new
2117 ID and ask to replace it with the old one. If we are router the
2118 packet is broadcasted. Send NICK_CHANGE notify. */
2119 silc_server_send_notify_nick_change(server, SILC_PRIMARY_ROUTE(server),
2120 SILC_BROADCAST(server), client->id,
2123 /* Check if anyone is watching the old nickname */
2124 if (server->server_type == SILC_ROUTER)
2125 silc_server_check_watcher_list(server, client, nick,
2126 SILC_NOTIFY_TYPE_NICK_CHANGE);
2128 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2130 /* Remove old cache entry */
2131 silc_idcache_del_by_context(server->local_list->clients, client);
2133 silc_free(client->id);
2134 client->id = new_id;
2136 silc_free(client->nickname);
2137 client->nickname = strdup(nick);
2139 /* Update client cache */
2140 silc_idcache_add(server->local_list->clients, client->nickname,
2141 client->id, (void *)client, 0, NULL);
2143 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2145 /* Send NICK_CHANGE notify to the client's channels */
2146 silc_server_send_notify_on_channels(server, NULL, client,
2147 SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
2148 oidp->data, oidp->len,
2149 nidp->data, nidp->len,
2151 strlen(client->nickname));
2153 /* Check if anyone is watching the new nickname */
2154 if (server->server_type == SILC_ROUTER)
2155 silc_server_check_watcher_list(server, client, NULL,
2156 SILC_NOTIFY_TYPE_NICK_CHANGE);
2159 /* Send the new Client ID as reply command back to client */
2160 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
2161 SILC_STATUS_OK, 0, ident, 2,
2162 2, nidp->data, nidp->len,
2163 3, nick, strlen(nick));
2164 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2165 0, packet->data, packet->len, FALSE);
2167 silc_buffer_free(packet);
2168 silc_buffer_free(nidp);
2170 silc_buffer_free(oidp);
2173 silc_server_command_free(cmd);
2176 /* Sends the LIST command reply */
2179 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2180 SilcChannelEntry *lch,
2181 SilcUInt32 lch_count,
2182 SilcChannelEntry *gch,
2183 SilcUInt32 gch_count)
2186 SilcBuffer packet, idp;
2187 SilcChannelEntry entry;
2189 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2191 unsigned char usercount[4];
2193 int valid_lcount = 0, valid_rcount = 0;
2195 for (i = 0; i < lch_count; i++) {
2196 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2201 for (i = 0; i < gch_count; i++) {
2202 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2208 status = SILC_STATUS_OK;
2209 if ((lch_count + gch_count) > 1)
2210 status = SILC_STATUS_LIST_START;
2213 for (i = 0, k = 0; i < lch_count; i++) {
2219 status = SILC_STATUS_LIST_ITEM;
2220 if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
2221 status = SILC_STATUS_LIST_END;
2223 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2225 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2226 topic = "*private*";
2227 memset(usercount, 0, sizeof(usercount));
2229 topic = entry->topic;
2230 users = silc_hash_table_count(entry->user_list);
2231 SILC_PUT32_MSB(users, usercount);
2234 /* Send the reply */
2236 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2237 status, 0, ident, 4,
2238 2, idp->data, idp->len,
2239 3, entry->channel_name,
2240 strlen(entry->channel_name),
2241 4, topic, topic ? strlen(topic) : 0,
2243 silc_server_packet_send(cmd->server, cmd->sock,
2244 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2245 packet->len, FALSE);
2246 silc_buffer_free(packet);
2247 silc_buffer_free(idp);
2252 for (i = 0, k = 0; i < gch_count; i++) {
2258 status = SILC_STATUS_LIST_ITEM;
2259 if (valid_rcount > 1 && k == valid_rcount - 1)
2260 status = SILC_STATUS_LIST_END;
2262 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2264 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2265 topic = "*private*";
2266 memset(usercount, 0, sizeof(usercount));
2268 topic = entry->topic;
2269 users = entry->user_count;
2270 SILC_PUT32_MSB(users, usercount);
2273 /* Send the reply */
2275 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2276 status, 0, ident, 4,
2277 2, idp->data, idp->len,
2278 3, entry->channel_name,
2279 strlen(entry->channel_name),
2280 4, topic, topic ? strlen(topic) : 0,
2282 silc_server_packet_send(cmd->server, cmd->sock,
2283 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2284 packet->len, FALSE);
2285 silc_buffer_free(packet);
2286 silc_buffer_free(idp);
2291 /* Server side of LIST command. This lists the channel of the requested
2292 server. Secret channels are not listed. */
2294 SILC_SERVER_CMD_FUNC(list)
2296 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2297 SilcServer server = cmd->server;
2298 SilcChannelID *channel_id = NULL;
2301 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2302 SilcUInt32 lch_count = 0, gch_count = 0;
2304 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2306 /* If we are normal server, send the command to router, since we
2307 want to know all channels in the network. */
2308 if (!cmd->pending && server->server_type == SILC_SERVER &&
2309 !server->standalone) {
2311 SilcUInt16 old_ident;
2313 old_ident = silc_command_get_ident(cmd->payload);
2314 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2315 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2316 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
2317 SILC_PACKET_COMMAND, cmd->packet->flags,
2318 tmpbuf->data, tmpbuf->len, TRUE);
2320 /* Reprocess this packet after received reply from router */
2321 silc_server_command_pending(server, SILC_COMMAND_LIST,
2322 silc_command_get_ident(cmd->payload),
2323 silc_server_command_list,
2324 silc_server_command_dup(cmd));
2325 cmd->pending = TRUE;
2326 silc_command_set_ident(cmd->payload, old_ident);
2327 silc_buffer_free(tmpbuf);
2331 /* Get Channel ID */
2332 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2334 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2336 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2337 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2342 /* Get the channels from local list */
2343 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2346 /* Get the channels from global list */
2347 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2350 /* Send the reply */
2351 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2352 gchannels, gch_count);
2354 silc_free(lchannels);
2355 silc_free(gchannels);
2358 silc_server_command_free(cmd);
2361 /* Server side of TOPIC command. Sets topic for channel and/or returns
2362 current topic to client. */
2364 SILC_SERVER_CMD_FUNC(topic)
2366 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2367 SilcServer server = cmd->server;
2368 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2369 SilcChannelID *channel_id;
2370 SilcChannelEntry channel;
2371 SilcChannelClientEntry chl;
2372 SilcBuffer packet, idp;
2374 SilcUInt32 argc, tmp_len;
2375 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2377 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2379 argc = silc_argument_get_arg_num(cmd->args);
2381 /* Get Channel ID */
2382 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2384 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2385 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2388 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2390 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2391 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2395 /* Check whether the channel exists */
2396 channel = silc_idlist_find_channel_by_id(server->local_list,
2399 channel = silc_idlist_find_channel_by_id(server->global_list,
2402 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2403 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
2411 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2413 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2414 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2419 if (strlen(tmp) > 256) {
2420 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2421 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2426 /* See whether the client is on channel and has rights to change topic */
2427 if (!silc_server_client_on_channel(client, channel, &chl)) {
2428 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2429 SILC_STATUS_ERR_NOT_ON_CHANNEL,
2434 if (channel->mode & SILC_CHANNEL_MODE_TOPIC &&
2435 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
2436 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
2437 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2438 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
2443 if (!channel->topic || strcmp(channel->topic, tmp)) {
2444 /* Set the topic for channel */
2445 silc_free(channel->topic);
2446 channel->topic = strdup(tmp);
2448 /* Send TOPIC_SET notify type to the network */
2449 silc_server_send_notify_topic_set(server, SILC_PRIMARY_ROUTE(server),
2450 SILC_BROADCAST(server), channel,
2451 client->id, SILC_ID_CLIENT,
2454 /* Send notify about topic change to all clients on the channel */
2455 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2456 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2457 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2458 idp->data, idp->len,
2460 strlen(channel->topic));
2461 silc_buffer_free(idp);
2465 /* Send the topic to client as reply packet */
2466 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2467 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2468 SILC_STATUS_OK, 0, ident, 2,
2469 2, idp->data, idp->len,
2472 strlen(channel->topic) : 0);
2473 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2474 0, packet->data, packet->len, FALSE);
2476 silc_buffer_free(packet);
2477 silc_buffer_free(idp);
2478 silc_free(channel_id);
2481 silc_server_command_free(cmd);
2484 /* Server side of INVITE command. Invites some client to join some channel.
2485 This command is also used to manage the invite list of the channel. */
2487 SILC_SERVER_CMD_FUNC(invite)
2489 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2490 SilcServer server = cmd->server;
2491 SilcSocketConnection sock = cmd->sock, dest_sock;
2492 SilcChannelClientEntry chl;
2493 SilcClientEntry sender, dest;
2494 SilcClientID *dest_id = NULL;
2495 SilcChannelEntry channel;
2496 SilcChannelID *channel_id = NULL;
2497 SilcIDListData idata;
2498 SilcBuffer idp, idp2, packet;
2499 unsigned char *tmp, *add, *del;
2501 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2503 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2505 /* Get Channel ID */
2506 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2508 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2509 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2512 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
2514 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2515 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2519 /* Get the channel entry */
2520 channel = silc_idlist_find_channel_by_id(server->local_list,
2523 channel = silc_idlist_find_channel_by_id(server->global_list,
2526 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2527 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
2533 /* Check whether the sender of this command is on the channel. */
2534 sender = (SilcClientEntry)sock->user_data;
2535 if (!silc_server_client_on_channel(sender, channel, &chl)) {
2536 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2537 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
2541 /* Check whether the channel is invite-only channel. If yes then the
2542 sender of this command must be at least channel operator. */
2543 if (channel->mode & SILC_CHANNEL_MODE_INVITE &&
2544 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
2545 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
2546 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2547 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
2552 /* Get destination client ID */
2553 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2558 dest_id = silc_id_payload_parse_id(tmp, len, NULL);
2560 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2561 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
2565 /* Get the client entry */
2566 dest = silc_server_get_client_resolve(server, dest_id, FALSE, &resolve);
2568 if (server->server_type != SILC_SERVER || !resolve) {
2569 silc_server_command_send_status_reply(
2570 cmd, SILC_COMMAND_INVITE,
2571 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0);
2575 /* The client info is being resolved. Reprocess this packet after
2576 receiving the reply to the query. */
2577 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2579 silc_server_command_invite,
2580 silc_server_command_dup(cmd));
2581 cmd->pending = TRUE;
2582 silc_free(channel_id);
2587 /* Check whether the requested client is already on the channel. */
2588 if (silc_server_client_on_channel(dest, channel, NULL)) {
2589 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2590 SILC_STATUS_ERR_USER_ON_CHANNEL,
2595 /* Get route to the client */
2596 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id,
2599 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2600 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2605 memset(invite, 0, sizeof(invite));
2606 strncat(invite, dest->nickname, strlen(dest->nickname));
2607 strncat(invite, "!", 1);
2608 strncat(invite, dest->username, strlen(dest->username));
2609 if (!strchr(dest->username, '@')) {
2610 strncat(invite, "@", 1);
2611 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2614 len = strlen(invite);
2615 if (!channel->invite_list)
2616 channel->invite_list = silc_calloc(len + 2,
2617 sizeof(*channel->invite_list));
2619 channel->invite_list = silc_realloc(channel->invite_list,
2620 sizeof(*channel->invite_list) *
2622 strlen(channel->invite_list) + 2));
2623 strncat(channel->invite_list, invite, len);
2624 strncat(channel->invite_list, ",", 1);
2626 if (!(dest->mode & SILC_UMODE_BLOCK_INVITE)) {
2627 /* Send notify to the client that is invited to the channel */
2628 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2629 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2630 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2632 SILC_NOTIFY_TYPE_INVITE, 3,
2633 idp->data, idp->len,
2634 channel->channel_name,
2635 strlen(channel->channel_name),
2636 idp2->data, idp2->len);
2637 silc_buffer_free(idp);
2638 silc_buffer_free(idp2);
2642 /* Add the client to the invite list of the channel */
2643 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2645 if (!channel->invite_list)
2646 channel->invite_list = silc_calloc(len + 2,
2647 sizeof(*channel->invite_list));
2649 channel->invite_list = silc_realloc(channel->invite_list,
2650 sizeof(*channel->invite_list) *
2652 strlen(channel->invite_list) + 2));
2653 if (add[len - 1] == ',')
2654 add[len - 1] = '\0';
2656 strncat(channel->invite_list, add, len);
2657 strncat(channel->invite_list, ",", 1);
2660 /* Get the invite to be removed and remove it from the list */
2661 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2662 if (del && channel->invite_list) {
2663 char *start, *end, *n;
2665 if (!strncmp(channel->invite_list, del,
2666 strlen(channel->invite_list) - 1)) {
2667 silc_free(channel->invite_list);
2668 channel->invite_list = NULL;
2670 start = strstr(channel->invite_list, del);
2671 if (start && strlen(start) >= len) {
2673 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2674 strncat(n, channel->invite_list, start - channel->invite_list);
2675 strncat(n, end + 1, ((channel->invite_list +
2676 strlen(channel->invite_list)) - end) - 1);
2677 silc_free(channel->invite_list);
2678 channel->invite_list = n;
2683 /* Send notify to the primary router */
2684 silc_server_send_notify_invite(server, SILC_PRIMARY_ROUTE(server),
2685 SILC_BROADCAST(server), channel,
2686 sender->id, add, del);
2688 /* Send command reply */
2689 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2693 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2694 SILC_STATUS_OK, 0, ident, 2,
2696 3, channel->invite_list,
2697 channel->invite_list ?
2698 strlen(channel->invite_list) : 0);
2701 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2702 SILC_STATUS_OK, 0, ident, 1,
2704 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2705 packet->data, packet->len, FALSE);
2706 silc_buffer_free(packet);
2710 silc_free(channel_id);
2711 silc_server_command_free(cmd);
2716 SilcSocketConnection sock;
2720 /* Quits connection to client. This gets called if client won't
2721 close the connection even when it has issued QUIT command. */
2723 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2725 QuitInternal q = (QuitInternal)context;
2727 /* Free all client specific data, such as client entry and entires
2728 on channels this client may be on. */
2729 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2731 q->sock->user_data = NULL;
2733 /* Close the connection on our side */
2734 silc_server_close_connection(q->server, q->sock);
2736 silc_free(q->signoff);
2740 /* Quits SILC session. This is the normal way to disconnect client. */
2742 SILC_SERVER_CMD_FUNC(quit)
2744 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2745 SilcServer server = cmd->server;
2746 SilcSocketConnection sock = cmd->sock;
2748 unsigned char *tmp = NULL;
2751 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2753 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2757 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2761 q = silc_calloc(1, sizeof(*q));
2764 q->signoff = tmp ? strdup(tmp) : NULL;
2766 /* We quit the connection with little timeout */
2767 silc_schedule_task_add(server->schedule, sock->sock,
2768 silc_server_command_quit_cb, (void *)q,
2769 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2772 silc_server_command_free(cmd);
2775 /* Server side of command KILL. This command is used by router operator
2776 to remove an client from the SILC Network temporarily. */
2778 SILC_SERVER_CMD_FUNC(kill)
2780 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2781 SilcServer server = cmd->server;
2782 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2783 SilcClientEntry remote_client;
2784 SilcClientID *client_id;
2785 unsigned char *tmp, *comment;
2786 SilcUInt32 tmp_len, tmp_len2;
2789 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2791 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2794 /* KILL command works only on router */
2795 if (server->server_type != SILC_ROUTER) {
2796 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2797 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
2801 /* Check whether client has the permissions. */
2802 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2803 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2804 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
2808 /* Get the client ID */
2809 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2811 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2812 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2816 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2818 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2819 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2824 /* Get the client entry */
2825 remote_client = silc_idlist_find_client_by_id(server->local_list,
2826 client_id, TRUE, NULL);
2828 if (!remote_client) {
2829 remote_client = silc_idlist_find_client_by_id(server->global_list,
2830 client_id, TRUE, NULL);
2832 if (!remote_client) {
2833 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2834 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2841 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2845 /* Send reply to the sender */
2846 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2849 /* Check if anyone is watching this nickname */
2850 if (server->server_type == SILC_ROUTER)
2851 silc_server_check_watcher_list(server, client, NULL,
2852 SILC_NOTIFY_TYPE_KILLED);
2854 /* Now do the killing */
2855 silc_server_kill_client(server, remote_client, comment, client->id,
2859 silc_server_command_free(cmd);
2862 /* Server side of command INFO. This sends information about us to
2863 the client. If client requested specific server we will send the
2864 command to that server. */
2866 SILC_SERVER_CMD_FUNC(info)
2868 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2869 SilcServer server = cmd->server;
2870 SilcBuffer packet, idp;
2873 char *dest_server, *server_info = NULL, *server_name;
2874 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2875 SilcServerEntry entry = NULL;
2876 SilcServerID *server_id = NULL;
2878 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2880 /* Get server name */
2881 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2884 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2886 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2888 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2889 SILC_STATUS_ERR_NO_SERVER_ID, 0);
2895 /* Check whether we have this server cached */
2896 entry = silc_idlist_find_server_by_id(server->local_list,
2897 server_id, TRUE, NULL);
2899 entry = silc_idlist_find_server_by_id(server->global_list,
2900 server_id, TRUE, NULL);
2901 if (!entry && server->server_type != SILC_SERVER) {
2902 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2903 SILC_STATUS_ERR_NO_SUCH_SERVER,
2910 /* Some buggy servers has sent request to router about themselves. */
2911 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2914 if ((!dest_server && !server_id && !entry) || (entry &&
2915 entry == server->id_entry) ||
2916 (dest_server && !cmd->pending &&
2917 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2918 /* Send our reply */
2919 char info_string[256];
2921 memset(info_string, 0, sizeof(info_string));
2922 snprintf(info_string, sizeof(info_string),
2923 "location: %s server: %s admin: %s <%s>",
2924 server->config->server_info->location,
2925 server->config->server_info->server_type,
2926 server->config->server_info->admin,
2927 server->config->server_info->email);
2929 server_info = info_string;
2930 entry = server->id_entry;
2932 /* Check whether we have this server cached */
2933 if (!entry && dest_server) {
2934 entry = silc_idlist_find_server_by_name(server->global_list,
2935 dest_server, TRUE, NULL);
2937 entry = silc_idlist_find_server_by_name(server->local_list,
2938 dest_server, TRUE, NULL);
2942 if (!cmd->pending &&
2943 server->server_type != SILC_SERVER && entry && !entry->server_info) {
2944 /* Send to the server */
2946 SilcUInt16 old_ident;
2948 old_ident = silc_command_get_ident(cmd->payload);
2949 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2950 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2952 silc_server_packet_send(server, entry->connection,
2953 SILC_PACKET_COMMAND, cmd->packet->flags,
2954 tmpbuf->data, tmpbuf->len, TRUE);
2956 /* Reprocess this packet after received reply from router */
2957 silc_server_command_pending(server, SILC_COMMAND_INFO,
2958 silc_command_get_ident(cmd->payload),
2959 silc_server_command_info,
2960 silc_server_command_dup(cmd));
2961 cmd->pending = TRUE;
2962 silc_command_set_ident(cmd->payload, old_ident);
2963 silc_buffer_free(tmpbuf);
2967 if (!entry && !cmd->pending && !server->standalone) {
2968 /* Send to the primary router */
2970 SilcUInt16 old_ident;
2972 old_ident = silc_command_get_ident(cmd->payload);
2973 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2974 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2976 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
2977 SILC_PACKET_COMMAND, cmd->packet->flags,
2978 tmpbuf->data, tmpbuf->len, TRUE);
2980 /* Reprocess this packet after received reply from router */
2981 silc_server_command_pending(server, SILC_COMMAND_INFO,
2982 silc_command_get_ident(cmd->payload),
2983 silc_server_command_info,
2984 silc_server_command_dup(cmd));
2985 cmd->pending = TRUE;
2986 silc_command_set_ident(cmd->payload, old_ident);
2987 silc_buffer_free(tmpbuf);
2992 silc_free(server_id);
2995 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2996 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3000 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
3002 server_info = entry->server_info;
3003 server_name = entry->server_name;
3005 /* Send the reply */
3006 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
3007 SILC_STATUS_OK, 0, ident, 3,
3008 2, idp->data, idp->len,
3010 strlen(server_name),
3013 strlen(server_info) : 0);
3014 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3015 packet->data, packet->len, FALSE);
3017 silc_buffer_free(packet);
3018 silc_buffer_free(idp);
3021 silc_server_command_free(cmd);
3024 /* Server side of command PING. This just replies to the ping. */
3026 SILC_SERVER_CMD_FUNC(ping)
3028 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3029 SilcServer server = cmd->server;
3034 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
3037 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
3039 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3040 SILC_STATUS_ERR_NO_SERVER_ID, 0);
3043 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
3047 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
3048 /* Send our reply */
3049 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3052 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3053 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3060 silc_server_command_free(cmd);
3063 /* Server side of command STATS. */
3065 SILC_SERVER_CMD_FUNC(stats)
3067 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3068 SilcServer server = cmd->server;
3069 SilcServerID *server_id;
3072 SilcBuffer packet, stats;
3073 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3076 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1);
3079 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3081 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3082 SILC_STATUS_ERR_NO_SERVER_ID, 0);
3085 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3089 /* The ID must be ours */
3090 if (!SILC_ID_SERVER_COMPARE(server->id, server_id)) {
3091 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3092 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3093 silc_free(server_id);
3096 silc_free(server_id);
3098 /* If we are router then just send everything we got. If we are normal
3099 server then we'll send this to our router to get all the latest
3100 statistical information. */
3101 if (!cmd->pending && server->server_type != SILC_ROUTER &&
3102 !server->standalone) {
3103 /* Send request to our router */
3104 SilcBuffer idp = silc_id_payload_encode(server->router->id,
3106 packet = silc_command_payload_encode_va(SILC_COMMAND_STATS,
3107 ++server->cmd_ident, 1,
3108 1, idp->data, idp->len);
3109 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
3110 SILC_PACKET_COMMAND, 0, packet->data,
3111 packet->len, FALSE);
3113 /* Reprocess this packet after received reply from router */
3114 silc_server_command_pending(server, SILC_COMMAND_STATS,
3116 silc_server_command_stats,
3117 silc_server_command_dup(cmd));
3118 cmd->pending = TRUE;
3119 silc_buffer_free(packet);
3120 silc_buffer_free(idp);
3124 /* Send our reply to sender */
3125 uptime = time(NULL) - server->starttime;
3127 stats = silc_buffer_alloc_size(60);
3128 silc_buffer_format(stats,
3129 SILC_STR_UI_INT(server->starttime),
3130 SILC_STR_UI_INT(uptime),
3131 SILC_STR_UI_INT(server->stat.my_clients),
3132 SILC_STR_UI_INT(server->stat.my_channels),
3133 SILC_STR_UI_INT(server->stat.my_server_ops),
3134 SILC_STR_UI_INT(server->stat.my_router_ops),
3135 SILC_STR_UI_INT(server->stat.cell_clients),
3136 SILC_STR_UI_INT(server->stat.cell_channels),
3137 SILC_STR_UI_INT(server->stat.cell_servers),
3138 SILC_STR_UI_INT(server->stat.clients),
3139 SILC_STR_UI_INT(server->stat.channels),
3140 SILC_STR_UI_INT(server->stat.servers),
3141 SILC_STR_UI_INT(server->stat.routers),
3142 SILC_STR_UI_INT(server->stat.server_ops),
3143 SILC_STR_UI_INT(server->stat.router_ops),
3146 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_STATS,
3147 SILC_STATUS_OK, 0, ident, 2,
3149 3, stats->data, stats->len);
3150 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
3151 0, packet->data, packet->len, FALSE);
3152 silc_buffer_free(packet);
3153 silc_buffer_free(stats);
3156 silc_server_command_free(cmd);
3159 /* Internal routine to join channel. The channel sent to this function
3160 has been either created or resolved from ID lists. This joins the sent
3161 client to the channel. */
3163 static void silc_server_command_join_channel(SilcServer server,
3164 SilcServerCommandContext cmd,
3165 SilcChannelEntry channel,
3166 SilcClientID *client_id,
3170 const unsigned char *auth,
3171 SilcUInt32 auth_len)
3173 SilcSocketConnection sock = cmd->sock;
3175 SilcUInt32 tmp_len, user_count;
3176 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
3177 SilcClientEntry client;
3178 SilcChannelClientEntry chl;
3179 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
3180 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3181 char check[512], check2[512];
3182 bool founder = FALSE;
3184 unsigned char *fkey = NULL;
3185 SilcUInt32 fkey_len = 0;
3187 SILC_LOG_DEBUG(("Joining client to channel"));
3192 /* Get the client entry */
3193 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3194 client = (SilcClientEntry)sock->user_data;
3196 client = silc_server_get_client_resolve(server, client_id, FALSE,
3203 silc_server_command_send_status_reply(
3204 cmd, SILC_COMMAND_JOIN,
3205 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3209 /* The client info is being resolved. Reprocess this packet after
3210 receiving the reply to the query. */
3211 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
3213 silc_server_command_join,
3214 silc_server_command_dup(cmd));
3215 cmd->pending = TRUE;
3219 cmd->pending = FALSE;
3223 * Check founder auth payload if provided. If client can gain founder
3224 * privileges it can override various conditions on joining the channel,
3225 * and can have directly the founder mode set on the channel.
3227 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3228 SilcIDListData idata = (SilcIDListData)client;
3229 SilcChannelClientEntry chl2;
3230 SilcHashTableList htl;
3232 if (channel->founder_key && idata->public_key &&
3233 silc_pkcs_public_key_compare(channel->founder_key,
3234 idata->public_key)) {
3235 /* Check whether the client is to become founder */
3236 if (silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
3237 channel->founder_key, 0, server->sha1hash,
3238 client->id, SILC_ID_CLIENT)) {
3240 /* There cannot be anyone else as founder on the channel now. This
3241 client is definitely the founder due to this authentication */
3242 silc_hash_table_list(channel->user_list, &htl);
3243 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
3244 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
3245 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3246 silc_server_force_cumode_change(server, NULL, channel, chl2,
3250 silc_hash_table_list_reset(&htl);
3252 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3259 * Check channel modes
3263 memset(check, 0, sizeof(check));
3264 memset(check2, 0, sizeof(check2));
3265 strncat(check, client->nickname, strlen(client->nickname));
3266 strncat(check, "!", 1);
3267 strncat(check, client->username, strlen(client->username));
3268 if (!strchr(client->username, '@')) {
3269 strncat(check, "@", 1);
3270 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3273 strncat(check2, client->nickname, strlen(client->nickname));
3274 if (!strchr(client->nickname, '@')) {
3275 strncat(check2, "@", 1);
3276 strncat(check2, server->server_name, strlen(server->server_name));
3278 strncat(check2, "!", 1);
3279 strncat(check2, client->username, strlen(client->username));
3280 if (!strchr(client->username, '@')) {
3281 strncat(check2, "@", 1);
3282 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3285 /* Check invite list if channel is invite-only channel */
3286 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3287 if (!channel->invite_list ||
3288 (!silc_string_match(channel->invite_list, check) &&
3289 !silc_string_match(channel->invite_list, check2))) {
3290 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3291 SILC_STATUS_ERR_NOT_INVITED, 0);
3296 /* Check ban list if it exists. If the client's nickname, server,
3297 username and/or hostname is in the ban list the access to the
3298 channel is denied. */
3299 if (channel->ban_list) {
3300 if (silc_string_match(channel->ban_list, check) ||
3301 silc_string_match(channel->ban_list, check2)) {
3302 silc_server_command_send_status_reply(
3303 cmd, SILC_COMMAND_JOIN,
3304 SILC_STATUS_ERR_BANNED_FROM_CHANNEL, 0);
3309 /* Check user count limit if set. */
3310 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3311 if (silc_hash_table_count(channel->user_list) + 1 >
3312 channel->user_limit) {
3313 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3314 SILC_STATUS_ERR_CHANNEL_IS_FULL,
3321 /* Check the channel passphrase if set. */
3322 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3323 /* Get passphrase */
3324 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3326 passphrase = silc_memdup(tmp, tmp_len);
3328 if (!passphrase || !channel->passphrase ||
3329 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3330 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3331 SILC_STATUS_ERR_BAD_PASSWORD, 0);
3337 * Client is allowed to join to the channel. Make it happen.
3340 /* Check whether the client already is on the channel */
3341 if (silc_server_client_on_channel(client, channel, NULL)) {
3342 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3343 SILC_STATUS_ERR_USER_ON_CHANNEL, 0);
3347 /* Generate new channel key as protocol dictates */
3349 if (!silc_server_create_channel_key(server, channel, 0))
3352 /* Send the channel key. This is broadcasted to the channel but is not
3353 sent to the client who is joining to the channel. */
3354 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3355 silc_server_send_channel_key(server, NULL, channel,
3356 server->server_type == SILC_ROUTER ?
3357 FALSE : !server->standalone);
3360 /* Join the client to the channel by adding it to channel's user list.
3361 Add also the channel to client entry's channels list for fast cross-
3363 chl = silc_calloc(1, sizeof(*chl));
3365 chl->client = client;
3366 chl->channel = channel;
3367 silc_hash_table_add(channel->user_list, client, chl);
3368 silc_hash_table_add(client->channels, channel, chl);
3369 channel->user_count++;
3370 channel->disabled = FALSE;
3372 /* Get users on the channel */
3373 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3376 /* Encode Client ID Payload of the original client who wants to join */
3377 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3379 /* Encode command reply packet */
3380 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3381 SILC_PUT32_MSB(channel->mode, mode);
3382 SILC_PUT32_MSB(created, tmp2);
3383 SILC_PUT32_MSB(user_count, tmp3);
3385 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3386 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3387 keyp = silc_channel_key_payload_encode(silc_id_get_len(channel->id,
3390 strlen(channel->channel_key->
3392 channel->channel_key->cipher->name,
3393 channel->key_len / 8, channel->key);
3397 if (channel->founder_key)
3398 fkey = silc_pkcs_public_key_encode(channel->founder_key, &fkey_len);
3401 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3402 SILC_STATUS_OK, 0, ident, 14,
3403 2, channel->channel_name,
3404 strlen(channel->channel_name),
3405 3, chidp->data, chidp->len,
3406 4, clidp->data, clidp->len,
3409 7, keyp ? keyp->data : NULL,
3410 keyp ? keyp->len : 0,
3411 8, channel->ban_list,
3413 strlen(channel->ban_list) : 0,
3414 9, channel->invite_list,
3415 channel->invite_list ?
3416 strlen(channel->invite_list) : 0,
3419 strlen(channel->topic) : 0,
3420 11, silc_hmac_get_name(channel->hmac),
3421 strlen(silc_hmac_get_name(channel->
3424 13, user_list->data, user_list->len,
3425 14, mode_list->data,
3427 15, fkey, fkey_len);
3429 /* Send command reply */
3430 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3431 reply->data, reply->len, FALSE);
3433 /* Send JOIN notify to locally connected clients on the channel. If
3434 we are normal server then router will send or have sent JOIN notify
3435 already. However since we've added the client already to our channel
3436 we'll ignore it (in packet_receive.c) so we must send it here. If
3437 we are router then this will send it to local clients and local
3439 SILC_LOG_DEBUG(("Send JOIN notify to channel"));
3440 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3441 SILC_NOTIFY_TYPE_JOIN, 2,
3442 clidp->data, clidp->len,
3443 chidp->data, chidp->len);
3445 /* Update statistics */
3446 server->stat.my_chanclients++;
3447 if (server->server_type == SILC_ROUTER) {
3448 server->stat.cell_chanclients++;
3449 server->stat.chanclients++;
3452 if (!cmd->pending) {
3453 /* Send JOIN notify packet to our primary router */
3454 silc_server_send_notify_join(server, SILC_PRIMARY_ROUTE(server),
3455 SILC_BROADCAST(server), channel, client->id);
3458 /* Distribute the channel key to all backup routers. */
3459 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3460 keyp->data, keyp->len, FALSE, TRUE);
3462 /* If client became founder by providing correct founder auth data
3463 notify the mode change to the channel. */
3465 SILC_PUT32_MSB(chl->mode, mode);
3466 SILC_LOG_DEBUG(("Send CUMODE_CHANGE notify to channel"));
3467 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3468 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
3469 clidp->data, clidp->len,
3470 mode, 4, clidp->data, clidp->len,
3475 /* Set CUMODE notify type to network */
3477 silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
3478 SILC_BROADCAST(server), channel,
3479 chl->mode, client->id, SILC_ID_CLIENT,
3480 client->id, channel->founder_key);
3482 silc_buffer_free(reply);
3483 silc_buffer_free(clidp);
3484 silc_buffer_free(chidp);
3485 silc_buffer_free(keyp);
3486 silc_buffer_free(user_list);
3487 silc_buffer_free(mode_list);
3491 silc_free(passphrase);
3494 /* Server side of command JOIN. Joins client into requested channel. If
3495 the channel does not exist it will be created. */
3497 SILC_SERVER_CMD_FUNC(join)
3499 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3500 SilcServer server = cmd->server;
3501 unsigned char *auth;
3502 SilcUInt32 tmp_len, auth_len;
3503 char *tmp, *channel_name = NULL, *cipher, *hmac;
3504 SilcChannelEntry channel;
3505 SilcUInt32 umode = 0;
3506 bool created = FALSE, create_key = TRUE;
3507 SilcClientID *client_id;
3509 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3511 /* Get channel name */
3512 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3514 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3515 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3522 channel_name[255] = '\0';
3524 if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
3525 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3526 SILC_STATUS_ERR_BAD_CHANNEL, 0);
3530 /* Get Client ID of the client who is joining to the channel */
3531 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3533 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3534 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3538 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3540 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3541 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3546 /* Get cipher, hmac name and auth payload */
3547 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3548 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3549 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3551 /* See if the channel exists */
3552 channel = silc_idlist_find_channel_by_name(server->local_list,
3553 channel_name, NULL);
3555 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3556 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3557 silc_free(client_id);
3558 client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
3561 (channel->disabled && server->server_type != SILC_ROUTER)) {
3562 /* Channel not found */
3564 /* If we are standalone server we don't have a router, we just create
3565 the channel by ourselves. */
3566 if (server->standalone) {
3567 channel = silc_server_create_new_channel(server, server->id, cipher,
3568 hmac, channel_name, TRUE);
3570 silc_server_command_send_status_reply(
3571 cmd, SILC_COMMAND_JOIN,
3572 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
3574 silc_free(client_id);
3578 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3584 /* The channel does not exist on our server. If we are normal server
3585 we will send JOIN command to our router which will handle the
3586 joining procedure (either creates the channel if it doesn't exist
3587 or joins the client to it). */
3588 if (server->server_type != SILC_ROUTER) {
3590 SilcUInt16 old_ident;
3592 /* If this is pending command callback then we've resolved
3593 it and it didn't work, return since we've notified the
3594 client already in the command reply callback. */
3596 silc_free(client_id);
3600 old_ident = silc_command_get_ident(cmd->payload);
3601 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3602 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3604 /* Send JOIN command to our router */
3605 silc_server_packet_send(server, (SilcSocketConnection)
3606 SILC_PRIMARY_ROUTE(server),
3607 SILC_PACKET_COMMAND, cmd->packet->flags,
3608 tmpbuf->data, tmpbuf->len, TRUE);
3610 /* Reprocess this packet after received reply from router */
3611 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3612 silc_command_get_ident(cmd->payload),
3613 silc_server_command_join,
3614 silc_server_command_dup(cmd));
3615 cmd->pending = TRUE;
3616 silc_command_set_ident(cmd->payload, old_ident);
3617 silc_buffer_free(tmpbuf);
3618 silc_free(client_id);
3622 /* We are router and the channel does not seem exist so we will check
3623 our global list as well for the channel. */
3624 channel = silc_idlist_find_channel_by_name(server->global_list,
3625 channel_name, NULL);
3627 /* Channel really does not exist, create it */
3628 channel = silc_server_create_new_channel(server, server->id, cipher,
3629 hmac, channel_name, TRUE);
3631 silc_server_command_send_status_reply(
3632 cmd, SILC_COMMAND_JOIN,
3633 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
3634 silc_free(client_id);
3638 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3646 /* Channel not found */
3648 /* If the command came from router and we are normal server then
3649 something went wrong with the joining as the channel was not found.
3650 We can't do anything else but ignore this. */
3651 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3652 server->server_type != SILC_ROUTER) {
3653 silc_free(client_id);
3657 /* We are router and the channel does not seem exist so we will check
3658 our global list as well for the channel. */
3659 channel = silc_idlist_find_channel_by_name(server->global_list,
3660 channel_name, NULL);
3662 /* Channel really does not exist, create it */
3663 channel = silc_server_create_new_channel(server, server->id, cipher,
3664 hmac, channel_name, TRUE);
3666 silc_server_command_send_status_reply(
3667 cmd, SILC_COMMAND_JOIN,
3668 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
3669 silc_free(client_id);
3673 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3680 /* Check whether the channel was created by our router */
3681 if (cmd->pending && context2) {
3682 SilcServerCommandReplyContext reply = context2;
3684 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3685 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3686 SILC_GET32_MSB(created, tmp);
3687 if (silc_argument_get_arg_type(reply->args, 7, NULL))
3688 create_key = FALSE; /* Router returned the key already */
3690 if (silc_command_get_status(reply->payload, NULL, NULL) &&
3691 channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3692 /* Save channel passphrase, if user provided it successfully */
3695 pa = silc_argument_get_arg_type(cmd->args, 3, &pa_len);
3697 silc_free(channel->passphrase);
3698 channel->passphrase = silc_memdup(pa, pa_len);
3703 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
3704 !channel->disabled && !silc_hash_table_count(channel->user_list))
3708 /* If the channel does not have global users and is also empty the client
3709 will be the channel founder and operator. */
3710 if (!channel->disabled &&
3711 !channel->global_users && !silc_hash_table_count(channel->user_list))
3712 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3714 /* Join to the channel */
3715 silc_server_command_join_channel(server, cmd, channel, client_id,
3716 created, create_key, umode,
3719 silc_free(client_id);
3722 silc_server_command_free(cmd);
3725 /* Server side of command MOTD. Sends server's current "message of the
3726 day" to the client. */
3728 SILC_SERVER_CMD_FUNC(motd)
3730 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3731 SilcServer server = cmd->server;
3732 SilcBuffer packet, idp;
3733 char *motd, *dest_server;
3734 SilcUInt32 motd_len;
3735 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3737 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3739 /* Get server name */
3740 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3742 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3743 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3747 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3750 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3752 if (server->config && server->config->server_info &&
3753 server->config->server_info->motd_file) {
3755 motd = silc_file_readfile(server->config->server_info->motd_file,
3761 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3768 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3774 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3775 packet->data, packet->len, FALSE);
3776 silc_buffer_free(packet);
3777 silc_buffer_free(idp);
3779 SilcServerEntry entry;
3781 /* Check whether we have this server cached */
3782 entry = silc_idlist_find_server_by_name(server->global_list,
3783 dest_server, TRUE, NULL);
3785 entry = silc_idlist_find_server_by_name(server->local_list,
3786 dest_server, TRUE, NULL);
3789 if (server->server_type != SILC_SERVER && !cmd->pending &&
3790 entry && !entry->motd) {
3791 /* Send to the server */
3793 SilcUInt16 old_ident;
3795 old_ident = silc_command_get_ident(cmd->payload);
3796 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3797 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3799 silc_server_packet_send(server, entry->connection,
3800 SILC_PACKET_COMMAND, cmd->packet->flags,
3801 tmpbuf->data, tmpbuf->len, TRUE);
3803 /* Reprocess this packet after received reply from router */
3804 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3805 silc_command_get_ident(cmd->payload),
3806 silc_server_command_motd,
3807 silc_server_command_dup(cmd));
3808 cmd->pending = TRUE;
3809 silc_command_set_ident(cmd->payload, old_ident);
3810 silc_buffer_free(tmpbuf);
3814 if (!entry && !cmd->pending && !server->standalone) {
3815 /* Send to the primary router */
3817 SilcUInt16 old_ident;
3819 old_ident = silc_command_get_ident(cmd->payload);
3820 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3821 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3823 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
3824 SILC_PACKET_COMMAND, cmd->packet->flags,
3825 tmpbuf->data, tmpbuf->len, TRUE);
3827 /* Reprocess this packet after received reply from router */
3828 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3829 silc_command_get_ident(cmd->payload),
3830 silc_server_command_motd,
3831 silc_server_command_dup(cmd));
3832 cmd->pending = TRUE;
3833 silc_command_set_ident(cmd->payload, old_ident);
3834 silc_buffer_free(tmpbuf);
3839 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3840 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3844 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3845 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3846 SILC_STATUS_OK, 0, ident, 2,
3850 strlen(entry->motd) : 0);
3851 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3852 packet->data, packet->len, FALSE);
3853 silc_buffer_free(packet);
3854 silc_buffer_free(idp);
3858 silc_server_command_free(cmd);
3861 /* Server side of command UMODE. Client can use this command to set/unset
3862 user mode. Client actually cannot set itself to be as server/router
3863 operator so this can be used only to unset the modes. */
3865 SILC_SERVER_CMD_FUNC(umode)
3867 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3868 SilcServer server = cmd->server;
3869 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3871 unsigned char *tmp_mask, m[4];
3872 SilcUInt32 mask = 0;
3873 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3874 bool set_mask = FALSE;
3876 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3879 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2);
3881 /* Get the client's mode mask */
3882 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3884 SILC_GET32_MSB(mask, tmp_mask);
3889 /* Check that mode changing is allowed. */
3890 if (!silc_server_check_umode_rights(server, client, mask)) {
3891 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3892 SILC_STATUS_ERR_PERM_DENIED, 0);
3896 /* Anonymous mode cannot be set by client */
3897 if (mask & SILC_UMODE_ANONYMOUS) {
3898 if (!(client->mode & SILC_UMODE_ANONYMOUS)) {
3899 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3900 SILC_STATUS_ERR_PERM_DENIED, 0);
3904 if (client->mode & SILC_UMODE_ANONYMOUS) {
3905 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3906 SILC_STATUS_ERR_PERM_DENIED, 0);
3911 /* Update statistics */
3912 if (mask & SILC_UMODE_GONE) {
3913 if (!(client->mode & SILC_UMODE_GONE))
3914 server->stat.my_aways++;
3916 if (client->mode & SILC_UMODE_GONE)
3917 server->stat.my_aways--;
3920 /* Change the mode */
3921 client->mode = mask;
3923 /* Send UMODE change to primary router */
3924 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
3925 SILC_BROADCAST(server), client->id,
3928 /* Check if anyone is watching this nickname */
3929 if (server->server_type == SILC_ROUTER)
3930 silc_server_check_watcher_list(server, client, NULL,
3931 SILC_NOTIFY_TYPE_UMODE_CHANGE);
3934 /* Send command reply to sender */
3935 SILC_PUT32_MSB(client->mode, m);
3936 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3937 SILC_STATUS_OK, 0, ident, 1,
3939 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3940 packet->data, packet->len, FALSE);
3941 silc_buffer_free(packet);
3944 silc_server_command_free(cmd);
3947 /* Server side command of CMODE. Changes channel mode */
3949 SILC_SERVER_CMD_FUNC(cmode)
3951 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3952 SilcServer server = cmd->server;
3953 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3954 SilcIDListData idata = (SilcIDListData)client;
3955 SilcChannelID *channel_id = NULL;
3956 SilcChannelEntry channel;
3957 SilcChannelClientEntry chl;
3958 SilcBuffer packet, cidp;
3959 unsigned char *tmp, *tmp_id, *tmp_mask;
3960 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3961 SilcUInt32 mode_mask = 0, old_mask = 0, tmp_len, tmp_len2;
3962 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3963 bool set_mask = FALSE;
3964 SilcPublicKey founder_key = NULL;
3965 unsigned char *fkey = NULL;
3966 SilcUInt32 fkey_len = 0;
3968 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 7);
3970 /* Get Channel ID */
3971 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3973 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3974 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3975 silc_server_command_free(cmd);
3978 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
3980 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3981 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3982 silc_server_command_free(cmd);
3986 /* Get channel entry */
3987 channel = silc_idlist_find_channel_by_id(server->local_list,
3990 channel = silc_idlist_find_channel_by_id(server->global_list,
3993 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3994 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
3996 silc_free(channel_id);
3997 silc_server_command_free(cmd);
4001 old_mask = channel->mode;
4003 /* Get the channel mode mask */
4004 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4006 SILC_GET32_MSB(mode_mask, tmp_mask);
4010 /* Check whether this client is on the channel */
4011 if (!silc_server_client_on_channel(client, channel, &chl)) {
4012 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4013 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4017 /* Check that client has rights to change any requested channel modes */
4018 if (set_mask && !silc_server_check_cmode_rights(server, channel, chl,
4020 SILC_LOG_DEBUG(("Client does not have rights to change mode"));
4021 silc_server_command_send_status_reply(
4022 cmd, SILC_COMMAND_CMODE,
4023 (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) ?
4024 SILC_STATUS_ERR_NO_CHANNEL_PRIV :
4025 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV), 0);
4029 /* If mode mask was not sent as argument then merely return the current
4030 mode mask to the sender. */
4033 SILC_PUT32_MSB(channel->mode, m);
4034 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4035 SILC_STATUS_OK, 0, ident, 2,
4036 2, tmp_id, tmp_len2,
4038 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4039 packet->data, packet->len, FALSE);
4040 silc_buffer_free(packet);
4045 * Check the modes. Modes that requires nothing special operation are
4049 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
4050 /* Channel uses private keys to protect traffic. Client(s) has set the
4051 key locally they want to use, server does not know that key. */
4052 /* Nothing interesting to do here */
4054 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
4055 /* The mode is removed and we need to generate and distribute
4056 new channel key. Clients are not using private channel keys
4057 anymore after this. */
4059 /* Re-generate channel key */
4060 if (!silc_server_create_channel_key(server, channel, 0))
4063 /* Send the channel key. This sends it to our local clients and if
4064 we are normal server to our router as well. */
4065 silc_server_send_channel_key(server, NULL, channel,
4066 server->server_type == SILC_ROUTER ?
4067 FALSE : !server->standalone);
4069 cipher = channel->channel_key->cipher->name;
4070 hmac = (char *)silc_hmac_get_name(channel->hmac);
4074 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
4075 /* User limit is set on channel */
4076 SilcUInt32 user_limit;
4078 /* Get user limit */
4079 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
4081 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
4082 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4083 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4087 SILC_GET32_MSB(user_limit, tmp);
4088 channel->user_limit = user_limit;
4091 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
4092 /* User limit mode is unset. Remove user limit */
4093 channel->user_limit = 0;
4096 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
4097 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
4098 /* Passphrase has been set to channel */
4100 /* Get the passphrase */
4101 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
4103 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4104 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4108 /* Save the passphrase */
4109 passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
4112 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
4113 /* Passphrase mode is unset. remove the passphrase */
4114 silc_free(channel->passphrase);
4115 channel->passphrase = NULL;
4119 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
4120 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
4121 /* Cipher to use protect the traffic */
4122 SilcCipher newkey, oldkey;
4125 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
4127 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4128 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4132 /* Delete old cipher and allocate the new one */
4133 if (!silc_cipher_alloc(cipher, &newkey)) {
4134 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4135 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4139 oldkey = channel->channel_key;
4140 channel->channel_key = newkey;
4142 /* Re-generate channel key */
4143 if (!silc_server_create_channel_key(server, channel, 0)) {
4144 /* We don't have new key, revert to old one */
4145 channel->channel_key = oldkey;
4149 /* Remove old channel key for good */
4150 silc_cipher_free(oldkey);
4152 /* Send the channel key. This sends it to our local clients and if
4153 we are normal server to our router as well. */
4154 silc_server_send_channel_key(server, NULL, channel,
4155 server->server_type == SILC_ROUTER ?
4156 FALSE : !server->standalone);
4159 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
4160 /* Cipher mode is unset. Remove the cipher and revert back to
4162 SilcCipher newkey, oldkey;
4163 cipher = channel->cipher;
4165 /* Delete old cipher and allocate default one */
4166 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
4167 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4168 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4172 oldkey = channel->channel_key;
4173 channel->channel_key = newkey;
4175 /* Re-generate channel key */
4176 if (!silc_server_create_channel_key(server, channel, 0)) {
4177 /* We don't have new key, revert to old one */
4178 channel->channel_key = oldkey;
4182 /* Remove old channel key for good */
4183 silc_cipher_free(oldkey);
4185 /* Send the channel key. This sends it to our local clients and if
4186 we are normal server to our router as well. */
4187 silc_server_send_channel_key(server, NULL, channel,
4188 server->server_type == SILC_ROUTER ?
4189 FALSE : !server->standalone);
4193 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
4194 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
4195 /* HMAC to use protect the traffic */
4196 unsigned char hash[32];
4200 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4202 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4203 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4207 /* Delete old hmac and allocate the new one */
4208 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4209 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4210 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4214 silc_hmac_free(channel->hmac);
4215 channel->hmac = newhmac;
4217 /* Set the HMAC key out of current channel key. The client must do
4219 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4220 channel->key_len / 8, hash);
4221 silc_hmac_set_key(channel->hmac, hash,
4222 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4223 memset(hash, 0, sizeof(hash));
4226 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4227 /* Hmac mode is unset. Remove the hmac and revert back to
4230 unsigned char hash[32];
4231 hmac = channel->hmac_name;
4233 /* Delete old hmac and allocate default one */
4234 silc_hmac_free(channel->hmac);
4235 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4236 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4237 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4241 silc_hmac_free(channel->hmac);
4242 channel->hmac = newhmac;
4244 /* Set the HMAC key out of current channel key. The client must do
4246 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4247 channel->key_len / 8,
4249 silc_hmac_set_key(channel->hmac, hash,
4250 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4251 memset(hash, 0, sizeof(hash));
4255 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4256 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4257 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4258 /* Set the founder authentication */
4259 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4261 silc_server_command_send_status_reply(
4262 cmd, SILC_COMMAND_CMODE,
4263 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4267 /* Verify the payload before setting the mode */
4268 if (!silc_auth_verify_data(tmp, tmp_len, SILC_AUTH_PUBLIC_KEY,
4269 idata->public_key, 0, server->sha1hash,
4270 client->id, SILC_ID_CLIENT)) {
4271 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4272 SILC_STATUS_ERR_AUTH_FAILED,
4277 /* Save the public key */
4278 channel->founder_key = silc_pkcs_public_key_copy(idata->public_key);
4279 if (!channel->founder_key) {
4280 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4281 SILC_STATUS_ERR_AUTH_FAILED,
4286 founder_key = channel->founder_key;
4287 fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
4289 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4290 SILC_STATUS_ERR_AUTH_FAILED,
4297 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4298 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4299 if (channel->founder_key)
4300 silc_pkcs_public_key_free(channel->founder_key);
4301 channel->founder_key = NULL;
4306 /* Finally, set the mode */
4307 old_mask = channel->mode = mode_mask;
4309 /* Send CMODE_CHANGE notify. */
4310 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4311 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4312 SILC_NOTIFY_TYPE_CMODE_CHANGE, 6,
4313 cidp->data, cidp->len,
4315 cipher, cipher ? strlen(cipher) : 0,
4316 hmac, hmac ? strlen(hmac) : 0,
4317 passphrase, passphrase ?
4318 strlen(passphrase) : 0,
4321 /* Set CMODE notify type to network */
4322 silc_server_send_notify_cmode(server, SILC_PRIMARY_ROUTE(server),
4323 SILC_BROADCAST(server), channel,
4324 mode_mask, client->id, SILC_ID_CLIENT,
4325 cipher, hmac, passphrase, founder_key);
4327 /* Send command reply to sender */
4328 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4329 SILC_STATUS_OK, 0, ident, 2,
4330 2, tmp_id, tmp_len2,
4332 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4333 packet->data, packet->len, FALSE);
4335 silc_buffer_free(packet);
4336 silc_buffer_free(cidp);
4339 channel->mode = old_mask;
4341 silc_free(channel_id);
4342 silc_server_command_free(cmd);
4345 /* Server side of CUMODE command. Changes client's mode on a channel. */
4347 SILC_SERVER_CMD_FUNC(cumode)
4349 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4350 SilcServer server = cmd->server;
4351 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4352 SilcIDListData idata = (SilcIDListData)client;
4353 SilcChannelID *channel_id;
4354 SilcClientID *client_id;
4355 SilcChannelEntry channel;
4356 SilcClientEntry target_client;
4357 SilcChannelClientEntry chl;
4358 SilcBuffer packet, idp;
4359 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4360 SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4362 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4363 SilcPublicKey founder_key = NULL;
4364 unsigned char *fkey = NULL;
4365 SilcUInt32 fkey_len = 0;
4367 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4369 /* Get Channel ID */
4370 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4372 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4373 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4376 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
4378 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4379 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4383 /* Get channel entry */
4384 channel = silc_idlist_find_channel_by_id(server->local_list,
4387 channel = silc_idlist_find_channel_by_id(server->global_list,
4390 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4391 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4397 /* Check whether sender is on the channel */
4398 if (!silc_server_client_on_channel(client, channel, &chl)) {
4399 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4400 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4403 sender_mask = chl->mode;
4405 /* Get the target client's channel mode mask */
4406 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4408 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4409 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4413 SILC_GET32_MSB(target_mask, tmp_mask);
4415 /* Get target Client ID */
4416 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4418 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4419 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4422 client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
4424 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4425 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4429 /* Get target client's entry */
4430 target_client = silc_idlist_find_client_by_id(server->local_list,
4431 client_id, TRUE, NULL);
4432 if (!target_client) {
4433 target_client = silc_idlist_find_client_by_id(server->global_list,
4434 client_id, TRUE, NULL);
4437 if (target_client != client &&
4438 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4439 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4440 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4441 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
4445 /* Check whether target client is on the channel */
4446 if (target_client != client) {
4447 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4448 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4449 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL, 0);
4458 /* If the target client is founder, no one else can change their mode
4460 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4461 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4462 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
4467 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4468 if (target_client != client) {
4469 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4470 SILC_STATUS_ERR_NOT_YOU, 0);
4474 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4475 /* The client tries to claim the founder rights. */
4476 unsigned char *tmp_auth;
4477 SilcUInt32 tmp_auth_len;
4478 SilcChannelClientEntry chl2;
4479 SilcHashTableList htl;
4481 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4482 !channel->founder_key || !idata->public_key ||
4483 !silc_pkcs_public_key_compare(channel->founder_key,
4484 idata->public_key)) {
4485 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4486 SILC_STATUS_ERR_AUTH_FAILED, 0);
4490 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4492 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4493 SILC_STATUS_ERR_AUTH_FAILED, 0);
4497 /* Verify the authentication payload */
4498 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len, SILC_AUTH_PUBLIC_KEY,
4499 channel->founder_key, 0, server->sha1hash,
4500 client->id, SILC_ID_CLIENT)) {
4501 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4502 SILC_STATUS_ERR_AUTH_FAILED, 0);
4507 founder_key = channel->founder_key;
4508 fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
4510 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4511 SILC_STATUS_ERR_AUTH_FAILED, 0);
4515 /* There cannot be anyone else as founder on the channel now. This
4516 client is definitely the founder due to this authentication */
4517 silc_hash_table_list(channel->user_list, &htl);
4518 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
4519 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
4520 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4521 silc_server_force_cumode_change(server, NULL, channel, chl2,
4525 silc_hash_table_list_reset(&htl);
4527 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4530 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4531 if (target_client == client) {
4532 /* Remove channel founder rights from itself */
4533 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4536 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4537 SILC_STATUS_ERR_NOT_YOU, 0);
4543 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4544 /* Promote to operator */
4545 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4546 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4547 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4548 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4549 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
4554 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4558 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4559 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4560 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4561 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4562 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
4567 /* Demote to normal user */
4568 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4573 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4574 if (target_client != client) {
4575 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4576 SILC_STATUS_ERR_NOT_YOU, 0);
4580 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
4581 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4585 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4586 if (target_client != client) {
4587 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4588 SILC_STATUS_ERR_NOT_YOU, 0);
4592 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4597 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4598 if (target_client != client) {
4599 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4600 SILC_STATUS_ERR_NOT_YOU, 0);
4604 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)) {
4605 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4609 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4610 if (target_client != client) {
4611 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4612 SILC_STATUS_ERR_NOT_YOU, 0);
4616 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4621 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4622 if (target_client != client) {
4623 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4624 SILC_STATUS_ERR_NOT_YOU, 0);
4628 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)) {
4629 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4633 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4634 if (target_client != client) {
4635 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4636 SILC_STATUS_ERR_NOT_YOU, 0);
4640 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4645 if (target_mask & SILC_CHANNEL_UMODE_QUIET) {
4646 if (!(chl->mode & SILC_CHANNEL_UMODE_QUIET)) {
4647 if (client == target_client) {
4648 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4649 SILC_STATUS_ERR_PERM_DENIED, 0);
4652 chl->mode |= SILC_CHANNEL_UMODE_QUIET;
4656 if (chl->mode & SILC_CHANNEL_UMODE_QUIET) {
4657 if (client == target_client) {
4658 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4659 SILC_STATUS_ERR_PERM_DENIED, 0);
4662 chl->mode &= ~SILC_CHANNEL_UMODE_QUIET;
4667 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4668 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4670 /* Send notify to channel, notify only if mode was actually changed. */
4672 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4673 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
4674 idp->data, idp->len,
4679 /* Set CUMODE notify type to network */
4680 silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
4681 SILC_BROADCAST(server), channel,
4682 target_mask, client->id, SILC_ID_CLIENT,
4683 target_client->id, founder_key);
4686 /* Send command reply to sender */
4687 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4688 SILC_STATUS_OK, 0, ident, 3,
4690 3, tmp_ch_id, tmp_ch_len,
4691 4, tmp_id, tmp_len);
4692 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4693 packet->data, packet->len, FALSE);
4695 silc_buffer_free(packet);
4696 silc_free(channel_id);
4697 silc_free(client_id);
4698 silc_buffer_free(idp);
4702 silc_server_command_free(cmd);
4705 /* Server side of KICK command. Kicks client out of channel. */
4707 SILC_SERVER_CMD_FUNC(kick)
4709 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4710 SilcServer server = cmd->server;
4711 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4712 SilcClientEntry target_client;
4713 SilcChannelID *channel_id;
4714 SilcClientID *client_id;
4715 SilcChannelEntry channel;
4716 SilcChannelClientEntry chl;
4718 SilcUInt32 tmp_len, target_idp_len;
4719 unsigned char *tmp, *comment, *target_idp;
4721 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4723 /* Get Channel ID */
4724 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4726 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4727 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4730 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4732 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4733 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4737 /* Get channel entry */
4738 channel = silc_idlist_find_channel_by_id(server->local_list,
4741 channel = silc_idlist_find_channel_by_id(server->local_list,
4744 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4745 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4751 /* Check whether sender is on the channel */
4752 if (!silc_server_client_on_channel(client, channel, &chl)) {
4753 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4754 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4758 /* Check that the kicker is channel operator or channel founder */
4759 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
4760 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4761 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4762 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
4766 /* Get target Client ID */
4767 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4769 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4770 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4773 client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
4775 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4776 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4780 /* Get target client's entry */
4781 target_client = silc_idlist_find_client_by_id(server->local_list,
4782 client_id, TRUE, NULL);
4783 if (!target_client) {
4784 target_client = silc_idlist_find_client_by_id(server->global_list,
4785 client_id, TRUE, NULL);
4788 /* Check whether target client is on the channel */
4789 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4790 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4791 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL,
4796 /* Check that the target client is not channel founder. Channel founder
4797 cannot be kicked from the channel. */
4798 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4799 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4800 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
4807 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4811 /* Send command reply to sender */
4812 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4815 /* Send KICKED notify to local clients on the channel */
4816 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4817 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4818 SILC_NOTIFY_TYPE_KICKED, 3,
4819 target_idp, target_idp_len,
4820 comment, comment ? strlen(comment) : 0,
4821 idp->data, idp->len);
4822 silc_buffer_free(idp);
4824 /* Send KICKED notify to primary route */
4825 silc_server_send_notify_kicked(server, SILC_PRIMARY_ROUTE(server),
4826 SILC_BROADCAST(server), channel,
4827 target_client->id, client->id, comment);
4829 /* Remove the client from the channel. If the channel does not exist
4830 after removing the client then the client kicked itself off the channel
4831 and we don't have to send anything after that. */
4832 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4833 target_client, FALSE))
4836 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4837 /* Re-generate channel key */
4838 if (!silc_server_create_channel_key(server, channel, 0))
4841 /* Send the channel key to the channel. The key of course is not sent
4842 to the client who was kicked off the channel. */
4843 silc_server_send_channel_key(server, target_client->connection, channel,
4844 server->server_type == SILC_ROUTER ?
4845 FALSE : !server->standalone);
4849 silc_server_command_free(cmd);
4852 /* Server side of OPER command. Client uses this comand to obtain server
4853 operator privileges to this server/router. */
4855 SILC_SERVER_CMD_FUNC(oper)
4857 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4858 SilcServer server = cmd->server;
4859 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4860 unsigned char *username, *auth;
4862 SilcServerConfigAdmin *admin;
4863 SilcIDListData idata = (SilcIDListData)client;
4864 bool result = FALSE;
4865 SilcPublicKey cached_key;
4867 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4869 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4872 /* Get the username */
4873 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4875 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4876 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4881 /* Get the admin configuration */
4882 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4883 username, client->nickname);
4885 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4886 username, client->nickname);
4888 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4889 SILC_STATUS_ERR_AUTH_FAILED,
4895 /* Get the authentication payload */
4896 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4898 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4899 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4904 /* Verify the authentication data. If both passphrase and public key
4905 is set then try both of them. */
4906 if (admin->passphrase)
4907 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4908 admin->passphrase, admin->passphrase_len,
4909 idata->hash, client->id, SILC_ID_CLIENT);
4910 if (!result && admin->publickeys) {
4911 cached_key = silc_server_get_public_key(server, admin->publickeys);
4914 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4915 cached_key, 0, idata->hash,
4916 client->id, SILC_ID_CLIENT);
4919 /* Authentication failed */
4920 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4921 SILC_STATUS_ERR_AUTH_FAILED,
4926 /* Client is now server operator */
4927 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4929 /* Update statistics */
4930 if (client->connection)
4931 server->stat.my_server_ops++;
4932 if (server->server_type == SILC_ROUTER)
4933 server->stat.server_ops++;
4935 /* Send UMODE change to primary router */
4936 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
4937 SILC_BROADCAST(server), client->id,
4940 /* Check if anyone is watching this nickname */
4941 if (server->server_type == SILC_ROUTER)
4942 silc_server_check_watcher_list(server, client, NULL,
4943 SILC_NOTIFY_TYPE_UMODE_CHANGE);
4945 /* Send reply to the sender */
4946 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4950 silc_server_command_free(cmd);
4953 SILC_TASK_CALLBACK(silc_server_command_detach_cb)
4955 QuitInternal q = (QuitInternal)context;
4956 SilcClientID *client_id = (SilcClientID *)q->sock;
4957 SilcClientEntry client;
4958 SilcSocketConnection sock;
4960 client = silc_idlist_find_client_by_id(q->server->local_list, client_id,
4962 if (client && client->connection) {
4963 sock = client->connection;
4965 /* If there is pending outgoing data for the client then purge it
4966 to the network before closing connection. */
4967 silc_server_packet_queue_purge(q->server, sock);
4969 /* Close the connection on our side */
4970 client->router = NULL;
4971 client->connection = NULL;
4972 sock->user_data = NULL;
4973 silc_server_close_connection(q->server, sock);
4976 silc_free(client_id);
4980 SILC_TASK_CALLBACK(silc_server_command_detach_timeout)
4982 QuitInternal q = (QuitInternal)context;
4983 SilcClientID *client_id = (SilcClientID *)q->sock;
4984 SilcClientEntry client;
4986 client = silc_idlist_find_client_by_id(q->server->local_list, client_id,
4988 if (client && client->mode & SILC_UMODE_DETACHED) {
4989 SILC_LOG_DEBUG(("Detach timeout"));
4990 silc_server_free_client_data(q->server, NULL, client, TRUE,
4994 silc_free(client_id);
4998 /* Server side of DETACH command. Detached the client from the network
4999 by closing the connection but preserving the session. */
5001 SILC_SERVER_CMD_FUNC(detach)
5003 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5004 SilcServer server = cmd->server;
5005 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5008 if (server->config->detach_disabled) {
5009 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
5010 SILC_STATUS_ERR_UNKNOWN_COMMAND, 0);
5014 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5017 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
5019 /* Remove operator privileges, since the client may resume in some
5020 other server which to it does not have operator privileges. */
5021 client->mode &= ~(SILC_UMODE_SERVER_OPERATOR |
5022 SILC_UMODE_ROUTER_OPERATOR);
5024 /* Send the user mode notify to notify that client is detached */
5025 client->mode |= SILC_UMODE_DETACHED;
5026 client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
5027 client->last_command = 0;
5028 client->fast_command = 0;
5029 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
5030 SILC_BROADCAST(server), client->id,
5032 server->stat.my_detached++;
5034 /* Check if anyone is watching this nickname */
5035 if (server->server_type == SILC_ROUTER)
5036 silc_server_check_watcher_list(server, client, NULL,
5037 SILC_NOTIFY_TYPE_UMODE_CHANGE);
5039 q = silc_calloc(1, sizeof(*q));
5041 q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
5042 silc_schedule_task_add(server->schedule, 0, silc_server_command_detach_cb,
5043 q, 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
5045 if (server->config->detach_timeout) {
5046 q = silc_calloc(1, sizeof(*q));
5048 q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
5049 silc_schedule_task_add(server->schedule, 0,
5050 silc_server_command_detach_timeout,
5051 q, server->config->detach_timeout * 60,
5052 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
5055 /* Send reply to the sender */
5056 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
5060 silc_server_command_free(cmd);
5063 /* Server side of WATCH command. */
5065 SILC_SERVER_CMD_FUNC(watch)
5067 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5068 SilcServer server = cmd->server;
5069 char *add_nick, *del_nick;
5070 SilcUInt32 add_nick_len, del_nick_len, tmp_len;
5072 unsigned char hash[16], *tmp;
5073 SilcClientEntry client;
5074 SilcClientID *client_id = NULL;
5076 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WATCH, cmd, 1, 3);
5078 if (server->server_type == SILC_SERVER && !server->standalone) {
5079 if (!cmd->pending) {
5080 /* Send the command to router */
5082 SilcUInt16 old_ident;
5084 old_ident = silc_command_get_ident(cmd->payload);
5085 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5086 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5088 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5089 SILC_PACKET_COMMAND, cmd->packet->flags,
5090 tmpbuf->data, tmpbuf->len, TRUE);
5092 /* Reprocess this packet after received reply from router */
5093 silc_server_command_pending(server, SILC_COMMAND_WATCH,
5094 silc_command_get_ident(cmd->payload),
5095 silc_server_command_watch,
5096 silc_server_command_dup(cmd));
5097 cmd->pending = TRUE;
5098 silc_command_set_ident(cmd->payload, old_ident);
5099 silc_buffer_free(tmpbuf);
5100 } else if (context2) {
5101 /* Received reply from router, just send same data to the client. */
5102 SilcServerCommandReplyContext reply = context2;
5104 silc_command_get_status(reply->payload, &status, NULL);
5105 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, status,
5112 /* We are router and keep the watch list for local cell */
5114 /* Get the client ID */
5115 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5117 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5118 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5122 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
5124 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5125 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5130 /* Get the client entry which must be in local list */
5131 client = silc_idlist_find_client_by_id(server->local_list,
5132 client_id, TRUE, NULL);
5134 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5135 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5141 add_nick = silc_argument_get_arg_type(cmd->args, 2, &add_nick_len);
5142 del_nick = silc_argument_get_arg_type(cmd->args, 3, &del_nick_len);
5143 if (!add_nick && !del_nick) {
5144 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5145 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5150 if (add_nick && add_nick_len > 128)
5151 add_nick[128] = '\0';
5152 if (del_nick && del_nick_len > 128)
5153 del_nick[128] = '\0';
5155 memset(nick, 0, sizeof(nick));
5157 /* Add new nickname to be watched in our cell */
5159 if (silc_server_name_bad_chars(add_nick, strlen(add_nick)) == TRUE) {
5160 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5161 SILC_STATUS_ERR_BAD_NICKNAME, 0);
5165 /* Hash the nick, we have the hash saved, not nicks because we can
5166 do one to one mapping to the nick from Client ID hash this way. */
5167 silc_to_lower(add_nick, nick, sizeof(nick) - 1);
5168 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
5170 /* Check whether this client is already watching this nickname */
5171 if (silc_hash_table_find_by_context(server->watcher_list, hash,
5173 /* Nickname is alredy being watched for this client */
5174 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5175 SILC_STATUS_ERR_NICKNAME_IN_USE,
5180 /* Get the nickname from the watcher list and use the same key in
5181 new entries as well. If key doesn't exist then create it. */
5182 if (!silc_hash_table_find(server->watcher_list, hash, (void **)&tmp, NULL))
5183 tmp = silc_memdup(hash, CLIENTID_HASH_LEN);
5185 /* Add the client to the watcher list with the specified nickname hash. */
5186 silc_hash_table_add(server->watcher_list, tmp, client);
5189 /* Delete nickname from watch list */
5191 if (silc_server_name_bad_chars(del_nick, strlen(del_nick)) == TRUE) {
5192 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5193 SILC_STATUS_ERR_BAD_NICKNAME, 0);
5197 /* Hash the nick, we have the hash saved, not nicks because we can
5198 do one to one mapping to the nick from Client ID hash this way. */
5199 silc_to_lower(del_nick, nick, sizeof(nick) - 1);
5200 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
5202 /* Check that this client is watching for this nickname */
5203 if (!silc_hash_table_find_by_context(server->watcher_list, hash,
5204 client, (void **)&tmp)) {
5205 /* Nickname is alredy being watched for this client */
5206 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5207 SILC_STATUS_ERR_NO_SUCH_NICK, 0);
5211 /* Delete the nickname from the watcher list. */
5212 silc_hash_table_del_by_context(server->watcher_list, hash, client);
5214 /* Now check whether there still exists entries with this key, if not
5215 then free the key to not leak memory. */
5216 if (!silc_hash_table_find(server->watcher_list, hash, NULL, NULL))
5220 /* Distribute the watch list to backup routers too */
5221 if (server->backup) {
5223 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5224 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5225 silc_server_backup_send(server, NULL, SILC_PACKET_COMMAND,
5226 cmd->packet->flags, tmpbuf->data, tmpbuf->len,
5228 silc_buffer_free(tmpbuf);
5231 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5235 silc_free(client_id);
5236 silc_server_command_free(cmd);
5239 /* Server side of SILCOPER command. Client uses this comand to obtain router
5240 operator privileges to this router. */
5242 SILC_SERVER_CMD_FUNC(silcoper)
5244 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5245 SilcServer server = cmd->server;
5246 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5247 unsigned char *username, *auth;
5249 SilcServerConfigAdmin *admin;
5250 SilcIDListData idata = (SilcIDListData)client;
5251 bool result = FALSE;
5252 SilcPublicKey cached_key;
5254 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
5256 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5259 if (server->server_type != SILC_ROUTER) {
5260 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5261 SILC_STATUS_ERR_AUTH_FAILED, 0);
5265 /* Get the username */
5266 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5268 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5269 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5274 /* Get the admin configuration */
5275 admin = silc_server_config_find_admin(server, cmd->sock->ip,
5276 username, client->nickname);
5278 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
5279 username, client->nickname);
5281 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5282 SILC_STATUS_ERR_AUTH_FAILED, 0);
5287 /* Get the authentication payload */
5288 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5290 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5291 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5296 /* Verify the authentication data. If both passphrase and public key
5297 is set then try both of them. */
5298 if (admin->passphrase)
5299 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
5300 admin->passphrase, admin->passphrase_len,
5301 idata->hash, client->id, SILC_ID_CLIENT);
5302 if (!result && admin->publickeys) {
5303 cached_key = silc_server_get_public_key(server, admin->publickeys);
5306 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
5307 cached_key, 0, idata->hash,
5308 client->id, SILC_ID_CLIENT);
5311 /* Authentication failed */
5312 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
5313 SILC_STATUS_ERR_AUTH_FAILED, 0);
5317 /* Client is now router operator */
5318 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
5320 /* Update statistics */
5321 if (client->connection)
5322 server->stat.my_router_ops++;
5323 if (server->server_type == SILC_ROUTER)
5324 server->stat.router_ops++;
5326 /* Send UMODE change to primary router */
5327 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
5328 SILC_BROADCAST(server), client->id,
5331 /* Check if anyone is watching this nickname */
5332 if (server->server_type == SILC_ROUTER)
5333 silc_server_check_watcher_list(server, client, NULL,
5334 SILC_NOTIFY_TYPE_UMODE_CHANGE);
5336 /* Send reply to the sender */
5337 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5341 silc_server_command_free(cmd);
5344 /* Server side of command BAN. This is used to manage the ban list of the
5345 channel. To add clients and remove clients from the ban list. */
5347 SILC_SERVER_CMD_FUNC(ban)
5349 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5350 SilcServer server = cmd->server;
5351 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5353 SilcChannelEntry channel;
5354 SilcChannelClientEntry chl;
5355 SilcChannelID *channel_id = NULL;
5356 unsigned char *id, *add, *del;
5357 SilcUInt32 id_len, tmp_len;
5358 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5360 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5363 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
5365 /* Get Channel ID */
5366 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
5368 channel_id = silc_id_payload_parse_id(id, id_len, NULL);
5370 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5371 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5376 /* Get channel entry. The server must know about the channel since the
5377 client is expected to be on the channel. */
5378 channel = silc_idlist_find_channel_by_id(server->local_list,
5381 channel = silc_idlist_find_channel_by_id(server->global_list,
5384 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5385 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5391 /* Check whether this client is on the channel */
5392 if (!silc_server_client_on_channel(client, channel, &chl)) {
5393 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5394 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5398 /* The client must be at least channel operator. */
5399 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
5400 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5401 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
5405 /* Get the new ban and add it to the ban list */
5406 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5408 if (!channel->ban_list)
5409 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
5411 channel->ban_list = silc_realloc(channel->ban_list,
5412 sizeof(*channel->ban_list) *
5414 strlen(channel->ban_list) + 2));
5415 if (add[tmp_len - 1] == ',')
5416 add[tmp_len - 1] = '\0';
5418 strncat(channel->ban_list, add, tmp_len);
5419 strncat(channel->ban_list, ",", 1);
5422 /* Get the ban to be removed and remove it from the list */
5423 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
5424 if (del && channel->ban_list) {
5425 char *start, *end, *n;
5427 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
5428 silc_free(channel->ban_list);
5429 channel->ban_list = NULL;
5431 start = strstr(channel->ban_list, del);
5432 if (start && strlen(start) >= tmp_len) {
5433 end = start + tmp_len;
5434 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
5435 strncat(n, channel->ban_list, start - channel->ban_list);
5436 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
5438 silc_free(channel->ban_list);
5439 channel->ban_list = n;
5444 /* Send the BAN notify type to our primary router. */
5446 silc_server_send_notify_ban(server, SILC_PRIMARY_ROUTE(server),
5447 SILC_BROADCAST(server), channel, add, del);
5449 /* Send the reply back to the client */
5451 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
5452 SILC_STATUS_OK, 0, ident, 2,
5454 3, channel->ban_list,
5456 strlen(channel->ban_list) -1 : 0);
5457 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5458 packet->data, packet->len, FALSE);
5460 silc_buffer_free(packet);
5463 silc_free(channel_id);
5464 silc_server_command_free(cmd);
5467 /* Server side command of LEAVE. Removes client from a channel. */
5469 SILC_SERVER_CMD_FUNC(leave)
5471 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5472 SilcServer server = cmd->server;
5473 SilcSocketConnection sock = cmd->sock;
5474 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
5475 SilcChannelID *id = NULL;
5476 SilcChannelEntry channel;
5480 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
5482 /* Get Channel ID */
5483 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
5485 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5486 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5489 id = silc_id_payload_parse_id(tmp, len, NULL);
5491 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5492 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5496 /* Get channel entry */
5497 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5499 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5501 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5502 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5508 /* Check whether this client is on the channel */
5509 if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
5510 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5511 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5515 /* Notify routers that they should remove this client from their list
5516 of clients on the channel. Send LEAVE notify type. */
5517 silc_server_send_notify_leave(server, SILC_PRIMARY_ROUTE(server),
5518 SILC_BROADCAST(server), channel, id_entry->id);
5520 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
5521 SILC_STATUS_OK, 0, 2, tmp, len);
5523 /* Remove client from channel */
5524 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5526 /* If the channel does not exist anymore we won't send anything */
5529 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5530 /* Re-generate channel key */
5531 if (!silc_server_create_channel_key(server, channel, 0))
5534 /* Send the channel key */
5535 silc_server_send_channel_key(server, NULL, channel,
5536 server->server_type == SILC_ROUTER ?
5537 FALSE : !server->standalone);
5542 silc_server_command_free(cmd);
5545 /* Server side of command USERS. Resolves clients and their USERS currently
5546 joined on the requested channel. The list of Client ID's and their modes
5547 on the channel is sent back. */
5549 SILC_SERVER_CMD_FUNC(users)
5551 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5552 SilcServer server = cmd->server;
5553 SilcChannelEntry channel;
5554 SilcChannelID *id = NULL;
5555 SilcBuffer packet, idp;
5556 unsigned char *channel_id;
5557 SilcUInt32 channel_id_len;
5558 SilcBuffer client_id_list;
5559 SilcBuffer client_mode_list;
5560 unsigned char lc[4];
5561 SilcUInt32 list_count = 0;
5562 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5565 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5567 /* Get Channel ID */
5568 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5570 /* Get channel name */
5571 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5573 if (!channel_id && !channel_name) {
5574 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5575 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5580 id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
5582 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5583 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5588 /* If we are server and we don't know about this channel we will send
5589 the command to our router. If we know about the channel then we also
5590 have the list of users already. */
5592 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5594 channel = silc_idlist_find_channel_by_name(server->local_list,
5595 channel_name, NULL);
5597 if (!channel || (!server->standalone && (channel->disabled ||
5598 !channel->users_resolved))) {
5599 if (server->server_type != SILC_ROUTER && !server->standalone &&
5603 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5604 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5606 /* Send USERS command */
5607 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5608 SILC_PACKET_COMMAND, cmd->packet->flags,
5609 tmpbuf->data, tmpbuf->len, TRUE);
5611 /* Reprocess this packet after received reply */
5612 silc_server_command_pending(server, SILC_COMMAND_USERS,
5613 silc_command_get_ident(cmd->payload),
5614 silc_server_command_users,
5615 silc_server_command_dup(cmd));
5616 cmd->pending = TRUE;
5617 silc_command_set_ident(cmd->payload, ident);
5618 silc_buffer_free(tmpbuf);
5623 /* Check the global list as well. */
5625 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5627 channel = silc_idlist_find_channel_by_name(server->global_list,
5628 channel_name, NULL);
5630 /* Channel really does not exist */
5631 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5632 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5638 /* If the channel is private or secret do not send anything, unless the
5639 user requesting this command is on the channel or is server */
5640 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5641 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5642 && !silc_server_client_on_channel(cmd->sock->user_data, channel,
5644 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5645 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5651 /* Get the users list */
5652 if (!silc_server_get_users_on_channel(server, channel, &client_id_list,
5653 &client_mode_list, &list_count)) {
5655 client_id_list = NULL;
5656 client_mode_list = NULL;
5660 SILC_PUT32_MSB(list_count, lc);
5663 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5664 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5665 SILC_STATUS_OK, 0, ident, 4,
5666 2, idp->data, idp->len,
5669 client_id_list->data : NULL,
5671 client_id_list->len : 0,
5672 5, client_mode_list ?
5673 client_mode_list->data : NULL,
5675 client_mode_list->len : 0);
5676 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5677 packet->data, packet->len, FALSE);
5679 silc_buffer_free(idp);
5680 silc_buffer_free(packet);
5682 silc_buffer_free(client_id_list);
5683 if (client_mode_list)
5684 silc_buffer_free(client_mode_list);
5688 silc_server_command_free(cmd);
5691 /* Server side of command GETKEY. This fetches the client's public key
5692 from the server where to the client is connected. */
5694 SILC_SERVER_CMD_FUNC(getkey)
5696 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5697 SilcServer server = cmd->server;
5699 SilcClientEntry client;
5700 SilcServerEntry server_entry;
5701 SilcClientID *client_id = NULL;
5702 SilcServerID *server_id = NULL;
5703 SilcIDPayload idp = NULL;
5704 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5705 unsigned char *tmp, *pkdata;
5706 SilcUInt32 tmp_len, pklen;
5707 SilcBuffer pk = NULL;
5709 SilcPublicKey public_key;
5711 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5713 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5714 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5718 idp = silc_id_payload_parse(tmp, tmp_len);
5720 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5721 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5726 id_type = silc_id_payload_get_type(idp);
5727 if (id_type == SILC_ID_CLIENT) {
5728 client_id = silc_id_payload_get_id(idp);
5730 /* If the client is not found from local list there is no chance it
5731 would be locally connected client so send the command further. */
5732 client = silc_idlist_find_client_by_id(server->local_list,
5733 client_id, TRUE, NULL);
5735 client = silc_idlist_find_client_by_id(server->global_list,
5736 client_id, TRUE, NULL);
5738 if ((!client && !cmd->pending && !server->standalone) ||
5739 (client && !client->connection && !cmd->pending &&
5740 !(client->mode & SILC_UMODE_DETACHED)) ||
5741 (client && !client->data.public_key && !cmd->pending)) {
5743 SilcUInt16 old_ident;
5744 SilcSocketConnection dest_sock;
5746 dest_sock = silc_server_get_client_route(server, NULL, 0,
5747 client_id, NULL, NULL);
5751 old_ident = silc_command_get_ident(cmd->payload);
5752 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5753 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5755 silc_server_packet_send(server, dest_sock,
5756 SILC_PACKET_COMMAND, cmd->packet->flags,
5757 tmpbuf->data, tmpbuf->len, TRUE);
5759 /* Reprocess this packet after received reply from router */
5760 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5761 silc_command_get_ident(cmd->payload),
5762 silc_server_command_getkey,
5763 silc_server_command_dup(cmd));
5764 cmd->pending = TRUE;
5765 silc_command_set_ident(cmd->payload, old_ident);
5766 silc_buffer_free(tmpbuf);
5771 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5772 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5777 /* The client is locally connected, just get the public key and
5778 send it back. If they key does not exist then do not send it,
5779 send just OK reply */
5780 public_key = client->data.public_key;
5785 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5786 pk = silc_buffer_alloc(4 + tmp_len);
5787 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5788 silc_buffer_format(pk,
5789 SILC_STR_UI_SHORT(tmp_len),
5790 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5791 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5797 } else if (id_type == SILC_ID_SERVER) {
5798 server_id = silc_id_payload_get_id(idp);
5800 /* If the server is not found from local list there is no chance it
5801 would be locally connected server so send the command further. */
5802 server_entry = silc_idlist_find_server_by_id(server->local_list,
5803 server_id, TRUE, NULL);
5805 server_entry = silc_idlist_find_server_by_id(server->global_list,
5806 server_id, TRUE, NULL);
5808 if (server_entry != server->id_entry &&
5809 ((!server_entry && !cmd->pending && !server->standalone) ||
5810 (server_entry && !server_entry->connection && !cmd->pending &&
5811 !server->standalone) ||
5812 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5813 !server->standalone))) {
5815 SilcUInt16 old_ident;
5817 old_ident = silc_command_get_ident(cmd->payload);
5818 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5819 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5821 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5822 SILC_PACKET_COMMAND, cmd->packet->flags,
5823 tmpbuf->data, tmpbuf->len, TRUE);
5825 /* Reprocess this packet after received reply from router */
5826 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5827 silc_command_get_ident(cmd->payload),
5828 silc_server_command_getkey,
5829 silc_server_command_dup(cmd));
5830 cmd->pending = TRUE;
5831 silc_command_set_ident(cmd->payload, old_ident);
5832 silc_buffer_free(tmpbuf);
5836 if (!server_entry) {
5837 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5838 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
5843 /* If they key does not exist then do not send it, send just OK reply */
5844 public_key = (!server_entry->data.public_key ?
5845 (server_entry == server->id_entry ? server->public_key :
5846 NULL) : server_entry->data.public_key);
5851 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5852 pk = silc_buffer_alloc(4 + tmp_len);
5853 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5854 silc_buffer_format(pk,
5855 SILC_STR_UI_SHORT(tmp_len),
5856 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5857 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5867 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5868 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5869 SILC_STATUS_OK, 0, ident,
5873 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5874 packet->data, packet->len, FALSE);
5875 silc_buffer_free(packet);
5878 silc_buffer_free(pk);
5882 silc_id_payload_free(idp);
5883 silc_free(client_id);
5884 silc_free(server_id);
5885 silc_server_command_free(cmd);
5889 /* Private range commands, specific to this implementation */
5891 /* Server side command of CONNECT. Connects us to the specified remote
5892 server or router. */
5894 SILC_SERVER_CMD_FUNC(connect)
5896 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5897 SilcServer server = cmd->server;
5898 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5899 unsigned char *tmp, *host;
5901 SilcUInt32 port = SILC_PORT;
5903 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
5905 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5908 /* Check whether client has the permissions. */
5909 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5910 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5911 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5912 SILC_STATUS_ERR_NO_SERVER_PRIV, 0);
5916 if (server->server_type == SILC_ROUTER &&
5917 client->mode & SILC_UMODE_SERVER_OPERATOR) {
5918 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5919 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
5923 /* Get the remote server */
5924 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5926 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5927 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5933 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5935 SILC_GET32_MSB(port, tmp);
5937 /* Create the connection. It is done with timeout and is async. */
5938 silc_server_create_connection(server, host, port);
5940 /* Send reply to the sender */
5941 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5945 silc_server_command_free(cmd);
5948 /* Server side command of CLOSE. Closes connection to a specified server. */
5950 SILC_SERVER_CMD_FUNC(close)
5952 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5953 SilcServer server = cmd->server;
5954 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5955 SilcServerEntry server_entry;
5956 SilcSocketConnection sock;
5959 unsigned char *name;
5960 SilcUInt32 port = SILC_PORT;
5962 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
5964 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5967 /* Check whether client has the permissions. */
5968 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5969 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5970 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5971 SILC_STATUS_ERR_NO_SERVER_PRIV,
5976 /* Get the remote server */
5977 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5979 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5980 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5986 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5988 SILC_GET32_MSB(port, tmp);
5990 server_entry = silc_idlist_find_server_by_conn(server->local_list,
5991 name, port, FALSE, NULL);
5993 server_entry = silc_idlist_find_server_by_conn(server->global_list,
5994 name, port, FALSE, NULL);
5995 if (!server_entry) {
5996 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5997 SILC_STATUS_ERR_NO_SERVER_ID, 0);
6001 /* Send reply to the sender */
6002 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
6005 /* Close the connection to the server */
6006 sock = (SilcSocketConnection)server_entry->connection;
6008 /* If we shutdown primary router connection manually then don't trigger
6009 any reconnect or backup router connections, by setting the router
6011 if (server->router == server_entry) {
6012 server->id_entry->router = NULL;
6013 server->router = NULL;
6014 server->standalone = TRUE;
6016 silc_server_free_sock_user_data(server, sock, NULL);
6017 silc_server_close_connection(server, sock);
6020 silc_server_command_free(cmd);
6023 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
6024 active connections. */
6026 SILC_SERVER_CMD_FUNC(shutdown)
6028 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
6029 SilcServer server = cmd->server;
6030 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
6032 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
6034 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
6037 /* Check whether client has the permission. */
6038 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
6039 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
6040 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
6041 SILC_STATUS_ERR_NO_SERVER_PRIV,
6046 /* Send reply to the sender */
6047 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
6050 /* Then, gracefully, or not, bring the server down. */
6051 silc_server_stop(server);
6055 silc_server_command_free(cmd);