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);
1620 silc_id_payload_free(idp);
1625 /* Get the max count of reply messages allowed */
1626 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1628 SILC_GET32_MSB(*count, tmp);
1635 /* Checks that all mandatory fields in client entry are present. If not
1636 then send WHOIS request to the server who owns the client. We use
1637 WHOIS because we want to get as much information as possible at once. */
1640 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1641 SilcClientEntry *clients,
1642 SilcUInt32 clients_count)
1644 SilcServer server = cmd->server;
1645 SilcClientEntry entry;
1646 SilcServerResolveContext resolve = NULL, r = NULL;
1647 SilcUInt32 resolve_count = 0;
1651 for (i = 0; i < clients_count; i++) {
1656 if (entry->nickname ||
1657 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1661 /* If we are normal server, and we've not resolved this client from
1662 router and it is global client, we'll check whether it is on some
1663 channel. If not then we cannot be sure about its validity, and
1664 we'll resolve it from router. */
1665 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
1666 entry->connection || silc_hash_table_count(entry->channels))
1670 /* We need to resolve this entry since it is not complete */
1672 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1673 /* The entry is being resolved (and we are not the resolver) so attach
1674 to the command reply and we're done with this one. */
1675 silc_server_command_pending(server, SILC_COMMAND_NONE,
1676 entry->resolve_cmd_ident,
1677 silc_server_command_identify,
1678 silc_server_command_dup(cmd));
1681 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1682 /* We've resolved this and it still is not ready. We'll return
1683 and are that this will be handled again after it is resolved. */
1684 for (i = 0; i < resolve_count; i++) {
1685 for (k = 0; k < r->res_argc; k++)
1686 silc_free(r->res_argv[k]);
1687 silc_free(r->res_argv);
1688 silc_free(r->res_argv_lens);
1689 silc_free(r->res_argv_types);
1694 /* We'll resolve this client */
1698 for (k = 0; k < resolve_count; k++) {
1699 if (resolve[k].router == entry->router) {
1706 resolve = silc_realloc(resolve, sizeof(*resolve) *
1707 (resolve_count + 1));
1708 r = &resolve[resolve_count];
1709 memset(r, 0, sizeof(*r));
1710 r->router = entry->router;
1711 r->ident = ++server->cmd_ident;
1715 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1717 r->res_argv_lens = silc_realloc(r->res_argv_lens,
1718 sizeof(*r->res_argv_lens) *
1720 r->res_argv_types = silc_realloc(r->res_argv_types,
1721 sizeof(*r->res_argv_types) *
1723 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1724 r->res_argv[r->res_argc] = silc_calloc(idp->len,
1725 sizeof(**r->res_argv));
1726 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1727 r->res_argv_lens[r->res_argc] = idp->len;
1728 r->res_argv_types[r->res_argc] = r->res_argc + 4;
1730 silc_buffer_free(idp);
1732 entry->resolve_cmd_ident = r->ident;
1733 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1734 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1739 /* Do the resolving */
1740 for (i = 0; i < resolve_count; i++) {
1745 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1746 now anyway so make it a good one. */
1747 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1748 r->res_argc, r->res_argv,
1752 silc_server_packet_send(server, r->router->connection,
1753 SILC_PACKET_COMMAND, cmd->packet->flags,
1754 res_cmd->data, res_cmd->len, FALSE);
1756 /* Reprocess this packet after received reply */
1757 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1759 silc_server_command_identify,
1760 silc_server_command_dup(cmd));
1761 cmd->pending = TRUE;
1763 silc_buffer_free(res_cmd);
1764 for (k = 0; k < r->res_argc; k++)
1765 silc_free(r->res_argv[k]);
1766 silc_free(r->res_argv);
1767 silc_free(r->res_argv_lens);
1768 silc_free(r->res_argv_types);
1777 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1778 SilcClientEntry *clients,
1779 SilcUInt32 clients_count,
1780 SilcServerEntry *servers,
1781 SilcUInt32 servers_count,
1782 SilcChannelEntry *channels,
1783 SilcUInt32 channels_count,
1784 ResolveError errors,
1785 SilcUInt32 errors_count,
1788 SilcServer server = cmd->server;
1789 int i, k, valid_count;
1791 SilcBuffer packet, idp;
1793 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1794 char nh[256], uh[256];
1795 SilcSocketConnection hsock;
1798 status = SILC_STATUS_OK;
1801 SilcClientEntry entry;
1802 valid_count = clients_count;
1804 if (silc_argument_get_arg_type(cmd->args, 1, NULL)) {
1805 /* Process only valid clients and ignore those that are not registered.
1806 This is checked with nickname only because when resolved client IDs
1807 we check that they are registered earlier. */
1809 for (i = 0; i < clients_count; i++) {
1810 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1817 /* No valid entries found at all, just send error */
1818 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1819 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1820 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1821 3, tmp, tmp ? strlen(tmp) : 0);
1826 /* Process all valid client entries and send command replies */
1828 if (valid_count > 1)
1829 status = SILC_STATUS_LIST_START;
1831 for (i = 0, k = 0; i < clients_count; i++) {
1837 status = SILC_STATUS_LIST_ITEM;
1838 if (valid_count > 1 && k == valid_count - 1
1839 && !servers_count && !channels_count && !errors_count)
1840 status = SILC_STATUS_LIST_END;
1841 if (count && k - 1 == count)
1842 status = SILC_STATUS_LIST_END;
1844 /* Send IDENTIFY reply */
1846 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1847 memset(uh, 0, sizeof(uh));
1848 memset(nh, 0, sizeof(nh));
1849 strncat(nh, entry->nickname, strlen(entry->nickname));
1850 if (!strchr(entry->nickname, '@')) {
1851 strncat(nh, "@", 1);
1852 if (entry->servername) {
1853 strncat(nh, entry->servername, strlen(entry->servername));
1855 len = entry->router ? strlen(entry->router->server_name) :
1856 strlen(server->server_name);
1857 strncat(nh, entry->router ? entry->router->server_name :
1858 server->server_name, len);
1862 if (!entry->username) {
1863 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1864 status, 0, ident, 2,
1865 2, idp->data, idp->len,
1868 strncat(uh, entry->username, strlen(entry->username));
1869 if (!strchr(entry->username, '@') && entry->connection) {
1870 strncat(uh, "@", 1);
1871 hsock = (SilcSocketConnection)entry->connection;
1872 len = strlen(hsock->hostname);
1873 strncat(uh, hsock->hostname, len);
1876 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1877 status, 0, ident, 3,
1878 2, idp->data, idp->len,
1883 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1884 0, packet->data, packet->len, FALSE);
1886 silc_buffer_free(packet);
1887 silc_buffer_free(idp);
1889 if (status == SILC_STATUS_LIST_END)
1896 SilcServerEntry entry;
1898 if (status == SILC_STATUS_OK && servers_count > 1)
1899 status = SILC_STATUS_LIST_START;
1901 for (i = 0, k = 0; i < servers_count; i++) {
1905 status = SILC_STATUS_LIST_ITEM;
1906 if (servers_count > 1 && k == servers_count - 1 && !channels_count &&
1908 status = SILC_STATUS_LIST_END;
1909 if (count && k - 1 == count)
1910 status = SILC_STATUS_LIST_END;
1912 /* Send IDENTIFY reply */
1913 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1915 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1916 status, 0, ident, 2,
1917 2, idp->data, idp->len,
1918 3, entry->server_name,
1919 entry->server_name ?
1920 strlen(entry->server_name) : 0);
1921 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1922 0, packet->data, packet->len, FALSE);
1924 silc_buffer_free(packet);
1925 silc_buffer_free(idp);
1927 if (status == SILC_STATUS_LIST_END)
1934 SilcChannelEntry entry;
1936 if (status == SILC_STATUS_OK && channels_count > 1)
1937 status = SILC_STATUS_LIST_START;
1939 for (i = 0, k = 0; i < channels_count; i++) {
1940 entry = channels[i];
1943 status = SILC_STATUS_LIST_ITEM;
1944 if (channels_count > 1 && k == channels_count - 1 && !errors_count)
1945 status = SILC_STATUS_LIST_END;
1946 if (count && k - 1 == count)
1947 status = SILC_STATUS_LIST_END;
1949 /* Send IDENTIFY reply */
1950 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1952 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1953 status, 0, ident, 2,
1954 2, idp->data, idp->len,
1955 3, entry->channel_name,
1956 entry->channel_name ?
1957 strlen(entry->channel_name): 0);
1958 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1959 0, packet->data, packet->len, FALSE);
1961 silc_buffer_free(packet);
1962 silc_buffer_free(idp);
1964 if (status == SILC_STATUS_LIST_END)
1970 /* Send error replies */
1972 if (status == SILC_STATUS_OK && errors_count > 1)
1973 status = SILC_STATUS_LIST_START;
1976 for (i = 0, k = 0; i < errors_count; i++) {
1978 idp = silc_id_payload_encode(errors[i].id, SILC_ID_CLIENT);
1982 tmp = silc_argument_get_arg_type(cmd->args, errors[i].index, &len);
1986 status = SILC_STATUS_LIST_ITEM;
1987 if (errors_count > 1 && k == errors_count - 1)
1988 status = SILC_STATUS_LIST_END;
1989 if (count && k - 1 == count)
1990 status = SILC_STATUS_LIST_END;
1993 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1994 (status == SILC_STATUS_OK ?
1995 errors[i].error : status),
1996 (status == SILC_STATUS_OK ?
1997 0 : errors[i].error),
1999 silc_buffer_free(idp);
2002 if (status == SILC_STATUS_LIST_END)
2010 silc_server_command_identify_process(SilcServerCommandContext cmd)
2012 SilcUInt32 count = 0;
2014 SilcClientEntry *clients = NULL;
2015 SilcServerEntry *servers = NULL;
2016 SilcChannelEntry *channels = NULL;
2017 SilcUInt32 clients_count = 0, servers_count = 0, channels_count = 0;
2018 SilcUInt32 errors_count = 0;
2019 ResolveError errors = NULL;
2021 /* Parse the IDENTIFY request */
2022 ret = silc_server_command_identify_parse(cmd,
2023 &clients, &clients_count,
2024 &servers, &servers_count,
2025 &channels, &channels_count,
2026 &count, &errors, &errors_count);
2031 /* Check that all mandatory fields are present and request those data
2032 from the server who owns the client if necessary. */
2033 if (!silc_server_command_identify_check_client(cmd, clients,
2039 /* Send the command reply to the client */
2040 silc_server_command_identify_send_reply(cmd,
2041 clients, clients_count,
2042 servers, servers_count,
2043 channels, channels_count,
2044 errors, errors_count,
2050 silc_free(channels);
2055 SILC_SERVER_CMD_FUNC(identify)
2057 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2060 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
2062 ret = silc_server_command_identify_process(cmd);
2063 silc_server_command_free(cmd);
2066 /* Server side of command NICK. Sets nickname for user. Setting
2067 nickname causes generation of a new client ID for the client. The
2068 new client ID is sent to the client after changing the nickname. */
2070 SILC_SERVER_CMD_FUNC(nick)
2072 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2073 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2074 SilcServer server = cmd->server;
2075 SilcBuffer packet, nidp, oidp = NULL;
2076 SilcClientID *new_id;
2077 SilcUInt32 nick_len;
2079 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2082 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2085 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
2087 /* Check nickname */
2088 nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
2091 if (silc_server_name_bad_chars(nick, nick_len) == TRUE) {
2092 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2093 SILC_STATUS_ERR_BAD_NICKNAME, 0);
2097 /* Check for same nickname */
2098 if (!strcmp(client->nickname, nick)) {
2099 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2103 /* Create new Client ID */
2104 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
2106 cmd->server->md5hash, nick,
2110 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2111 SILC_STATUS_ERR_BAD_NICKNAME, 0);
2114 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2117 /* Send notify about nickname change to our router. We send the new
2118 ID and ask to replace it with the old one. If we are router the
2119 packet is broadcasted. Send NICK_CHANGE notify. */
2120 silc_server_send_notify_nick_change(server, SILC_PRIMARY_ROUTE(server),
2121 SILC_BROADCAST(server), client->id,
2124 /* Check if anyone is watching the old nickname */
2125 if (server->server_type == SILC_ROUTER)
2126 silc_server_check_watcher_list(server, client, nick,
2127 SILC_NOTIFY_TYPE_NICK_CHANGE);
2129 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2131 /* Remove old cache entry */
2132 silc_idcache_del_by_context(server->local_list->clients, client);
2134 silc_free(client->id);
2135 client->id = new_id;
2137 silc_free(client->nickname);
2138 client->nickname = strdup(nick);
2140 /* Update client cache */
2141 silc_idcache_add(server->local_list->clients, client->nickname,
2142 client->id, (void *)client, 0, NULL);
2144 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2146 /* Send NICK_CHANGE notify to the client's channels */
2147 silc_server_send_notify_on_channels(server, NULL, client,
2148 SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
2149 oidp->data, oidp->len,
2150 nidp->data, nidp->len,
2152 strlen(client->nickname));
2154 /* Check if anyone is watching the new nickname */
2155 if (server->server_type == SILC_ROUTER)
2156 silc_server_check_watcher_list(server, client, NULL,
2157 SILC_NOTIFY_TYPE_NICK_CHANGE);
2160 /* Send the new Client ID as reply command back to client */
2161 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
2162 SILC_STATUS_OK, 0, ident, 2,
2163 2, nidp->data, nidp->len,
2164 3, nick, strlen(nick));
2165 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2166 0, packet->data, packet->len, FALSE);
2168 silc_buffer_free(packet);
2169 silc_buffer_free(nidp);
2171 silc_buffer_free(oidp);
2174 silc_server_command_free(cmd);
2177 /* Sends the LIST command reply */
2180 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2181 SilcChannelEntry *lch,
2182 SilcUInt32 lch_count,
2183 SilcChannelEntry *gch,
2184 SilcUInt32 gch_count)
2187 SilcBuffer packet, idp;
2188 SilcChannelEntry entry;
2190 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2192 unsigned char usercount[4];
2194 int valid_lcount = 0, valid_rcount = 0;
2196 for (i = 0; i < lch_count; i++) {
2197 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2202 for (i = 0; i < gch_count; i++) {
2203 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2209 status = SILC_STATUS_OK;
2210 if ((lch_count + gch_count) > 1)
2211 status = SILC_STATUS_LIST_START;
2214 for (i = 0, k = 0; i < lch_count; i++) {
2220 status = SILC_STATUS_LIST_ITEM;
2221 if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
2222 status = SILC_STATUS_LIST_END;
2224 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2226 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2227 topic = "*private*";
2228 memset(usercount, 0, sizeof(usercount));
2230 topic = entry->topic;
2231 users = silc_hash_table_count(entry->user_list);
2232 SILC_PUT32_MSB(users, usercount);
2235 /* Send the reply */
2237 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2238 status, 0, ident, 4,
2239 2, idp->data, idp->len,
2240 3, entry->channel_name,
2241 strlen(entry->channel_name),
2242 4, topic, topic ? strlen(topic) : 0,
2244 silc_server_packet_send(cmd->server, cmd->sock,
2245 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2246 packet->len, FALSE);
2247 silc_buffer_free(packet);
2248 silc_buffer_free(idp);
2253 for (i = 0, k = 0; i < gch_count; i++) {
2259 status = SILC_STATUS_LIST_ITEM;
2260 if (valid_rcount > 1 && k == valid_rcount - 1)
2261 status = SILC_STATUS_LIST_END;
2263 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2265 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2266 topic = "*private*";
2267 memset(usercount, 0, sizeof(usercount));
2269 topic = entry->topic;
2270 users = entry->user_count;
2271 SILC_PUT32_MSB(users, usercount);
2274 /* Send the reply */
2276 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2277 status, 0, ident, 4,
2278 2, idp->data, idp->len,
2279 3, entry->channel_name,
2280 strlen(entry->channel_name),
2281 4, topic, topic ? strlen(topic) : 0,
2283 silc_server_packet_send(cmd->server, cmd->sock,
2284 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2285 packet->len, FALSE);
2286 silc_buffer_free(packet);
2287 silc_buffer_free(idp);
2292 /* Server side of LIST command. This lists the channel of the requested
2293 server. Secret channels are not listed. */
2295 SILC_SERVER_CMD_FUNC(list)
2297 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2298 SilcServer server = cmd->server;
2299 SilcChannelID *channel_id = NULL;
2302 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2303 SilcUInt32 lch_count = 0, gch_count = 0;
2305 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2307 /* If we are normal server, send the command to router, since we
2308 want to know all channels in the network. */
2309 if (!cmd->pending && server->server_type == SILC_SERVER &&
2310 !server->standalone) {
2312 SilcUInt16 old_ident;
2314 old_ident = silc_command_get_ident(cmd->payload);
2315 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2316 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2317 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
2318 SILC_PACKET_COMMAND, cmd->packet->flags,
2319 tmpbuf->data, tmpbuf->len, TRUE);
2321 /* Reprocess this packet after received reply from router */
2322 silc_server_command_pending(server, SILC_COMMAND_LIST,
2323 silc_command_get_ident(cmd->payload),
2324 silc_server_command_list,
2325 silc_server_command_dup(cmd));
2326 cmd->pending = TRUE;
2327 silc_command_set_ident(cmd->payload, old_ident);
2328 silc_buffer_free(tmpbuf);
2332 /* Get Channel ID */
2333 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2335 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2337 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2338 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2343 /* Get the channels from local list */
2344 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2347 /* Get the channels from global list */
2348 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2351 /* Send the reply */
2352 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2353 gchannels, gch_count);
2355 silc_free(lchannels);
2356 silc_free(gchannels);
2359 silc_server_command_free(cmd);
2362 /* Server side of TOPIC command. Sets topic for channel and/or returns
2363 current topic to client. */
2365 SILC_SERVER_CMD_FUNC(topic)
2367 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2368 SilcServer server = cmd->server;
2369 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2370 SilcChannelID *channel_id;
2371 SilcChannelEntry channel;
2372 SilcChannelClientEntry chl;
2373 SilcBuffer packet, idp;
2375 SilcUInt32 argc, tmp_len;
2376 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2378 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2380 argc = silc_argument_get_arg_num(cmd->args);
2382 /* Get Channel ID */
2383 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2385 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2386 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2389 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2391 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2392 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2396 /* Check whether the channel exists */
2397 channel = silc_idlist_find_channel_by_id(server->local_list,
2400 channel = silc_idlist_find_channel_by_id(server->global_list,
2403 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2404 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
2412 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2414 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2415 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2420 if (strlen(tmp) > 256) {
2421 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2422 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2427 /* See whether the client is on channel and has rights to change topic */
2428 if (!silc_server_client_on_channel(client, channel, &chl)) {
2429 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2430 SILC_STATUS_ERR_NOT_ON_CHANNEL,
2435 if (channel->mode & SILC_CHANNEL_MODE_TOPIC &&
2436 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
2437 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
2438 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2439 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
2444 if (!channel->topic || strcmp(channel->topic, tmp)) {
2445 /* Set the topic for channel */
2446 silc_free(channel->topic);
2447 channel->topic = strdup(tmp);
2449 /* Send TOPIC_SET notify type to the network */
2450 silc_server_send_notify_topic_set(server, SILC_PRIMARY_ROUTE(server),
2451 SILC_BROADCAST(server), channel,
2452 client->id, SILC_ID_CLIENT,
2455 /* Send notify about topic change to all clients on the channel */
2456 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2457 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2458 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2459 idp->data, idp->len,
2461 strlen(channel->topic));
2462 silc_buffer_free(idp);
2466 /* Send the topic to client as reply packet */
2467 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2468 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2469 SILC_STATUS_OK, 0, ident, 2,
2470 2, idp->data, idp->len,
2473 strlen(channel->topic) : 0);
2474 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2475 0, packet->data, packet->len, FALSE);
2477 silc_buffer_free(packet);
2478 silc_buffer_free(idp);
2479 silc_free(channel_id);
2482 silc_server_command_free(cmd);
2485 /* Server side of INVITE command. Invites some client to join some channel.
2486 This command is also used to manage the invite list of the channel. */
2488 SILC_SERVER_CMD_FUNC(invite)
2490 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2491 SilcServer server = cmd->server;
2492 SilcSocketConnection sock = cmd->sock, dest_sock;
2493 SilcChannelClientEntry chl;
2494 SilcClientEntry sender, dest;
2495 SilcClientID *dest_id = NULL;
2496 SilcChannelEntry channel;
2497 SilcChannelID *channel_id = NULL;
2498 SilcIDListData idata;
2499 SilcBuffer idp, idp2, packet;
2500 unsigned char *tmp, *add, *del;
2502 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2504 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2506 /* Get Channel ID */
2507 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2509 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2510 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2513 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
2515 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2516 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2520 /* Get the channel entry */
2521 channel = silc_idlist_find_channel_by_id(server->local_list,
2524 channel = silc_idlist_find_channel_by_id(server->global_list,
2527 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2528 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
2534 /* Check whether the sender of this command is on the channel. */
2535 sender = (SilcClientEntry)sock->user_data;
2536 if (!silc_server_client_on_channel(sender, channel, &chl)) {
2537 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2538 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
2542 /* Check whether the channel is invite-only channel. If yes then the
2543 sender of this command must be at least channel operator. */
2544 if (channel->mode & SILC_CHANNEL_MODE_INVITE &&
2545 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
2546 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
2547 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2548 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
2553 /* Get destination client ID */
2554 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2559 dest_id = silc_id_payload_parse_id(tmp, len, NULL);
2561 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2562 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
2566 /* Get the client entry */
2567 dest = silc_server_get_client_resolve(server, dest_id, FALSE, &resolve);
2569 if (server->server_type != SILC_SERVER || !resolve) {
2570 silc_server_command_send_status_reply(
2571 cmd, SILC_COMMAND_INVITE,
2572 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0);
2576 /* The client info is being resolved. Reprocess this packet after
2577 receiving the reply to the query. */
2578 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2580 silc_server_command_invite,
2581 silc_server_command_dup(cmd));
2582 cmd->pending = TRUE;
2583 silc_free(channel_id);
2588 /* Check whether the requested client is already on the channel. */
2589 if (silc_server_client_on_channel(dest, channel, NULL)) {
2590 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2591 SILC_STATUS_ERR_USER_ON_CHANNEL,
2596 /* Get route to the client */
2597 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id,
2600 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2601 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2606 memset(invite, 0, sizeof(invite));
2607 strncat(invite, dest->nickname, strlen(dest->nickname));
2608 strncat(invite, "!", 1);
2609 strncat(invite, dest->username, strlen(dest->username));
2610 if (!strchr(dest->username, '@')) {
2611 strncat(invite, "@", 1);
2612 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2615 len = strlen(invite);
2616 if (!channel->invite_list)
2617 channel->invite_list = silc_calloc(len + 2,
2618 sizeof(*channel->invite_list));
2620 channel->invite_list = silc_realloc(channel->invite_list,
2621 sizeof(*channel->invite_list) *
2623 strlen(channel->invite_list) + 2));
2624 strncat(channel->invite_list, invite, len);
2625 strncat(channel->invite_list, ",", 1);
2627 if (!(dest->mode & SILC_UMODE_BLOCK_INVITE)) {
2628 /* Send notify to the client that is invited to the channel */
2629 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2630 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2631 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2633 SILC_NOTIFY_TYPE_INVITE, 3,
2634 idp->data, idp->len,
2635 channel->channel_name,
2636 strlen(channel->channel_name),
2637 idp2->data, idp2->len);
2638 silc_buffer_free(idp);
2639 silc_buffer_free(idp2);
2643 /* Add the client to the invite list of the channel */
2644 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2646 if (!channel->invite_list)
2647 channel->invite_list = silc_calloc(len + 2,
2648 sizeof(*channel->invite_list));
2650 channel->invite_list = silc_realloc(channel->invite_list,
2651 sizeof(*channel->invite_list) *
2653 strlen(channel->invite_list) + 2));
2654 if (add[len - 1] == ',')
2655 add[len - 1] = '\0';
2657 strncat(channel->invite_list, add, len);
2658 strncat(channel->invite_list, ",", 1);
2661 /* Get the invite to be removed and remove it from the list */
2662 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2663 if (del && channel->invite_list) {
2664 char *start, *end, *n;
2666 if (!strncmp(channel->invite_list, del,
2667 strlen(channel->invite_list) - 1)) {
2668 silc_free(channel->invite_list);
2669 channel->invite_list = NULL;
2671 start = strstr(channel->invite_list, del);
2672 if (start && strlen(start) >= len) {
2674 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2675 strncat(n, channel->invite_list, start - channel->invite_list);
2676 strncat(n, end + 1, ((channel->invite_list +
2677 strlen(channel->invite_list)) - end) - 1);
2678 silc_free(channel->invite_list);
2679 channel->invite_list = n;
2684 /* Send notify to the primary router */
2685 silc_server_send_notify_invite(server, SILC_PRIMARY_ROUTE(server),
2686 SILC_BROADCAST(server), channel,
2687 sender->id, add, del);
2689 /* Send command reply */
2690 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2694 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2695 SILC_STATUS_OK, 0, ident, 2,
2697 3, channel->invite_list,
2698 channel->invite_list ?
2699 strlen(channel->invite_list) : 0);
2702 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2703 SILC_STATUS_OK, 0, ident, 1,
2705 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2706 packet->data, packet->len, FALSE);
2707 silc_buffer_free(packet);
2711 silc_free(channel_id);
2712 silc_server_command_free(cmd);
2717 SilcSocketConnection sock;
2721 /* Quits connection to client. This gets called if client won't
2722 close the connection even when it has issued QUIT command. */
2724 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2726 QuitInternal q = (QuitInternal)context;
2728 /* Free all client specific data, such as client entry and entires
2729 on channels this client may be on. */
2730 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2732 q->sock->user_data = NULL;
2734 /* Close the connection on our side */
2735 silc_server_close_connection(q->server, q->sock);
2737 silc_free(q->signoff);
2741 /* Quits SILC session. This is the normal way to disconnect client. */
2743 SILC_SERVER_CMD_FUNC(quit)
2745 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2746 SilcServer server = cmd->server;
2747 SilcSocketConnection sock = cmd->sock;
2749 unsigned char *tmp = NULL;
2752 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2754 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2758 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2762 q = silc_calloc(1, sizeof(*q));
2765 q->signoff = tmp ? strdup(tmp) : NULL;
2767 /* We quit the connection with little timeout */
2768 silc_schedule_task_add(server->schedule, sock->sock,
2769 silc_server_command_quit_cb, (void *)q,
2770 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2773 silc_server_command_free(cmd);
2776 /* Server side of command KILL. This command is used by router operator
2777 to remove an client from the SILC Network temporarily. */
2779 SILC_SERVER_CMD_FUNC(kill)
2781 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2782 SilcServer server = cmd->server;
2783 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2784 SilcClientEntry remote_client;
2785 SilcClientID *client_id;
2786 unsigned char *tmp, *comment;
2787 SilcUInt32 tmp_len, tmp_len2;
2790 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2792 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2795 /* KILL command works only on router */
2796 if (server->server_type != SILC_ROUTER) {
2797 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2798 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
2802 /* Check whether client has the permissions. */
2803 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2804 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2805 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
2809 /* Get the client ID */
2810 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2812 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2813 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2817 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2819 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2820 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2825 /* Get the client entry */
2826 remote_client = silc_idlist_find_client_by_id(server->local_list,
2827 client_id, TRUE, NULL);
2829 if (!remote_client) {
2830 remote_client = silc_idlist_find_client_by_id(server->global_list,
2831 client_id, TRUE, NULL);
2833 if (!remote_client) {
2834 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2835 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2842 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2846 /* Send reply to the sender */
2847 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2850 /* Check if anyone is watching this nickname */
2851 if (server->server_type == SILC_ROUTER)
2852 silc_server_check_watcher_list(server, client, NULL,
2853 SILC_NOTIFY_TYPE_KILLED);
2855 /* Now do the killing */
2856 silc_server_kill_client(server, remote_client, comment, client->id,
2860 silc_server_command_free(cmd);
2863 /* Server side of command INFO. This sends information about us to
2864 the client. If client requested specific server we will send the
2865 command to that server. */
2867 SILC_SERVER_CMD_FUNC(info)
2869 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2870 SilcServer server = cmd->server;
2871 SilcBuffer packet, idp;
2874 char *dest_server, *server_info = NULL, *server_name;
2875 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2876 SilcServerEntry entry = NULL;
2877 SilcServerID *server_id = NULL;
2879 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2881 /* Get server name */
2882 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2885 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2887 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2889 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2890 SILC_STATUS_ERR_NO_SERVER_ID, 0);
2896 /* Check whether we have this server cached */
2897 entry = silc_idlist_find_server_by_id(server->local_list,
2898 server_id, TRUE, NULL);
2900 entry = silc_idlist_find_server_by_id(server->global_list,
2901 server_id, TRUE, NULL);
2902 if (!entry && server->server_type != SILC_SERVER) {
2903 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2904 SILC_STATUS_ERR_NO_SUCH_SERVER,
2911 /* Some buggy servers has sent request to router about themselves. */
2912 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2915 if ((!dest_server && !server_id && !entry) || (entry &&
2916 entry == server->id_entry) ||
2917 (dest_server && !cmd->pending &&
2918 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2919 /* Send our reply */
2920 char info_string[256];
2922 memset(info_string, 0, sizeof(info_string));
2923 snprintf(info_string, sizeof(info_string),
2924 "location: %s server: %s admin: %s <%s>",
2925 server->config->server_info->location,
2926 server->config->server_info->server_type,
2927 server->config->server_info->admin,
2928 server->config->server_info->email);
2930 server_info = info_string;
2931 entry = server->id_entry;
2933 /* Check whether we have this server cached */
2934 if (!entry && dest_server) {
2935 entry = silc_idlist_find_server_by_name(server->global_list,
2936 dest_server, TRUE, NULL);
2938 entry = silc_idlist_find_server_by_name(server->local_list,
2939 dest_server, TRUE, NULL);
2943 if (!cmd->pending &&
2944 server->server_type != SILC_SERVER && entry && !entry->server_info) {
2945 /* Send to the server */
2947 SilcUInt16 old_ident;
2949 old_ident = silc_command_get_ident(cmd->payload);
2950 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2951 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2953 silc_server_packet_send(server, entry->connection,
2954 SILC_PACKET_COMMAND, cmd->packet->flags,
2955 tmpbuf->data, tmpbuf->len, TRUE);
2957 /* Reprocess this packet after received reply from router */
2958 silc_server_command_pending(server, SILC_COMMAND_INFO,
2959 silc_command_get_ident(cmd->payload),
2960 silc_server_command_info,
2961 silc_server_command_dup(cmd));
2962 cmd->pending = TRUE;
2963 silc_command_set_ident(cmd->payload, old_ident);
2964 silc_buffer_free(tmpbuf);
2968 if (!entry && !cmd->pending && !server->standalone) {
2969 /* Send to the primary router */
2971 SilcUInt16 old_ident;
2973 old_ident = silc_command_get_ident(cmd->payload);
2974 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2975 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2977 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
2978 SILC_PACKET_COMMAND, cmd->packet->flags,
2979 tmpbuf->data, tmpbuf->len, TRUE);
2981 /* Reprocess this packet after received reply from router */
2982 silc_server_command_pending(server, SILC_COMMAND_INFO,
2983 silc_command_get_ident(cmd->payload),
2984 silc_server_command_info,
2985 silc_server_command_dup(cmd));
2986 cmd->pending = TRUE;
2987 silc_command_set_ident(cmd->payload, old_ident);
2988 silc_buffer_free(tmpbuf);
2993 silc_free(server_id);
2996 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2997 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3001 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
3003 server_info = entry->server_info;
3004 server_name = entry->server_name;
3006 /* Send the reply */
3007 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
3008 SILC_STATUS_OK, 0, ident, 3,
3009 2, idp->data, idp->len,
3011 strlen(server_name),
3014 strlen(server_info) : 0);
3015 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3016 packet->data, packet->len, FALSE);
3018 silc_buffer_free(packet);
3019 silc_buffer_free(idp);
3022 silc_server_command_free(cmd);
3025 /* Server side of command PING. This just replies to the ping. */
3027 SILC_SERVER_CMD_FUNC(ping)
3029 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3030 SilcServer server = cmd->server;
3035 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
3038 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
3040 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3041 SILC_STATUS_ERR_NO_SERVER_ID, 0);
3044 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
3048 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
3049 /* Send our reply */
3050 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3053 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3054 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3061 silc_server_command_free(cmd);
3064 /* Server side of command STATS. */
3066 SILC_SERVER_CMD_FUNC(stats)
3068 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3069 SilcServer server = cmd->server;
3070 SilcServerID *server_id;
3073 SilcBuffer packet, stats;
3074 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3077 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1);
3080 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3082 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3083 SILC_STATUS_ERR_NO_SERVER_ID, 0);
3086 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3090 /* The ID must be ours */
3091 if (!SILC_ID_SERVER_COMPARE(server->id, server_id)) {
3092 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3093 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3094 silc_free(server_id);
3097 silc_free(server_id);
3099 /* If we are router then just send everything we got. If we are normal
3100 server then we'll send this to our router to get all the latest
3101 statistical information. */
3102 if (!cmd->pending && server->server_type != SILC_ROUTER &&
3103 !server->standalone) {
3104 /* Send request to our router */
3105 SilcBuffer idp = silc_id_payload_encode(server->router->id,
3107 packet = silc_command_payload_encode_va(SILC_COMMAND_STATS,
3108 ++server->cmd_ident, 1,
3109 1, idp->data, idp->len);
3110 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
3111 SILC_PACKET_COMMAND, 0, packet->data,
3112 packet->len, FALSE);
3114 /* Reprocess this packet after received reply from router */
3115 silc_server_command_pending(server, SILC_COMMAND_STATS,
3117 silc_server_command_stats,
3118 silc_server_command_dup(cmd));
3119 cmd->pending = TRUE;
3120 silc_buffer_free(packet);
3121 silc_buffer_free(idp);
3125 /* Send our reply to sender */
3126 uptime = time(NULL) - server->starttime;
3128 stats = silc_buffer_alloc_size(60);
3129 silc_buffer_format(stats,
3130 SILC_STR_UI_INT(server->starttime),
3131 SILC_STR_UI_INT(uptime),
3132 SILC_STR_UI_INT(server->stat.my_clients),
3133 SILC_STR_UI_INT(server->stat.my_channels),
3134 SILC_STR_UI_INT(server->stat.my_server_ops),
3135 SILC_STR_UI_INT(server->stat.my_router_ops),
3136 SILC_STR_UI_INT(server->stat.cell_clients),
3137 SILC_STR_UI_INT(server->stat.cell_channels),
3138 SILC_STR_UI_INT(server->stat.cell_servers),
3139 SILC_STR_UI_INT(server->stat.clients),
3140 SILC_STR_UI_INT(server->stat.channels),
3141 SILC_STR_UI_INT(server->stat.servers),
3142 SILC_STR_UI_INT(server->stat.routers),
3143 SILC_STR_UI_INT(server->stat.server_ops),
3144 SILC_STR_UI_INT(server->stat.router_ops),
3147 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_STATS,
3148 SILC_STATUS_OK, 0, ident, 2,
3150 3, stats->data, stats->len);
3151 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
3152 0, packet->data, packet->len, FALSE);
3153 silc_buffer_free(packet);
3154 silc_buffer_free(stats);
3157 silc_server_command_free(cmd);
3160 /* Internal routine to join channel. The channel sent to this function
3161 has been either created or resolved from ID lists. This joins the sent
3162 client to the channel. */
3164 static void silc_server_command_join_channel(SilcServer server,
3165 SilcServerCommandContext cmd,
3166 SilcChannelEntry channel,
3167 SilcClientID *client_id,
3171 const unsigned char *auth,
3172 SilcUInt32 auth_len)
3174 SilcSocketConnection sock = cmd->sock;
3176 SilcUInt32 tmp_len, user_count;
3177 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
3178 SilcClientEntry client;
3179 SilcChannelClientEntry chl;
3180 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
3181 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3182 char check[512], check2[512];
3183 bool founder = FALSE;
3185 unsigned char *fkey = NULL;
3186 SilcUInt32 fkey_len = 0;
3188 SILC_LOG_DEBUG(("Joining client to channel"));
3193 /* Get the client entry */
3194 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3195 client = (SilcClientEntry)sock->user_data;
3197 client = silc_server_get_client_resolve(server, client_id, FALSE,
3204 silc_server_command_send_status_reply(
3205 cmd, SILC_COMMAND_JOIN,
3206 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3210 /* The client info is being resolved. Reprocess this packet after
3211 receiving the reply to the query. */
3212 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
3214 silc_server_command_join,
3215 silc_server_command_dup(cmd));
3216 cmd->pending = TRUE;
3220 cmd->pending = FALSE;
3224 * Check founder auth payload if provided. If client can gain founder
3225 * privileges it can override various conditions on joining the channel,
3226 * and can have directly the founder mode set on the channel.
3228 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3229 SilcIDListData idata = (SilcIDListData)client;
3230 SilcChannelClientEntry chl2;
3231 SilcHashTableList htl;
3233 if (channel->founder_key && idata->public_key &&
3234 silc_pkcs_public_key_compare(channel->founder_key,
3235 idata->public_key)) {
3236 /* Check whether the client is to become founder */
3237 if (silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
3238 channel->founder_key, 0, server->sha1hash,
3239 client->id, SILC_ID_CLIENT)) {
3241 /* There cannot be anyone else as founder on the channel now. This
3242 client is definitely the founder due to this authentication */
3243 silc_hash_table_list(channel->user_list, &htl);
3244 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
3245 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
3246 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3247 silc_server_force_cumode_change(server, NULL, channel, chl2,
3251 silc_hash_table_list_reset(&htl);
3253 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3260 * Check channel modes
3264 memset(check, 0, sizeof(check));
3265 memset(check2, 0, sizeof(check2));
3266 strncat(check, client->nickname, strlen(client->nickname));
3267 strncat(check, "!", 1);
3268 strncat(check, client->username, strlen(client->username));
3269 if (!strchr(client->username, '@')) {
3270 strncat(check, "@", 1);
3271 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3274 strncat(check2, client->nickname, strlen(client->nickname));
3275 if (!strchr(client->nickname, '@')) {
3276 strncat(check2, "@", 1);
3277 strncat(check2, server->server_name, strlen(server->server_name));
3279 strncat(check2, "!", 1);
3280 strncat(check2, client->username, strlen(client->username));
3281 if (!strchr(client->username, '@')) {
3282 strncat(check2, "@", 1);
3283 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3286 /* Check invite list if channel is invite-only channel */
3287 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3288 if (!channel->invite_list ||
3289 (!silc_string_match(channel->invite_list, check) &&
3290 !silc_string_match(channel->invite_list, check2))) {
3291 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3292 SILC_STATUS_ERR_NOT_INVITED, 0);
3297 /* Check ban list if it exists. If the client's nickname, server,
3298 username and/or hostname is in the ban list the access to the
3299 channel is denied. */
3300 if (channel->ban_list) {
3301 if (silc_string_match(channel->ban_list, check) ||
3302 silc_string_match(channel->ban_list, check2)) {
3303 silc_server_command_send_status_reply(
3304 cmd, SILC_COMMAND_JOIN,
3305 SILC_STATUS_ERR_BANNED_FROM_CHANNEL, 0);
3310 /* Check user count limit if set. */
3311 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3312 if (silc_hash_table_count(channel->user_list) + 1 >
3313 channel->user_limit) {
3314 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3315 SILC_STATUS_ERR_CHANNEL_IS_FULL,
3322 /* Check the channel passphrase if set. */
3323 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3324 /* Get passphrase */
3325 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3327 passphrase = silc_memdup(tmp, tmp_len);
3329 if (!passphrase || !channel->passphrase ||
3330 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3331 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3332 SILC_STATUS_ERR_BAD_PASSWORD, 0);
3338 * Client is allowed to join to the channel. Make it happen.
3341 /* Check whether the client already is on the channel */
3342 if (silc_server_client_on_channel(client, channel, NULL)) {
3343 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3344 SILC_STATUS_ERR_USER_ON_CHANNEL, 0);
3348 /* Generate new channel key as protocol dictates */
3350 if (!silc_server_create_channel_key(server, channel, 0))
3353 /* Send the channel key. This is broadcasted to the channel but is not
3354 sent to the client who is joining to the channel. */
3355 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3356 silc_server_send_channel_key(server, NULL, channel,
3357 server->server_type == SILC_ROUTER ?
3358 FALSE : !server->standalone);
3361 /* Join the client to the channel by adding it to channel's user list.
3362 Add also the channel to client entry's channels list for fast cross-
3364 chl = silc_calloc(1, sizeof(*chl));
3366 chl->client = client;
3367 chl->channel = channel;
3368 silc_hash_table_add(channel->user_list, client, chl);
3369 silc_hash_table_add(client->channels, channel, chl);
3370 channel->user_count++;
3371 channel->disabled = FALSE;
3373 /* Get users on the channel */
3374 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3377 /* Encode Client ID Payload of the original client who wants to join */
3378 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3380 /* Encode command reply packet */
3381 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3382 SILC_PUT32_MSB(channel->mode, mode);
3383 SILC_PUT32_MSB(created, tmp2);
3384 SILC_PUT32_MSB(user_count, tmp3);
3386 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3387 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3388 keyp = silc_channel_key_payload_encode(silc_id_get_len(channel->id,
3391 strlen(channel->channel_key->
3393 channel->channel_key->cipher->name,
3394 channel->key_len / 8, channel->key);
3398 if (channel->founder_key)
3399 fkey = silc_pkcs_public_key_encode(channel->founder_key, &fkey_len);
3402 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3403 SILC_STATUS_OK, 0, ident, 14,
3404 2, channel->channel_name,
3405 strlen(channel->channel_name),
3406 3, chidp->data, chidp->len,
3407 4, clidp->data, clidp->len,
3410 7, keyp ? keyp->data : NULL,
3411 keyp ? keyp->len : 0,
3412 8, channel->ban_list,
3414 strlen(channel->ban_list) : 0,
3415 9, channel->invite_list,
3416 channel->invite_list ?
3417 strlen(channel->invite_list) : 0,
3420 strlen(channel->topic) : 0,
3421 11, silc_hmac_get_name(channel->hmac),
3422 strlen(silc_hmac_get_name(channel->
3425 13, user_list->data, user_list->len,
3426 14, mode_list->data,
3428 15, fkey, fkey_len);
3430 /* Send command reply */
3431 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3432 reply->data, reply->len, FALSE);
3434 /* Send JOIN notify to locally connected clients on the channel. If
3435 we are normal server then router will send or have sent JOIN notify
3436 already. However since we've added the client already to our channel
3437 we'll ignore it (in packet_receive.c) so we must send it here. If
3438 we are router then this will send it to local clients and local
3440 SILC_LOG_DEBUG(("Send JOIN notify to channel"));
3441 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3442 SILC_NOTIFY_TYPE_JOIN, 2,
3443 clidp->data, clidp->len,
3444 chidp->data, chidp->len);
3446 /* Update statistics */
3447 server->stat.my_chanclients++;
3448 if (server->server_type == SILC_ROUTER) {
3449 server->stat.cell_chanclients++;
3450 server->stat.chanclients++;
3453 if (!cmd->pending) {
3454 /* Send JOIN notify packet to our primary router */
3455 silc_server_send_notify_join(server, SILC_PRIMARY_ROUTE(server),
3456 SILC_BROADCAST(server), channel, client->id);
3459 /* Distribute the channel key to all backup routers. */
3460 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3461 keyp->data, keyp->len, FALSE, TRUE);
3463 /* If client became founder by providing correct founder auth data
3464 notify the mode change to the channel. */
3466 SILC_PUT32_MSB(chl->mode, mode);
3467 SILC_LOG_DEBUG(("Send CUMODE_CHANGE notify to channel"));
3468 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3469 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
3470 clidp->data, clidp->len,
3471 mode, 4, clidp->data, clidp->len,
3476 /* Set CUMODE notify type to network */
3478 silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
3479 SILC_BROADCAST(server), channel,
3480 chl->mode, client->id, SILC_ID_CLIENT,
3481 client->id, channel->founder_key);
3483 silc_buffer_free(reply);
3484 silc_buffer_free(clidp);
3485 silc_buffer_free(chidp);
3486 silc_buffer_free(keyp);
3487 silc_buffer_free(user_list);
3488 silc_buffer_free(mode_list);
3492 silc_free(passphrase);
3495 /* Server side of command JOIN. Joins client into requested channel. If
3496 the channel does not exist it will be created. */
3498 SILC_SERVER_CMD_FUNC(join)
3500 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3501 SilcServer server = cmd->server;
3502 unsigned char *auth;
3503 SilcUInt32 tmp_len, auth_len;
3504 char *tmp, *channel_name = NULL, *cipher, *hmac;
3505 SilcChannelEntry channel;
3506 SilcUInt32 umode = 0;
3507 bool created = FALSE, create_key = TRUE;
3508 SilcClientID *client_id;
3510 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3512 /* Get channel name */
3513 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3515 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3516 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3523 channel_name[255] = '\0';
3525 if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
3526 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3527 SILC_STATUS_ERR_BAD_CHANNEL, 0);
3531 /* Get Client ID of the client who is joining to the channel */
3532 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3534 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3535 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3539 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3541 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3542 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3547 /* Get cipher, hmac name and auth payload */
3548 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3549 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3550 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3552 /* See if the channel exists */
3553 channel = silc_idlist_find_channel_by_name(server->local_list,
3554 channel_name, NULL);
3556 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3557 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3558 silc_free(client_id);
3559 client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
3562 (channel->disabled && server->server_type != SILC_ROUTER)) {
3563 /* Channel not found */
3565 /* If we are standalone server we don't have a router, we just create
3566 the channel by ourselves. */
3567 if (server->standalone) {
3568 channel = silc_server_create_new_channel(server, server->id, cipher,
3569 hmac, channel_name, TRUE);
3571 silc_server_command_send_status_reply(
3572 cmd, SILC_COMMAND_JOIN,
3573 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
3575 silc_free(client_id);
3579 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3585 /* The channel does not exist on our server. If we are normal server
3586 we will send JOIN command to our router which will handle the
3587 joining procedure (either creates the channel if it doesn't exist
3588 or joins the client to it). */
3589 if (server->server_type != SILC_ROUTER) {
3591 SilcUInt16 old_ident;
3593 /* If this is pending command callback then we've resolved
3594 it and it didn't work, return since we've notified the
3595 client already in the command reply callback. */
3597 silc_free(client_id);
3601 old_ident = silc_command_get_ident(cmd->payload);
3602 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3603 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3605 /* Send JOIN command to our router */
3606 silc_server_packet_send(server, (SilcSocketConnection)
3607 SILC_PRIMARY_ROUTE(server),
3608 SILC_PACKET_COMMAND, cmd->packet->flags,
3609 tmpbuf->data, tmpbuf->len, TRUE);
3611 /* Reprocess this packet after received reply from router */
3612 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3613 silc_command_get_ident(cmd->payload),
3614 silc_server_command_join,
3615 silc_server_command_dup(cmd));
3616 cmd->pending = TRUE;
3617 silc_command_set_ident(cmd->payload, old_ident);
3618 silc_buffer_free(tmpbuf);
3619 silc_free(client_id);
3623 /* We are router and the channel does not seem exist so we will check
3624 our global list as well for the channel. */
3625 channel = silc_idlist_find_channel_by_name(server->global_list,
3626 channel_name, NULL);
3628 /* Channel really does not exist, create it */
3629 channel = silc_server_create_new_channel(server, server->id, cipher,
3630 hmac, channel_name, TRUE);
3632 silc_server_command_send_status_reply(
3633 cmd, SILC_COMMAND_JOIN,
3634 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
3635 silc_free(client_id);
3639 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3647 /* Channel not found */
3649 /* If the command came from router and we are normal server then
3650 something went wrong with the joining as the channel was not found.
3651 We can't do anything else but ignore this. */
3652 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3653 server->server_type != SILC_ROUTER) {
3654 silc_free(client_id);
3658 /* We are router and the channel does not seem exist so we will check
3659 our global list as well for the channel. */
3660 channel = silc_idlist_find_channel_by_name(server->global_list,
3661 channel_name, NULL);
3663 /* Channel really does not exist, create it */
3664 channel = silc_server_create_new_channel(server, server->id, cipher,
3665 hmac, channel_name, TRUE);
3667 silc_server_command_send_status_reply(
3668 cmd, SILC_COMMAND_JOIN,
3669 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
3670 silc_free(client_id);
3674 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3681 /* Check whether the channel was created by our router */
3682 if (cmd->pending && context2) {
3683 SilcServerCommandReplyContext reply = context2;
3685 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3686 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3687 SILC_GET32_MSB(created, tmp);
3688 if (silc_argument_get_arg_type(reply->args, 7, NULL))
3689 create_key = FALSE; /* Router returned the key already */
3691 if (silc_command_get_status(reply->payload, NULL, NULL) &&
3692 channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3693 /* Save channel passphrase, if user provided it successfully */
3696 pa = silc_argument_get_arg_type(cmd->args, 3, &pa_len);
3698 silc_free(channel->passphrase);
3699 channel->passphrase = silc_memdup(pa, pa_len);
3704 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
3705 !channel->disabled && !silc_hash_table_count(channel->user_list))
3709 /* If the channel does not have global users and is also empty the client
3710 will be the channel founder and operator. */
3711 if (!channel->disabled &&
3712 !channel->global_users && !silc_hash_table_count(channel->user_list))
3713 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3715 /* Join to the channel */
3716 silc_server_command_join_channel(server, cmd, channel, client_id,
3717 created, create_key, umode,
3720 silc_free(client_id);
3723 silc_server_command_free(cmd);
3726 /* Server side of command MOTD. Sends server's current "message of the
3727 day" to the client. */
3729 SILC_SERVER_CMD_FUNC(motd)
3731 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3732 SilcServer server = cmd->server;
3733 SilcBuffer packet, idp;
3734 char *motd, *dest_server;
3735 SilcUInt32 motd_len;
3736 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3738 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3740 /* Get server name */
3741 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3743 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3744 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3748 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3751 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3753 if (server->config && server->config->server_info &&
3754 server->config->server_info->motd_file) {
3756 motd = silc_file_readfile(server->config->server_info->motd_file,
3762 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3769 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3775 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3776 packet->data, packet->len, FALSE);
3777 silc_buffer_free(packet);
3778 silc_buffer_free(idp);
3780 SilcServerEntry entry;
3782 /* Check whether we have this server cached */
3783 entry = silc_idlist_find_server_by_name(server->global_list,
3784 dest_server, TRUE, NULL);
3786 entry = silc_idlist_find_server_by_name(server->local_list,
3787 dest_server, TRUE, NULL);
3790 if (server->server_type != SILC_SERVER && !cmd->pending &&
3791 entry && !entry->motd) {
3792 /* Send to the server */
3794 SilcUInt16 old_ident;
3796 old_ident = silc_command_get_ident(cmd->payload);
3797 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3798 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3800 silc_server_packet_send(server, entry->connection,
3801 SILC_PACKET_COMMAND, cmd->packet->flags,
3802 tmpbuf->data, tmpbuf->len, TRUE);
3804 /* Reprocess this packet after received reply from router */
3805 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3806 silc_command_get_ident(cmd->payload),
3807 silc_server_command_motd,
3808 silc_server_command_dup(cmd));
3809 cmd->pending = TRUE;
3810 silc_command_set_ident(cmd->payload, old_ident);
3811 silc_buffer_free(tmpbuf);
3815 if (!entry && !cmd->pending && !server->standalone) {
3816 /* Send to the primary router */
3818 SilcUInt16 old_ident;
3820 old_ident = silc_command_get_ident(cmd->payload);
3821 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3822 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3824 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
3825 SILC_PACKET_COMMAND, cmd->packet->flags,
3826 tmpbuf->data, tmpbuf->len, TRUE);
3828 /* Reprocess this packet after received reply from router */
3829 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3830 silc_command_get_ident(cmd->payload),
3831 silc_server_command_motd,
3832 silc_server_command_dup(cmd));
3833 cmd->pending = TRUE;
3834 silc_command_set_ident(cmd->payload, old_ident);
3835 silc_buffer_free(tmpbuf);
3840 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3841 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3845 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3846 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3847 SILC_STATUS_OK, 0, ident, 2,
3851 strlen(entry->motd) : 0);
3852 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3853 packet->data, packet->len, FALSE);
3854 silc_buffer_free(packet);
3855 silc_buffer_free(idp);
3859 silc_server_command_free(cmd);
3862 /* Server side of command UMODE. Client can use this command to set/unset
3863 user mode. Client actually cannot set itself to be as server/router
3864 operator so this can be used only to unset the modes. */
3866 SILC_SERVER_CMD_FUNC(umode)
3868 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3869 SilcServer server = cmd->server;
3870 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3872 unsigned char *tmp_mask, m[4];
3873 SilcUInt32 mask = 0;
3874 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3875 bool set_mask = FALSE;
3877 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3880 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2);
3882 /* Get the client's mode mask */
3883 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3885 SILC_GET32_MSB(mask, tmp_mask);
3890 /* Check that mode changing is allowed. */
3891 if (!silc_server_check_umode_rights(server, client, mask)) {
3892 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3893 SILC_STATUS_ERR_PERM_DENIED, 0);
3897 /* Anonymous mode cannot be set by client */
3898 if (mask & SILC_UMODE_ANONYMOUS) {
3899 if (!(client->mode & SILC_UMODE_ANONYMOUS)) {
3900 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3901 SILC_STATUS_ERR_PERM_DENIED, 0);
3905 if (client->mode & SILC_UMODE_ANONYMOUS) {
3906 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3907 SILC_STATUS_ERR_PERM_DENIED, 0);
3912 /* Update statistics */
3913 if (mask & SILC_UMODE_GONE) {
3914 if (!(client->mode & SILC_UMODE_GONE))
3915 server->stat.my_aways++;
3917 if (client->mode & SILC_UMODE_GONE)
3918 server->stat.my_aways--;
3921 /* Change the mode */
3922 client->mode = mask;
3924 /* Send UMODE change to primary router */
3925 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
3926 SILC_BROADCAST(server), client->id,
3929 /* Check if anyone is watching this nickname */
3930 if (server->server_type == SILC_ROUTER)
3931 silc_server_check_watcher_list(server, client, NULL,
3932 SILC_NOTIFY_TYPE_UMODE_CHANGE);
3935 /* Send command reply to sender */
3936 SILC_PUT32_MSB(client->mode, m);
3937 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3938 SILC_STATUS_OK, 0, ident, 1,
3940 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3941 packet->data, packet->len, FALSE);
3942 silc_buffer_free(packet);
3945 silc_server_command_free(cmd);
3948 /* Server side command of CMODE. Changes channel mode */
3950 SILC_SERVER_CMD_FUNC(cmode)
3952 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3953 SilcServer server = cmd->server;
3954 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3955 SilcIDListData idata = (SilcIDListData)client;
3956 SilcChannelID *channel_id = NULL;
3957 SilcChannelEntry channel;
3958 SilcChannelClientEntry chl;
3959 SilcBuffer packet, cidp;
3960 unsigned char *tmp, *tmp_id, *tmp_mask;
3961 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3962 SilcUInt32 mode_mask = 0, old_mask = 0, tmp_len, tmp_len2;
3963 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3964 bool set_mask = FALSE;
3965 SilcPublicKey founder_key = NULL;
3966 unsigned char *fkey = NULL;
3967 SilcUInt32 fkey_len = 0;
3969 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 7);
3971 /* Get Channel ID */
3972 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3974 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3975 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3976 silc_server_command_free(cmd);
3979 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
3981 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3982 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3983 silc_server_command_free(cmd);
3987 /* Get channel entry */
3988 channel = silc_idlist_find_channel_by_id(server->local_list,
3991 channel = silc_idlist_find_channel_by_id(server->global_list,
3994 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3995 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
3997 silc_free(channel_id);
3998 silc_server_command_free(cmd);
4002 old_mask = channel->mode;
4004 /* Get the channel mode mask */
4005 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4007 SILC_GET32_MSB(mode_mask, tmp_mask);
4011 /* Check whether this client is on the channel */
4012 if (!silc_server_client_on_channel(client, channel, &chl)) {
4013 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4014 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4018 /* Check that client has rights to change any requested channel modes */
4019 if (set_mask && !silc_server_check_cmode_rights(server, channel, chl,
4021 SILC_LOG_DEBUG(("Client does not have rights to change mode"));
4022 silc_server_command_send_status_reply(
4023 cmd, SILC_COMMAND_CMODE,
4024 (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) ?
4025 SILC_STATUS_ERR_NO_CHANNEL_PRIV :
4026 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV), 0);
4030 /* If mode mask was not sent as argument then merely return the current
4031 mode mask to the sender. */
4034 SILC_PUT32_MSB(channel->mode, m);
4035 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4036 SILC_STATUS_OK, 0, ident, 2,
4037 2, tmp_id, tmp_len2,
4039 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4040 packet->data, packet->len, FALSE);
4041 silc_buffer_free(packet);
4046 * Check the modes. Modes that requires nothing special operation are
4050 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
4051 /* Channel uses private keys to protect traffic. Client(s) has set the
4052 key locally they want to use, server does not know that key. */
4053 /* Nothing interesting to do here */
4055 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
4056 /* The mode is removed and we need to generate and distribute
4057 new channel key. Clients are not using private channel keys
4058 anymore after this. */
4060 /* Re-generate channel key */
4061 if (!silc_server_create_channel_key(server, channel, 0))
4064 /* Send the channel key. This sends it to our local clients and if
4065 we are normal server to our router as well. */
4066 silc_server_send_channel_key(server, NULL, channel,
4067 server->server_type == SILC_ROUTER ?
4068 FALSE : !server->standalone);
4070 cipher = channel->channel_key->cipher->name;
4071 hmac = (char *)silc_hmac_get_name(channel->hmac);
4075 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
4076 /* User limit is set on channel */
4077 SilcUInt32 user_limit;
4079 /* Get user limit */
4080 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
4082 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
4083 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4084 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4088 SILC_GET32_MSB(user_limit, tmp);
4089 channel->user_limit = user_limit;
4092 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
4093 /* User limit mode is unset. Remove user limit */
4094 channel->user_limit = 0;
4097 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
4098 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
4099 /* Passphrase has been set to channel */
4101 /* Get the passphrase */
4102 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
4104 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4105 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4109 /* Save the passphrase */
4110 passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
4113 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
4114 /* Passphrase mode is unset. remove the passphrase */
4115 silc_free(channel->passphrase);
4116 channel->passphrase = NULL;
4120 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
4121 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
4122 /* Cipher to use protect the traffic */
4123 SilcCipher newkey, oldkey;
4126 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
4128 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4129 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4133 /* Delete old cipher and allocate the new one */
4134 if (!silc_cipher_alloc(cipher, &newkey)) {
4135 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4136 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4140 oldkey = channel->channel_key;
4141 channel->channel_key = newkey;
4143 /* Re-generate channel key */
4144 if (!silc_server_create_channel_key(server, channel, 0)) {
4145 /* We don't have new key, revert to old one */
4146 channel->channel_key = oldkey;
4150 /* Remove old channel key for good */
4151 silc_cipher_free(oldkey);
4153 /* Send the channel key. This sends it to our local clients and if
4154 we are normal server to our router as well. */
4155 silc_server_send_channel_key(server, NULL, channel,
4156 server->server_type == SILC_ROUTER ?
4157 FALSE : !server->standalone);
4160 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
4161 /* Cipher mode is unset. Remove the cipher and revert back to
4163 SilcCipher newkey, oldkey;
4164 cipher = channel->cipher;
4166 /* Delete old cipher and allocate default one */
4167 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
4168 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4169 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4173 oldkey = channel->channel_key;
4174 channel->channel_key = newkey;
4176 /* Re-generate channel key */
4177 if (!silc_server_create_channel_key(server, channel, 0)) {
4178 /* We don't have new key, revert to old one */
4179 channel->channel_key = oldkey;
4183 /* Remove old channel key for good */
4184 silc_cipher_free(oldkey);
4186 /* Send the channel key. This sends it to our local clients and if
4187 we are normal server to our router as well. */
4188 silc_server_send_channel_key(server, NULL, channel,
4189 server->server_type == SILC_ROUTER ?
4190 FALSE : !server->standalone);
4194 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
4195 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
4196 /* HMAC to use protect the traffic */
4197 unsigned char hash[32];
4201 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4203 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4204 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4208 /* Delete old hmac and allocate the new one */
4209 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4210 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4211 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4215 silc_hmac_free(channel->hmac);
4216 channel->hmac = newhmac;
4218 /* Set the HMAC key out of current channel key. The client must do
4220 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4221 channel->key_len / 8, hash);
4222 silc_hmac_set_key(channel->hmac, hash,
4223 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4224 memset(hash, 0, sizeof(hash));
4227 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4228 /* Hmac mode is unset. Remove the hmac and revert back to
4231 unsigned char hash[32];
4232 hmac = channel->hmac_name;
4234 /* Delete old hmac and allocate default one */
4235 silc_hmac_free(channel->hmac);
4236 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4237 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4238 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4242 silc_hmac_free(channel->hmac);
4243 channel->hmac = newhmac;
4245 /* Set the HMAC key out of current channel key. The client must do
4247 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4248 channel->key_len / 8,
4250 silc_hmac_set_key(channel->hmac, hash,
4251 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4252 memset(hash, 0, sizeof(hash));
4256 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4257 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4258 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4259 /* Set the founder authentication */
4260 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4262 silc_server_command_send_status_reply(
4263 cmd, SILC_COMMAND_CMODE,
4264 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4268 /* Verify the payload before setting the mode */
4269 if (!silc_auth_verify_data(tmp, tmp_len, SILC_AUTH_PUBLIC_KEY,
4270 idata->public_key, 0, server->sha1hash,
4271 client->id, SILC_ID_CLIENT)) {
4272 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4273 SILC_STATUS_ERR_AUTH_FAILED,
4278 /* Save the public key */
4279 channel->founder_key = silc_pkcs_public_key_copy(idata->public_key);
4280 if (!channel->founder_key) {
4281 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4282 SILC_STATUS_ERR_AUTH_FAILED,
4287 founder_key = channel->founder_key;
4288 fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
4290 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4291 SILC_STATUS_ERR_AUTH_FAILED,
4293 silc_pkcs_public_key_free(channel->founder_key);
4294 channel->founder_key = NULL;
4300 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4301 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4302 if (channel->founder_key)
4303 silc_pkcs_public_key_free(channel->founder_key);
4304 channel->founder_key = NULL;
4309 /* Finally, set the mode */
4310 old_mask = channel->mode = mode_mask;
4312 /* Send CMODE_CHANGE notify. */
4313 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4314 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4315 SILC_NOTIFY_TYPE_CMODE_CHANGE, 6,
4316 cidp->data, cidp->len,
4318 cipher, cipher ? strlen(cipher) : 0,
4319 hmac, hmac ? strlen(hmac) : 0,
4320 passphrase, passphrase ?
4321 strlen(passphrase) : 0,
4324 /* Set CMODE notify type to network */
4325 silc_server_send_notify_cmode(server, SILC_PRIMARY_ROUTE(server),
4326 SILC_BROADCAST(server), channel,
4327 mode_mask, client->id, SILC_ID_CLIENT,
4328 cipher, hmac, passphrase, founder_key);
4330 /* Send command reply to sender */
4331 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4332 SILC_STATUS_OK, 0, ident, 2,
4333 2, tmp_id, tmp_len2,
4335 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4336 packet->data, packet->len, FALSE);
4338 silc_buffer_free(packet);
4339 silc_buffer_free(cidp);
4342 channel->mode = old_mask;
4344 silc_free(channel_id);
4345 silc_server_command_free(cmd);
4348 /* Server side of CUMODE command. Changes client's mode on a channel. */
4350 SILC_SERVER_CMD_FUNC(cumode)
4352 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4353 SilcServer server = cmd->server;
4354 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4355 SilcIDListData idata = (SilcIDListData)client;
4356 SilcChannelID *channel_id;
4357 SilcClientID *client_id;
4358 SilcChannelEntry channel;
4359 SilcClientEntry target_client;
4360 SilcChannelClientEntry chl;
4361 SilcBuffer packet, idp;
4362 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4363 SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4365 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4366 SilcPublicKey founder_key = NULL;
4367 unsigned char *fkey = NULL;
4368 SilcUInt32 fkey_len = 0;
4370 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4372 /* Get Channel ID */
4373 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4375 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4376 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4379 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
4381 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4382 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4386 /* Get channel entry */
4387 channel = silc_idlist_find_channel_by_id(server->local_list,
4390 channel = silc_idlist_find_channel_by_id(server->global_list,
4393 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4394 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4400 /* Check whether sender is on the channel */
4401 if (!silc_server_client_on_channel(client, channel, &chl)) {
4402 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4403 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4406 sender_mask = chl->mode;
4408 /* Get the target client's channel mode mask */
4409 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4411 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4412 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4416 SILC_GET32_MSB(target_mask, tmp_mask);
4418 /* Get target Client ID */
4419 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4421 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4422 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4425 client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
4427 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4428 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4432 /* Get target client's entry */
4433 target_client = silc_idlist_find_client_by_id(server->local_list,
4434 client_id, TRUE, NULL);
4435 if (!target_client) {
4436 target_client = silc_idlist_find_client_by_id(server->global_list,
4437 client_id, TRUE, NULL);
4440 if (target_client != client &&
4441 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4442 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4443 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4444 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
4448 /* Check whether target client is on the channel */
4449 if (target_client != client) {
4450 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4451 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4452 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL, 0);
4461 /* If the target client is founder, no one else can change their mode
4463 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4464 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4465 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
4470 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4471 if (target_client != client) {
4472 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4473 SILC_STATUS_ERR_NOT_YOU, 0);
4477 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4478 /* The client tries to claim the founder rights. */
4479 unsigned char *tmp_auth;
4480 SilcUInt32 tmp_auth_len;
4481 SilcChannelClientEntry chl2;
4482 SilcHashTableList htl;
4484 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4485 !channel->founder_key || !idata->public_key ||
4486 !silc_pkcs_public_key_compare(channel->founder_key,
4487 idata->public_key)) {
4488 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4489 SILC_STATUS_ERR_AUTH_FAILED, 0);
4493 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4495 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4496 SILC_STATUS_ERR_AUTH_FAILED, 0);
4500 /* Verify the authentication payload */
4501 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len, SILC_AUTH_PUBLIC_KEY,
4502 channel->founder_key, 0, server->sha1hash,
4503 client->id, SILC_ID_CLIENT)) {
4504 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4505 SILC_STATUS_ERR_AUTH_FAILED, 0);
4510 founder_key = channel->founder_key;
4511 fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
4513 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4514 SILC_STATUS_ERR_AUTH_FAILED, 0);
4518 /* There cannot be anyone else as founder on the channel now. This
4519 client is definitely the founder due to this authentication */
4520 silc_hash_table_list(channel->user_list, &htl);
4521 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
4522 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
4523 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4524 silc_server_force_cumode_change(server, NULL, channel, chl2,
4528 silc_hash_table_list_reset(&htl);
4530 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4533 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4534 if (target_client == client) {
4535 /* Remove channel founder rights from itself */
4536 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4539 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4540 SILC_STATUS_ERR_NOT_YOU, 0);
4546 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4547 /* Promote to operator */
4548 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4549 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4550 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4551 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4552 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
4557 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4561 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4562 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4563 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4564 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4565 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
4570 /* Demote to normal user */
4571 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4576 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4577 if (target_client != client) {
4578 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4579 SILC_STATUS_ERR_NOT_YOU, 0);
4583 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
4584 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4588 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4589 if (target_client != client) {
4590 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4591 SILC_STATUS_ERR_NOT_YOU, 0);
4595 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4600 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4601 if (target_client != client) {
4602 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4603 SILC_STATUS_ERR_NOT_YOU, 0);
4607 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)) {
4608 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4612 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4613 if (target_client != client) {
4614 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4615 SILC_STATUS_ERR_NOT_YOU, 0);
4619 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4624 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4625 if (target_client != client) {
4626 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4627 SILC_STATUS_ERR_NOT_YOU, 0);
4631 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)) {
4632 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4636 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4637 if (target_client != client) {
4638 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4639 SILC_STATUS_ERR_NOT_YOU, 0);
4643 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4648 if (target_mask & SILC_CHANNEL_UMODE_QUIET) {
4649 if (!(chl->mode & SILC_CHANNEL_UMODE_QUIET)) {
4650 if (client == target_client) {
4651 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4652 SILC_STATUS_ERR_PERM_DENIED, 0);
4655 chl->mode |= SILC_CHANNEL_UMODE_QUIET;
4659 if (chl->mode & SILC_CHANNEL_UMODE_QUIET) {
4660 if (client == target_client) {
4661 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4662 SILC_STATUS_ERR_PERM_DENIED, 0);
4665 chl->mode &= ~SILC_CHANNEL_UMODE_QUIET;
4670 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4671 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4673 /* Send notify to channel, notify only if mode was actually changed. */
4675 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4676 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
4677 idp->data, idp->len,
4682 /* Set CUMODE notify type to network */
4683 silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
4684 SILC_BROADCAST(server), channel,
4685 target_mask, client->id, SILC_ID_CLIENT,
4686 target_client->id, founder_key);
4689 /* Send command reply to sender */
4690 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4691 SILC_STATUS_OK, 0, ident, 3,
4693 3, tmp_ch_id, tmp_ch_len,
4694 4, tmp_id, tmp_len);
4695 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4696 packet->data, packet->len, FALSE);
4698 silc_buffer_free(packet);
4699 silc_free(channel_id);
4700 silc_free(client_id);
4701 silc_buffer_free(idp);
4705 silc_server_command_free(cmd);
4708 /* Server side of KICK command. Kicks client out of channel. */
4710 SILC_SERVER_CMD_FUNC(kick)
4712 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4713 SilcServer server = cmd->server;
4714 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4715 SilcClientEntry target_client;
4716 SilcChannelID *channel_id;
4717 SilcClientID *client_id;
4718 SilcChannelEntry channel;
4719 SilcChannelClientEntry chl;
4721 SilcUInt32 tmp_len, target_idp_len;
4722 unsigned char *tmp, *comment, *target_idp;
4724 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4726 /* Get Channel ID */
4727 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4729 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4730 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4733 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4735 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4736 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4740 /* Get channel entry */
4741 channel = silc_idlist_find_channel_by_id(server->local_list,
4744 channel = silc_idlist_find_channel_by_id(server->local_list,
4747 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4748 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4754 /* Check whether sender is on the channel */
4755 if (!silc_server_client_on_channel(client, channel, &chl)) {
4756 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4757 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4761 /* Check that the kicker is channel operator or channel founder */
4762 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
4763 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4764 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4765 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
4769 /* Get target Client ID */
4770 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4772 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4773 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4776 client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
4778 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4779 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4783 /* Get target client's entry */
4784 target_client = silc_idlist_find_client_by_id(server->local_list,
4785 client_id, TRUE, NULL);
4786 if (!target_client) {
4787 target_client = silc_idlist_find_client_by_id(server->global_list,
4788 client_id, TRUE, NULL);
4791 /* Check whether target client is on the channel */
4792 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4793 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4794 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL,
4799 /* Check that the target client is not channel founder. Channel founder
4800 cannot be kicked from the channel. */
4801 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4802 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4803 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
4810 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4814 /* Send command reply to sender */
4815 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4818 /* Send KICKED notify to local clients on the channel */
4819 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4820 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4821 SILC_NOTIFY_TYPE_KICKED, 3,
4822 target_idp, target_idp_len,
4823 comment, comment ? strlen(comment) : 0,
4824 idp->data, idp->len);
4825 silc_buffer_free(idp);
4827 /* Send KICKED notify to primary route */
4828 silc_server_send_notify_kicked(server, SILC_PRIMARY_ROUTE(server),
4829 SILC_BROADCAST(server), channel,
4830 target_client->id, client->id, comment);
4832 /* Remove the client from the channel. If the channel does not exist
4833 after removing the client then the client kicked itself off the channel
4834 and we don't have to send anything after that. */
4835 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4836 target_client, FALSE))
4839 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4840 /* Re-generate channel key */
4841 if (!silc_server_create_channel_key(server, channel, 0))
4844 /* Send the channel key to the channel. The key of course is not sent
4845 to the client who was kicked off the channel. */
4846 silc_server_send_channel_key(server, target_client->connection, channel,
4847 server->server_type == SILC_ROUTER ?
4848 FALSE : !server->standalone);
4852 silc_server_command_free(cmd);
4855 /* Server side of OPER command. Client uses this comand to obtain server
4856 operator privileges to this server/router. */
4858 SILC_SERVER_CMD_FUNC(oper)
4860 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4861 SilcServer server = cmd->server;
4862 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4863 unsigned char *username, *auth;
4865 SilcServerConfigAdmin *admin;
4866 SilcIDListData idata = (SilcIDListData)client;
4867 bool result = FALSE;
4868 SilcPublicKey cached_key;
4870 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4872 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4875 /* Get the username */
4876 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4878 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4879 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4884 /* Get the admin configuration */
4885 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4886 username, client->nickname);
4888 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4889 username, client->nickname);
4891 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4892 SILC_STATUS_ERR_AUTH_FAILED,
4898 /* Get the authentication payload */
4899 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4901 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4902 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4907 /* Verify the authentication data. If both passphrase and public key
4908 is set then try both of them. */
4909 if (admin->passphrase)
4910 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4911 admin->passphrase, admin->passphrase_len,
4912 idata->hash, client->id, SILC_ID_CLIENT);
4913 if (!result && admin->publickeys) {
4914 cached_key = silc_server_get_public_key(server, admin->publickeys);
4917 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4918 cached_key, 0, idata->hash,
4919 client->id, SILC_ID_CLIENT);
4922 /* Authentication failed */
4923 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4924 SILC_STATUS_ERR_AUTH_FAILED,
4929 /* Client is now server operator */
4930 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4932 /* Update statistics */
4933 if (SILC_IS_LOCAL(client))
4934 server->stat.my_server_ops++;
4935 if (server->server_type == SILC_ROUTER)
4936 server->stat.server_ops++;
4938 /* Send UMODE change to primary router */
4939 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
4940 SILC_BROADCAST(server), client->id,
4943 /* Check if anyone is watching this nickname */
4944 if (server->server_type == SILC_ROUTER)
4945 silc_server_check_watcher_list(server, client, NULL,
4946 SILC_NOTIFY_TYPE_UMODE_CHANGE);
4948 /* Send reply to the sender */
4949 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4953 silc_server_command_free(cmd);
4956 SILC_TASK_CALLBACK(silc_server_command_detach_cb)
4958 QuitInternal q = (QuitInternal)context;
4959 SilcClientID *client_id = (SilcClientID *)q->sock;
4960 SilcClientEntry client;
4961 SilcSocketConnection sock;
4963 client = silc_idlist_find_client_by_id(q->server->local_list, client_id,
4965 if (client && client->connection) {
4966 sock = client->connection;
4968 /* If there is pending outgoing data for the client then purge it
4969 to the network before closing connection. */
4970 silc_server_packet_queue_purge(q->server, sock);
4972 /* Close the connection on our side */
4973 client->router = NULL;
4974 client->connection = NULL;
4975 sock->user_data = NULL;
4976 silc_server_close_connection(q->server, sock);
4979 silc_free(client_id);
4983 SILC_TASK_CALLBACK(silc_server_command_detach_timeout)
4985 QuitInternal q = (QuitInternal)context;
4986 SilcClientID *client_id = (SilcClientID *)q->sock;
4987 SilcClientEntry client;
4989 client = silc_idlist_find_client_by_id(q->server->local_list, client_id,
4991 if (client && client->mode & SILC_UMODE_DETACHED) {
4992 SILC_LOG_DEBUG(("Detach timeout"));
4993 silc_server_free_client_data(q->server, NULL, client, TRUE,
4997 silc_free(client_id);
5001 /* Server side of DETACH command. Detached the client from the network
5002 by closing the connection but preserving the session. */
5004 SILC_SERVER_CMD_FUNC(detach)
5006 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5007 SilcServer server = cmd->server;
5008 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5011 if (server->config->detach_disabled) {
5012 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
5013 SILC_STATUS_ERR_UNKNOWN_COMMAND, 0);
5017 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5020 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
5022 /* Remove operator privileges, since the client may resume in some
5023 other server which to it does not have operator privileges. */
5024 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
5025 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
5027 /* Send the user mode notify to notify that client is detached */
5028 client->mode |= SILC_UMODE_DETACHED;
5029 client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
5030 client->last_command = 0;
5031 client->fast_command = 0;
5032 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
5033 SILC_BROADCAST(server), client->id,
5035 server->stat.my_detached++;
5037 /* Check if anyone is watching this nickname */
5038 if (server->server_type == SILC_ROUTER)
5039 silc_server_check_watcher_list(server, client, NULL,
5040 SILC_NOTIFY_TYPE_UMODE_CHANGE);
5042 q = silc_calloc(1, sizeof(*q));
5044 q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
5045 silc_schedule_task_add(server->schedule, 0, silc_server_command_detach_cb,
5046 q, 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
5048 if (server->config->detach_timeout) {
5049 q = silc_calloc(1, sizeof(*q));
5051 q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
5052 silc_schedule_task_add(server->schedule, 0,
5053 silc_server_command_detach_timeout,
5054 q, server->config->detach_timeout * 60,
5055 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
5058 /* Send reply to the sender */
5059 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
5063 silc_server_command_free(cmd);
5066 /* Server side of WATCH command. */
5068 SILC_SERVER_CMD_FUNC(watch)
5070 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5071 SilcServer server = cmd->server;
5072 char *add_nick, *del_nick;
5073 SilcUInt32 add_nick_len, del_nick_len, tmp_len;
5075 unsigned char hash[16], *tmp;
5076 SilcClientEntry client;
5077 SilcClientID *client_id = NULL;
5079 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WATCH, cmd, 1, 3);
5081 if (server->server_type == SILC_SERVER && !server->standalone) {
5082 if (!cmd->pending) {
5083 /* Send the command to router */
5085 SilcUInt16 old_ident;
5087 old_ident = silc_command_get_ident(cmd->payload);
5088 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5089 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5091 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5092 SILC_PACKET_COMMAND, cmd->packet->flags,
5093 tmpbuf->data, tmpbuf->len, TRUE);
5095 /* Reprocess this packet after received reply from router */
5096 silc_server_command_pending(server, SILC_COMMAND_WATCH,
5097 silc_command_get_ident(cmd->payload),
5098 silc_server_command_watch,
5099 silc_server_command_dup(cmd));
5100 cmd->pending = TRUE;
5101 silc_command_set_ident(cmd->payload, old_ident);
5102 silc_buffer_free(tmpbuf);
5103 } else if (context2) {
5104 /* Received reply from router, just send same data to the client. */
5105 SilcServerCommandReplyContext reply = context2;
5107 silc_command_get_status(reply->payload, &status, NULL);
5108 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, status,
5115 /* We are router and keep the watch list for local cell */
5117 /* Get the client ID */
5118 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5120 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5121 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5125 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
5127 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5128 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5133 /* Get the client entry which must be in local list */
5134 client = silc_idlist_find_client_by_id(server->local_list,
5135 client_id, TRUE, NULL);
5137 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5138 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5144 add_nick = silc_argument_get_arg_type(cmd->args, 2, &add_nick_len);
5145 del_nick = silc_argument_get_arg_type(cmd->args, 3, &del_nick_len);
5146 if (!add_nick && !del_nick) {
5147 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5148 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5153 if (add_nick && add_nick_len > 128)
5154 add_nick[128] = '\0';
5155 if (del_nick && del_nick_len > 128)
5156 del_nick[128] = '\0';
5158 memset(nick, 0, sizeof(nick));
5160 /* Add new nickname to be watched in our cell */
5162 if (silc_server_name_bad_chars(add_nick, strlen(add_nick)) == TRUE) {
5163 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5164 SILC_STATUS_ERR_BAD_NICKNAME, 0);
5168 /* Hash the nick, we have the hash saved, not nicks because we can
5169 do one to one mapping to the nick from Client ID hash this way. */
5170 silc_to_lower(add_nick, nick, sizeof(nick) - 1);
5171 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
5173 /* Check whether this client is already watching this nickname */
5174 if (silc_hash_table_find_by_context(server->watcher_list, hash,
5176 /* Nickname is alredy being watched for this client */
5177 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5178 SILC_STATUS_ERR_NICKNAME_IN_USE,
5183 /* Get the nickname from the watcher list and use the same key in
5184 new entries as well. If key doesn't exist then create it. */
5185 if (!silc_hash_table_find(server->watcher_list, hash, (void **)&tmp, NULL))
5186 tmp = silc_memdup(hash, CLIENTID_HASH_LEN);
5188 /* Add the client to the watcher list with the specified nickname hash. */
5189 silc_hash_table_add(server->watcher_list, tmp, client);
5192 /* Delete nickname from watch list */
5194 if (silc_server_name_bad_chars(del_nick, strlen(del_nick)) == TRUE) {
5195 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5196 SILC_STATUS_ERR_BAD_NICKNAME, 0);
5200 /* Hash the nick, we have the hash saved, not nicks because we can
5201 do one to one mapping to the nick from Client ID hash this way. */
5202 silc_to_lower(del_nick, nick, sizeof(nick) - 1);
5203 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
5205 /* Check that this client is watching for this nickname */
5206 if (!silc_hash_table_find_by_context(server->watcher_list, hash,
5207 client, (void **)&tmp)) {
5208 /* Nickname is alredy being watched for this client */
5209 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5210 SILC_STATUS_ERR_NO_SUCH_NICK, 0);
5214 /* Delete the nickname from the watcher list. */
5215 silc_hash_table_del_by_context(server->watcher_list, hash, client);
5217 /* Now check whether there still exists entries with this key, if not
5218 then free the key to not leak memory. */
5219 if (!silc_hash_table_find(server->watcher_list, hash, NULL, NULL))
5223 /* Distribute the watch list to backup routers too */
5224 if (server->backup) {
5226 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5227 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5228 silc_server_backup_send(server, NULL, SILC_PACKET_COMMAND,
5229 cmd->packet->flags, tmpbuf->data, tmpbuf->len,
5231 silc_buffer_free(tmpbuf);
5234 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5238 silc_free(client_id);
5239 silc_server_command_free(cmd);
5242 /* Server side of SILCOPER command. Client uses this comand to obtain router
5243 operator privileges to this router. */
5245 SILC_SERVER_CMD_FUNC(silcoper)
5247 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5248 SilcServer server = cmd->server;
5249 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5250 unsigned char *username, *auth;
5252 SilcServerConfigAdmin *admin;
5253 SilcIDListData idata = (SilcIDListData)client;
5254 bool result = FALSE;
5255 SilcPublicKey cached_key;
5257 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
5259 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5262 if (server->server_type != SILC_ROUTER) {
5263 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5264 SILC_STATUS_ERR_AUTH_FAILED, 0);
5268 /* Get the username */
5269 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5271 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5272 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5277 /* Get the admin configuration */
5278 admin = silc_server_config_find_admin(server, cmd->sock->ip,
5279 username, client->nickname);
5281 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
5282 username, client->nickname);
5284 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5285 SILC_STATUS_ERR_AUTH_FAILED, 0);
5290 /* Get the authentication payload */
5291 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5293 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5294 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5299 /* Verify the authentication data. If both passphrase and public key
5300 is set then try both of them. */
5301 if (admin->passphrase)
5302 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
5303 admin->passphrase, admin->passphrase_len,
5304 idata->hash, client->id, SILC_ID_CLIENT);
5305 if (!result && admin->publickeys) {
5306 cached_key = silc_server_get_public_key(server, admin->publickeys);
5309 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
5310 cached_key, 0, idata->hash,
5311 client->id, SILC_ID_CLIENT);
5314 /* Authentication failed */
5315 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
5316 SILC_STATUS_ERR_AUTH_FAILED, 0);
5320 /* Client is now router operator */
5321 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
5323 /* Update statistics */
5324 if (SILC_IS_LOCAL(client))
5325 server->stat.my_router_ops++;
5326 if (server->server_type == SILC_ROUTER)
5327 server->stat.router_ops++;
5329 /* Send UMODE change to primary router */
5330 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
5331 SILC_BROADCAST(server), client->id,
5334 /* Check if anyone is watching this nickname */
5335 if (server->server_type == SILC_ROUTER)
5336 silc_server_check_watcher_list(server, client, NULL,
5337 SILC_NOTIFY_TYPE_UMODE_CHANGE);
5339 /* Send reply to the sender */
5340 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5344 silc_server_command_free(cmd);
5347 /* Server side of command BAN. This is used to manage the ban list of the
5348 channel. To add clients and remove clients from the ban list. */
5350 SILC_SERVER_CMD_FUNC(ban)
5352 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5353 SilcServer server = cmd->server;
5354 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5356 SilcChannelEntry channel;
5357 SilcChannelClientEntry chl;
5358 SilcChannelID *channel_id = NULL;
5359 unsigned char *id, *add, *del;
5360 SilcUInt32 id_len, tmp_len;
5361 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5363 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5366 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
5368 /* Get Channel ID */
5369 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
5371 channel_id = silc_id_payload_parse_id(id, id_len, NULL);
5373 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5374 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5379 /* Get channel entry. The server must know about the channel since the
5380 client is expected to be on the channel. */
5381 channel = silc_idlist_find_channel_by_id(server->local_list,
5384 channel = silc_idlist_find_channel_by_id(server->global_list,
5387 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5388 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5394 /* Check whether this client is on the channel */
5395 if (!silc_server_client_on_channel(client, channel, &chl)) {
5396 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5397 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5401 /* The client must be at least channel operator. */
5402 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
5403 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5404 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
5408 /* Get the new ban and add it to the ban list */
5409 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5411 if (!channel->ban_list)
5412 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
5414 channel->ban_list = silc_realloc(channel->ban_list,
5415 sizeof(*channel->ban_list) *
5417 strlen(channel->ban_list) + 2));
5418 if (add[tmp_len - 1] == ',')
5419 add[tmp_len - 1] = '\0';
5421 strncat(channel->ban_list, add, tmp_len);
5422 strncat(channel->ban_list, ",", 1);
5425 /* Get the ban to be removed and remove it from the list */
5426 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
5427 if (del && channel->ban_list) {
5428 char *start, *end, *n;
5430 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
5431 silc_free(channel->ban_list);
5432 channel->ban_list = NULL;
5434 start = strstr(channel->ban_list, del);
5435 if (start && strlen(start) >= tmp_len) {
5436 end = start + tmp_len;
5437 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
5438 strncat(n, channel->ban_list, start - channel->ban_list);
5439 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
5441 silc_free(channel->ban_list);
5442 channel->ban_list = n;
5447 /* Send the BAN notify type to our primary router. */
5449 silc_server_send_notify_ban(server, SILC_PRIMARY_ROUTE(server),
5450 SILC_BROADCAST(server), channel, add, del);
5452 /* Send the reply back to the client */
5454 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
5455 SILC_STATUS_OK, 0, ident, 2,
5457 3, channel->ban_list,
5459 strlen(channel->ban_list) -1 : 0);
5460 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5461 packet->data, packet->len, FALSE);
5463 silc_buffer_free(packet);
5466 silc_free(channel_id);
5467 silc_server_command_free(cmd);
5470 /* Server side command of LEAVE. Removes client from a channel. */
5472 SILC_SERVER_CMD_FUNC(leave)
5474 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5475 SilcServer server = cmd->server;
5476 SilcSocketConnection sock = cmd->sock;
5477 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
5478 SilcChannelID *id = NULL;
5479 SilcChannelEntry channel;
5483 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
5485 /* Get Channel ID */
5486 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
5488 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5489 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5492 id = silc_id_payload_parse_id(tmp, len, NULL);
5494 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5495 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5499 /* Get channel entry */
5500 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5502 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5504 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5505 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5511 /* Check whether this client is on the channel */
5512 if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
5513 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5514 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5518 /* Notify routers that they should remove this client from their list
5519 of clients on the channel. Send LEAVE notify type. */
5520 silc_server_send_notify_leave(server, SILC_PRIMARY_ROUTE(server),
5521 SILC_BROADCAST(server), channel, id_entry->id);
5523 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
5524 SILC_STATUS_OK, 0, 2, tmp, len);
5526 /* Remove client from channel */
5527 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5529 /* If the channel does not exist anymore we won't send anything */
5532 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5533 /* Re-generate channel key */
5534 if (!silc_server_create_channel_key(server, channel, 0))
5537 /* Send the channel key */
5538 silc_server_send_channel_key(server, NULL, channel,
5539 server->server_type == SILC_ROUTER ?
5540 FALSE : !server->standalone);
5545 silc_server_command_free(cmd);
5548 /* Server side of command USERS. Resolves clients and their USERS currently
5549 joined on the requested channel. The list of Client ID's and their modes
5550 on the channel is sent back. */
5552 SILC_SERVER_CMD_FUNC(users)
5554 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5555 SilcServer server = cmd->server;
5556 SilcChannelEntry channel;
5557 SilcChannelID *id = NULL;
5558 SilcBuffer packet, idp;
5559 unsigned char *channel_id;
5560 SilcUInt32 channel_id_len;
5561 SilcBuffer client_id_list;
5562 SilcBuffer client_mode_list;
5563 unsigned char lc[4];
5564 SilcUInt32 list_count = 0;
5565 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5568 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5570 /* Get Channel ID */
5571 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5573 /* Get channel name */
5574 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5576 if (!channel_id && !channel_name) {
5577 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5578 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5583 id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
5585 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5586 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5591 /* If we are server and we don't know about this channel we will send
5592 the command to our router. If we know about the channel then we also
5593 have the list of users already. */
5595 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5597 channel = silc_idlist_find_channel_by_name(server->local_list,
5598 channel_name, NULL);
5600 if (!channel || (!server->standalone && (channel->disabled ||
5601 !channel->users_resolved))) {
5602 if (server->server_type != SILC_ROUTER && !server->standalone &&
5606 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5607 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5609 /* Send USERS command */
5610 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5611 SILC_PACKET_COMMAND, cmd->packet->flags,
5612 tmpbuf->data, tmpbuf->len, TRUE);
5614 /* Reprocess this packet after received reply */
5615 silc_server_command_pending(server, SILC_COMMAND_USERS,
5616 silc_command_get_ident(cmd->payload),
5617 silc_server_command_users,
5618 silc_server_command_dup(cmd));
5619 cmd->pending = TRUE;
5620 silc_command_set_ident(cmd->payload, ident);
5621 silc_buffer_free(tmpbuf);
5626 /* Check the global list as well. */
5628 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5630 channel = silc_idlist_find_channel_by_name(server->global_list,
5631 channel_name, NULL);
5633 /* Channel really does not exist */
5634 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5635 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5641 /* If the channel is private or secret do not send anything, unless the
5642 user requesting this command is on the channel or is server */
5643 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5644 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5645 && !silc_server_client_on_channel(cmd->sock->user_data, channel,
5647 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5648 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5654 /* Get the users list */
5655 if (!silc_server_get_users_on_channel(server, channel, &client_id_list,
5656 &client_mode_list, &list_count)) {
5658 client_id_list = NULL;
5659 client_mode_list = NULL;
5663 SILC_PUT32_MSB(list_count, lc);
5666 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5667 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5668 SILC_STATUS_OK, 0, ident, 4,
5669 2, idp->data, idp->len,
5672 client_id_list->data : NULL,
5674 client_id_list->len : 0,
5675 5, client_mode_list ?
5676 client_mode_list->data : NULL,
5678 client_mode_list->len : 0);
5679 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5680 packet->data, packet->len, FALSE);
5682 silc_buffer_free(idp);
5683 silc_buffer_free(packet);
5685 silc_buffer_free(client_id_list);
5686 if (client_mode_list)
5687 silc_buffer_free(client_mode_list);
5691 silc_server_command_free(cmd);
5694 /* Server side of command GETKEY. This fetches the client's public key
5695 from the server where to the client is connected. */
5697 SILC_SERVER_CMD_FUNC(getkey)
5699 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5700 SilcServer server = cmd->server;
5702 SilcClientEntry client;
5703 SilcServerEntry server_entry;
5704 SilcClientID *client_id = NULL;
5705 SilcServerID *server_id = NULL;
5706 SilcIDPayload idp = NULL;
5707 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5708 unsigned char *tmp, *pkdata;
5709 SilcUInt32 tmp_len, pklen;
5710 SilcBuffer pk = NULL;
5712 SilcPublicKey public_key;
5714 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5716 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5717 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5721 idp = silc_id_payload_parse(tmp, tmp_len);
5723 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5724 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5729 id_type = silc_id_payload_get_type(idp);
5730 if (id_type == SILC_ID_CLIENT) {
5731 client_id = silc_id_payload_get_id(idp);
5733 /* If the client is not found from local list there is no chance it
5734 would be locally connected client so send the command further. */
5735 client = silc_idlist_find_client_by_id(server->local_list,
5736 client_id, TRUE, NULL);
5738 client = silc_idlist_find_client_by_id(server->global_list,
5739 client_id, TRUE, NULL);
5741 if ((!client && !cmd->pending && !server->standalone) ||
5742 (client && !client->connection && !cmd->pending &&
5743 !(client->mode & SILC_UMODE_DETACHED)) ||
5744 (client && !client->data.public_key && !cmd->pending)) {
5746 SilcUInt16 old_ident;
5747 SilcSocketConnection dest_sock;
5749 dest_sock = silc_server_get_client_route(server, NULL, 0,
5750 client_id, NULL, NULL);
5754 old_ident = silc_command_get_ident(cmd->payload);
5755 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5756 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5758 silc_server_packet_send(server, dest_sock,
5759 SILC_PACKET_COMMAND, cmd->packet->flags,
5760 tmpbuf->data, tmpbuf->len, TRUE);
5762 /* Reprocess this packet after received reply from router */
5763 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5764 silc_command_get_ident(cmd->payload),
5765 silc_server_command_getkey,
5766 silc_server_command_dup(cmd));
5767 cmd->pending = TRUE;
5768 silc_command_set_ident(cmd->payload, old_ident);
5769 silc_buffer_free(tmpbuf);
5774 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5775 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5780 /* The client is locally connected, just get the public key and
5781 send it back. If they key does not exist then do not send it,
5782 send just OK reply */
5783 public_key = client->data.public_key;
5788 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5789 pk = silc_buffer_alloc(4 + tmp_len);
5790 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5791 silc_buffer_format(pk,
5792 SILC_STR_UI_SHORT(tmp_len),
5793 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5794 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5800 } else if (id_type == SILC_ID_SERVER) {
5801 server_id = silc_id_payload_get_id(idp);
5803 /* If the server is not found from local list there is no chance it
5804 would be locally connected server so send the command further. */
5805 server_entry = silc_idlist_find_server_by_id(server->local_list,
5806 server_id, TRUE, NULL);
5808 server_entry = silc_idlist_find_server_by_id(server->global_list,
5809 server_id, TRUE, NULL);
5811 if (server_entry != server->id_entry &&
5812 ((!server_entry && !cmd->pending && !server->standalone) ||
5813 (server_entry && !server_entry->connection && !cmd->pending &&
5814 !server->standalone) ||
5815 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5816 !server->standalone))) {
5818 SilcUInt16 old_ident;
5820 old_ident = silc_command_get_ident(cmd->payload);
5821 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5822 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5824 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5825 SILC_PACKET_COMMAND, cmd->packet->flags,
5826 tmpbuf->data, tmpbuf->len, TRUE);
5828 /* Reprocess this packet after received reply from router */
5829 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5830 silc_command_get_ident(cmd->payload),
5831 silc_server_command_getkey,
5832 silc_server_command_dup(cmd));
5833 cmd->pending = TRUE;
5834 silc_command_set_ident(cmd->payload, old_ident);
5835 silc_buffer_free(tmpbuf);
5839 if (!server_entry) {
5840 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5841 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
5846 /* If they key does not exist then do not send it, send just OK reply */
5847 public_key = (!server_entry->data.public_key ?
5848 (server_entry == server->id_entry ? server->public_key :
5849 NULL) : server_entry->data.public_key);
5854 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5855 pk = silc_buffer_alloc(4 + tmp_len);
5856 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5857 silc_buffer_format(pk,
5858 SILC_STR_UI_SHORT(tmp_len),
5859 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5860 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5870 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5871 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5872 SILC_STATUS_OK, 0, ident,
5876 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5877 packet->data, packet->len, FALSE);
5878 silc_buffer_free(packet);
5881 silc_buffer_free(pk);
5885 silc_id_payload_free(idp);
5886 silc_free(client_id);
5887 silc_free(server_id);
5888 silc_server_command_free(cmd);
5892 /* Private range commands, specific to this implementation */
5894 /* Server side command of CONNECT. Connects us to the specified remote
5895 server or router. */
5897 SILC_SERVER_CMD_FUNC(connect)
5899 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5900 SilcServer server = cmd->server;
5901 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5902 unsigned char *tmp, *host;
5904 SilcUInt32 port = SILC_PORT;
5906 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
5908 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5911 /* Check whether client has the permissions. */
5912 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5913 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5914 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5915 SILC_STATUS_ERR_NO_SERVER_PRIV, 0);
5919 if (server->server_type == SILC_ROUTER &&
5920 client->mode & SILC_UMODE_SERVER_OPERATOR) {
5921 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5922 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
5926 /* Get the remote server */
5927 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5929 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5930 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5936 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5938 SILC_GET32_MSB(port, tmp);
5940 /* Create the connection. It is done with timeout and is async. */
5941 silc_server_create_connection(server, host, port);
5943 /* Send reply to the sender */
5944 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5948 silc_server_command_free(cmd);
5951 /* Server side command of CLOSE. Closes connection to a specified server. */
5953 SILC_SERVER_CMD_FUNC(close)
5955 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5956 SilcServer server = cmd->server;
5957 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5958 SilcServerEntry server_entry;
5959 SilcSocketConnection sock;
5962 unsigned char *name;
5963 SilcUInt32 port = SILC_PORT;
5965 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
5967 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5970 /* Check whether client has the permissions. */
5971 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5972 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5973 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5974 SILC_STATUS_ERR_NO_SERVER_PRIV,
5979 /* Get the remote server */
5980 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5982 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5983 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5989 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5991 SILC_GET32_MSB(port, tmp);
5993 server_entry = silc_idlist_find_server_by_conn(server->local_list,
5994 name, port, FALSE, NULL);
5996 server_entry = silc_idlist_find_server_by_conn(server->global_list,
5997 name, port, FALSE, NULL);
5998 if (!server_entry) {
5999 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
6000 SILC_STATUS_ERR_NO_SERVER_ID, 0);
6004 /* Send reply to the sender */
6005 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
6008 /* Close the connection to the server */
6009 sock = (SilcSocketConnection)server_entry->connection;
6011 /* If we shutdown primary router connection manually then don't trigger
6012 any reconnect or backup router connections, by setting the router
6014 if (server->router == server_entry) {
6015 server->id_entry->router = NULL;
6016 server->router = NULL;
6017 server->standalone = TRUE;
6019 silc_server_free_sock_user_data(server, sock, NULL);
6020 silc_server_close_connection(server, sock);
6023 silc_server_command_free(cmd);
6026 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
6027 active connections. */
6029 SILC_SERVER_CMD_FUNC(shutdown)
6031 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
6032 SilcServer server = cmd->server;
6033 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
6035 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
6037 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
6040 /* Check whether client has the permission. */
6041 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
6042 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
6043 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
6044 SILC_STATUS_ERR_NO_SERVER_PRIV,
6049 /* Send reply to the sender */
6050 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
6053 /* Then, gracefully, or not, bring the server down. */
6054 silc_server_stop(server);
6058 silc_server_command_free(cmd);