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->reply_cmd == SILC_COMMAND_NONE &&
371 && r->ident == ident) {
372 silc_dlist_del(server->pending_commands, r);
378 /* Checks for pending commands and marks callbacks to be called from
379 the command reply function. Returns TRUE if there were pending command. */
381 SilcServerCommandPendingCallbacks
382 silc_server_command_pending_check(SilcServer server,
383 SilcServerCommandReplyContext ctx,
386 SilcUInt32 *callbacks_count)
388 SilcServerCommandPending *r;
389 SilcServerCommandPendingCallbacks callbacks = NULL;
392 silc_dlist_start(server->pending_commands);
393 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
394 if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE)
395 && r->ident == ident) {
396 callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
397 callbacks[i].context = r->context;
398 callbacks[i].callback = r->callback;
399 r->reply_check = TRUE;
405 *callbacks_count = i;
409 /* Sends simple status message as command reply packet */
412 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
419 SILC_LOG_DEBUG(("Sending command status %d", status));
422 silc_command_reply_payload_encode_va(command, status, error,
423 silc_command_get_ident(cmd->payload),
425 silc_server_packet_send(cmd->server, cmd->sock,
426 SILC_PACKET_COMMAND_REPLY, 0,
427 buffer->data, buffer->len, FALSE);
428 silc_buffer_free(buffer);
431 /* Sends command status reply with one extra argument. The argument
432 type must be sent as argument. */
435 silc_server_command_send_status_data(SilcServerCommandContext cmd,
440 const unsigned char *arg,
445 SILC_LOG_DEBUG(("Sending command status %d", status));
448 silc_command_reply_payload_encode_va(command, status, 0,
449 silc_command_get_ident(cmd->payload),
450 1, arg_type, arg, arg_len);
451 silc_server_packet_send(cmd->server, cmd->sock,
452 SILC_PACKET_COMMAND_REPLY, 0,
453 buffer->data, buffer->len, FALSE);
454 silc_buffer_free(buffer);
457 /* This function can be called to check whether in the command reply
458 an error occurred. This function has no effect if this is called
459 when the command function was not called as pending command callback.
460 This returns TRUE if error had occurred. */
463 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
464 SilcServerCommandReplyContext cmdr,
467 if (!cmd->pending || !cmdr)
470 if (!silc_command_get_status(cmdr->payload, NULL, NULL)) {
473 /* Send the same command reply payload */
474 silc_command_set_ident(cmdr->payload,
475 silc_command_get_ident(cmd->payload));
476 buffer = silc_command_payload_encode_payload(cmdr->payload);
477 silc_server_packet_send(cmd->server, cmd->sock,
478 SILC_PACKET_COMMAND_REPLY, 0,
479 buffer->data, buffer->len, FALSE);
480 silc_buffer_free(buffer);
487 /******************************************************************************
491 ******************************************************************************/
500 #define ADD_ERROR(errptr, errptr_count, _id, _id_type, _index, _status) \
502 errptr = silc_realloc(errptr, sizeof(*errptr) * (errptr_count + 1)); \
505 errptr[errptr_count].id = _id; \
506 errptr[errptr_count].id_type = _id_type; \
507 errptr[errptr_count].index = _index; \
508 errptr[errptr_count].error = _status; \
513 silc_server_command_whois_parse(SilcServerCommandContext cmd,
514 SilcClientID ***client_id,
515 SilcUInt32 *client_id_count,
519 ResolveError *error_client,
520 SilcUInt32 *error_client_count)
524 SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
528 /* If client ID is in the command it must be used instead of nickname */
529 tmp = silc_argument_get_arg_type(cmd->args, 4, &len);
531 /* No ID, get the nickname@server string and parse it. */
532 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
534 silc_parse_userfqdn(tmp, nickname, server_name);
536 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
537 SILC_STATUS_ERR_BAD_NICKNAME, 0);
541 /* Command includes ID, we must use that. Take all ID's from the
543 for (k = 0, i = 0; i < argc; i++) {
544 tmp = silc_argument_get_arg_type(cmd->args, i + 4, &len);
547 id = silc_id_payload_parse_id(tmp, len, NULL);
549 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
550 (*client_id_count + 1));
551 (*client_id)[k] = id;
552 (*client_id_count)++;
555 ADD_ERROR((*error_client), (*error_client_count), NULL, 0, i + 4,
556 SILC_STATUS_ERR_BAD_CLIENT_ID);
561 /* Get the max count of reply messages allowed */
562 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
564 SILC_GET32_MSB(*count, tmp);
571 /* Resolve context used by both WHOIS and IDENTIFY commands */
573 SilcServerEntry router;
575 unsigned char **res_argv;
576 SilcUInt32 *res_argv_lens;
577 SilcUInt32 *res_argv_types;
579 } *SilcServerResolveContext;
582 silc_server_command_whois_check(SilcServerCommandContext cmd,
583 SilcClientEntry *clients,
584 SilcUInt32 clients_count)
586 SilcServer server = cmd->server;
587 SilcClientEntry entry;
588 SilcServerResolveContext resolve = NULL, r = NULL;
589 SilcUInt32 resolve_count = 0;
593 SILC_LOG_DEBUG(("Start"));
595 for (i = 0; i < clients_count; i++) {
600 if ((entry->nickname && entry->username && entry->userinfo) ||
601 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
605 /* If we are normal server, and we've not resolved this client from
606 router and it is global client, we'll check whether it is on some
607 channel. If not then we cannot be sure about its validity, and
608 we'll resolve it from router. */
609 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
610 entry->connection || silc_hash_table_count(entry->channels))
614 /* We need to resolve this entry since it is not complete */
616 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
617 /* The entry is being resolved (and we are not the resolver) so attach
618 to the command reply and we're done with this one. */
619 silc_server_command_pending(server, SILC_COMMAND_NONE,
620 entry->resolve_cmd_ident,
621 silc_server_command_whois,
622 silc_server_command_dup(cmd));
625 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
626 /* We've resolved this and it still is not ready. We'll return
627 and are that this will be handled again after it is resolved. */
628 for (i = 0; i < resolve_count; i++) {
629 for (k = 0; k < r->res_argc; k++)
630 silc_free(r->res_argv[k]);
631 silc_free(r->res_argv);
632 silc_free(r->res_argv_lens);
633 silc_free(r->res_argv_types);
638 /* We'll resolve this client */
642 for (k = 0; k < resolve_count; k++) {
643 if (resolve[k].router == entry->router) {
650 resolve = silc_realloc(resolve, sizeof(*resolve) *
651 (resolve_count + 1));
652 r = &resolve[resolve_count];
653 memset(r, 0, sizeof(*r));
654 r->router = entry->router;
655 r->ident = ++server->cmd_ident;
659 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
661 r->res_argv_lens = silc_realloc(r->res_argv_lens,
662 sizeof(*r->res_argv_lens) *
664 r->res_argv_types = silc_realloc(r->res_argv_types,
665 sizeof(*r->res_argv_types) *
667 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
668 r->res_argv[r->res_argc] = silc_calloc(idp->len,
669 sizeof(**r->res_argv));
670 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
671 r->res_argv_lens[r->res_argc] = idp->len;
672 r->res_argv_types[r->res_argc] = r->res_argc + 4;
674 silc_buffer_free(idp);
676 entry->resolve_cmd_ident = r->ident;
677 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
678 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
683 /* Do the resolving */
684 for (i = 0; i < resolve_count; i++) {
689 /* Send WHOIS request. We send WHOIS since we're doing the requesting
690 now anyway so make it a good one. */
691 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
692 r->res_argc, r->res_argv,
696 silc_server_packet_send(server, r->router->connection,
697 SILC_PACKET_COMMAND, cmd->packet->flags,
698 res_cmd->data, res_cmd->len, FALSE);
700 /* Reprocess this packet after received reply */
701 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
703 silc_server_command_whois,
704 silc_server_command_dup(cmd));
707 silc_buffer_free(res_cmd);
708 for (k = 0; k < r->res_argc; k++)
709 silc_free(r->res_argv[k]);
710 silc_free(r->res_argv);
711 silc_free(r->res_argv_lens);
712 silc_free(r->res_argv_types);
721 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
722 SilcClientEntry *clients,
723 SilcUInt32 clients_count,
725 SilcUInt32 errors_count,
726 int count, const char *nickname,
727 SilcClientID **client_ids)
729 SilcServer server = cmd->server;
731 int i, k, valid_count = clients_count;
733 SilcBuffer packet, idp, channels, umode_list = NULL;
734 SilcClientEntry entry;
736 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
737 char nh[256], uh[256];
738 unsigned char idle[4], mode[4];
739 unsigned char *fingerprint;
740 SilcSocketConnection hsock;
743 /* Process only valid clients and ignore those that are not registered.
744 This is checked with nickname only because when resolved client IDs
745 we check that they are registered earlier. */
747 for (i = 0; i < clients_count; i++)
748 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
754 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
755 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
756 3, nickname, strlen(nickname));
761 /* Start processing found clients. */
762 status = SILC_STATUS_OK;
764 status = SILC_STATUS_LIST_START;
766 for (i = 0, k = 0; i < clients_count; i++) {
772 status = SILC_STATUS_LIST_ITEM;
773 if (valid_count > 1 && k == valid_count - 1 && !errors_count)
774 status = SILC_STATUS_LIST_END;
775 if (count && k - 1 == count)
776 status = SILC_STATUS_LIST_END;
778 /* Send WHOIS reply */
779 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
780 tmp = silc_argument_get_first_arg(cmd->args, NULL);
782 memset(uh, 0, sizeof(uh));
783 memset(nh, 0, sizeof(nh));
784 memset(idle, 0, sizeof(idle));
786 strncat(nh, entry->nickname, strlen(entry->nickname));
787 if (!strchr(entry->nickname, '@')) {
789 if (entry->servername) {
790 strncat(nh, entry->servername, strlen(entry->servername));
792 len = entry->router ? strlen(entry->router->server_name) :
793 strlen(server->server_name);
794 strncat(nh, entry->router ? entry->router->server_name :
795 server->server_name, len);
799 strncat(uh, entry->username, strlen(entry->username));
800 if (!strchr(entry->username, '@') && entry->connection) {
802 hsock = (SilcSocketConnection)entry->connection;
803 len = strlen(hsock->hostname);
804 strncat(uh, hsock->hostname, len);
807 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
808 channels = silc_server_get_client_channel_list(server, entry, FALSE,
811 channels = silc_server_get_client_channel_list(server, entry, TRUE,
814 if (entry->data.fingerprint[0] != 0 && entry->data.fingerprint[1] != 0)
815 fingerprint = entry->data.fingerprint;
819 SILC_PUT32_MSB(entry->mode, mode);
820 if (entry->connection)
821 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
824 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
826 2, idp->data, idp->len,
830 strlen(entry->userinfo),
831 6, channels ? channels->data : NULL,
832 channels ? channels->len : 0,
836 fingerprint ? 20 : 0,
837 10, umode_list ? umode_list->data :
838 NULL, umode_list ? umode_list->len :
841 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
842 0, packet->data, packet->len, FALSE);
844 silc_buffer_free(packet);
845 silc_buffer_free(idp);
847 silc_buffer_free(channels);
849 silc_buffer_free(umode_list);
853 if (status == SILC_STATUS_LIST_END)
858 /* Send error replies */
859 if (status == SILC_STATUS_OK && errors_count > 1)
860 status = SILC_STATUS_LIST_START;
863 for (i = 0, k = 0; i < errors_count; i++) {
865 idp = silc_id_payload_encode(errors[i].id, SILC_ID_CLIENT);
869 tmp = silc_argument_get_arg_type(cmd->args, errors[i].index, &len);
873 status = SILC_STATUS_LIST_ITEM;
874 if (errors_count > 1 && k == errors_count - 1)
875 status = SILC_STATUS_LIST_END;
876 if (count && k - 1 == count)
877 status = SILC_STATUS_LIST_END;
880 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
881 (status == SILC_STATUS_OK ?
882 errors[i].error : status),
883 (status == SILC_STATUS_OK ?
884 0 : errors[i].error),
886 silc_buffer_free(idp);
889 if (status == SILC_STATUS_LIST_END)
896 silc_server_command_whois_send_router(SilcServerCommandContext cmd)
898 SilcServer server = cmd->server;
900 SilcUInt16 old_ident;
902 old_ident = silc_command_get_ident(cmd->payload);
903 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
904 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
906 /* Send WHOIS command to our router */
907 silc_server_packet_send(server, (SilcSocketConnection)
908 SILC_PRIMARY_ROUTE(server),
909 SILC_PACKET_COMMAND, cmd->packet->flags,
910 tmpbuf->data, tmpbuf->len, TRUE);
912 /* Reprocess this packet after received reply from router */
913 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
914 silc_command_get_ident(cmd->payload),
915 silc_server_command_whois,
916 silc_server_command_dup(cmd));
918 silc_command_set_ident(cmd->payload, old_ident);
919 silc_buffer_free(tmpbuf);
923 silc_server_command_whois_process(SilcServerCommandContext cmd)
925 SilcServer server = cmd->server;
926 char *nick = NULL, *server_name = NULL;
928 SilcClientEntry *clients = NULL, entry;
929 SilcClientID **client_id = NULL;
930 SilcUInt32 client_id_count = 0, clients_count = 0, error_client_count = 0;
931 ResolveError error_client = NULL;
933 bool check_global = FALSE;
935 /* Parse the whois request */
936 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
937 &nick, &server_name, &count,
938 &error_client, &error_client_count))
941 /* Send the WHOIS request to the router only if it included nickname.
942 Since nicknames can be expanded into many clients we need to send it
943 to router. If the WHOIS included only client ID's we will check them
944 first locally since we just might have them. */
945 if (nick && !client_id_count && cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
946 server->server_type == SILC_SERVER && !cmd->pending &&
947 !server->standalone) {
948 silc_server_command_whois_send_router(cmd);
953 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
955 else if (server->server_type != SILC_SERVER)
958 /* Get all clients matching that ID or nickname from local list */
959 if (client_id_count) {
960 /* Check all Client ID's received in the command packet */
961 for (i = 0; i < client_id_count; i++) {
962 entry = silc_idlist_find_client_by_id(server->local_list,
963 client_id[i], TRUE, NULL);
964 if (!entry && check_global)
965 entry = silc_idlist_find_client_by_id(server->global_list,
966 client_id[i], TRUE, NULL);
968 clients = silc_realloc(clients, sizeof(*clients) *
969 (clients_count + 1));
970 clients[clients_count++] = entry;
972 /* If we are normal server and did not send the request first to router
973 do it now, since we do not have the Client ID information. */
974 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
975 server->server_type == SILC_SERVER && !cmd->pending &&
976 !server->standalone) {
977 silc_server_command_whois_send_router(cmd);
982 ADD_ERROR(error_client, error_client_count, client_id[i],
983 SILC_ID_CLIENT, 0, SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
987 /* Find by nickname */
988 if (!silc_idlist_get_clients_by_hash(server->local_list,
989 nick, server->md5hash,
990 &clients, &clients_count))
991 silc_idlist_get_clients_by_nickname(server->local_list,
993 &clients, &clients_count);
995 if (!silc_idlist_get_clients_by_hash(server->global_list,
996 nick, server->md5hash,
997 &clients, &clients_count))
998 silc_idlist_get_clients_by_nickname(server->global_list,
1000 &clients, &clients_count);
1004 if (!clients && (client_id_count || nick)) {
1005 /* If we are normal server and did not send the request first to router
1006 do it now, since we do not have the information. */
1007 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1008 server->server_type == SILC_SERVER && !cmd->pending &&
1009 !server->standalone) {
1010 silc_server_command_whois_send_router(cmd);
1015 /* Such client(s) really does not exist in the SILC network. */
1016 if (!client_id_count)
1017 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
1018 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1019 3, nick, strlen(nick));
1021 silc_server_command_whois_send_reply(cmd, NULL, 0,
1022 error_client, error_client_count,
1027 /* Router always finds the client entry if it exists in the SILC network.
1028 However, it might be incomplete entry and does not include all the
1029 mandatory fields that WHOIS command reply requires. Check for these and
1030 make query from the server who owns the client if some fields are
1032 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
1037 /* Send the command reply */
1038 silc_server_command_whois_send_reply(cmd, clients, clients_count,
1039 error_client, error_client_count,
1040 count, nick, client_id);
1043 if (client_id_count) {
1044 for (i = 0; i < client_id_count; i++)
1045 silc_free(client_id[i]);
1046 silc_free(client_id);
1049 silc_free(error_client);
1051 silc_free(server_name);
1056 /* Server side of command WHOIS. Processes user's query and sends found
1057 results as command replies back to the client. */
1059 SILC_SERVER_CMD_FUNC(whois)
1061 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1064 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 3328);
1066 ret = silc_server_command_whois_process(cmd);
1067 silc_server_command_free(cmd);
1070 /******************************************************************************
1074 ******************************************************************************/
1077 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
1085 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1087 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
1088 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1093 /* Get the nickname@server string and parse it. */
1094 silc_parse_userfqdn(tmp, nickname, server_name);
1096 /* Get the max count of reply messages allowed */
1097 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1099 SILC_GET32_MSB(*count, tmp);
1107 silc_server_command_whowas_check(SilcServerCommandContext cmd,
1108 SilcClientEntry *clients,
1109 SilcUInt32 clients_count)
1111 SilcServer server = cmd->server;
1113 SilcClientEntry entry;
1115 for (i = 0; i < clients_count; i++) {
1118 if (!entry->nickname || !entry->username) {
1120 SilcUInt16 old_ident;
1125 old_ident = silc_command_get_ident(cmd->payload);
1126 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1127 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1129 /* Send WHOWAS command */
1130 silc_server_packet_send(server, entry->router->connection,
1131 SILC_PACKET_COMMAND, cmd->packet->flags,
1132 tmpbuf->data, tmpbuf->len, TRUE);
1134 /* Reprocess this packet after received reply */
1135 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1136 silc_command_get_ident(cmd->payload),
1137 silc_server_command_whowas,
1138 silc_server_command_dup(cmd));
1139 cmd->pending = TRUE;
1140 silc_command_set_ident(cmd->payload, old_ident);
1142 silc_buffer_free(tmpbuf);
1151 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1152 SilcClientEntry *clients,
1153 SilcUInt32 clients_count)
1155 SilcServer server = cmd->server;
1157 int i, k, count = 0, len;
1158 SilcBuffer packet, idp;
1159 SilcClientEntry entry = NULL;
1161 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1162 char nh[256], uh[256];
1165 status = SILC_STATUS_OK;
1167 /* Process only entries that are not registered anymore. */
1169 for (i = 0; i < clients_count; i++) {
1170 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1177 /* No valid entries found at all, just send error */
1178 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1179 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1180 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1181 3, tmp, tmp ? strlen(tmp) : 0);
1185 if (valid_count > 1)
1186 status = SILC_STATUS_LIST_START;
1188 for (i = 0, k = 0; i < clients_count; i++) {
1194 status = SILC_STATUS_LIST_ITEM;
1195 if (valid_count > 1 && k == valid_count - 1)
1196 status = SILC_STATUS_LIST_END;
1197 if (count && k - 1 == count)
1198 status = SILC_STATUS_LIST_END;
1200 /* Send WHOWAS reply */
1201 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1202 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1203 memset(uh, 0, sizeof(uh));
1204 memset(nh, 0, sizeof(nh));
1206 strncat(nh, entry->nickname, strlen(entry->nickname));
1207 if (!strchr(entry->nickname, '@')) {
1208 strncat(nh, "@", 1);
1209 if (entry->servername) {
1210 strncat(nh, entry->servername, strlen(entry->servername));
1212 len = entry->router ? strlen(entry->router->server_name) :
1213 strlen(server->server_name);
1214 strncat(nh, entry->router ? entry->router->server_name :
1215 server->server_name, len);
1219 strncat(uh, entry->username, strlen(entry->username));
1220 if (!strchr(entry->username, '@')) {
1221 strncat(uh, "@", 1);
1222 strcat(uh, "*private*");
1226 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1227 status, 0, ident, 4,
1228 2, idp->data, idp->len,
1233 strlen(entry->userinfo) : 0);
1234 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1235 0, packet->data, packet->len, FALSE);
1237 silc_buffer_free(packet);
1238 silc_buffer_free(idp);
1240 if (status == SILC_STATUS_LIST_END)
1247 silc_server_command_whowas_process(SilcServerCommandContext cmd)
1249 SilcServer server = cmd->server;
1250 char *nick = NULL, *server_name = NULL;
1252 SilcClientEntry *clients = NULL;
1253 SilcUInt32 clients_count = 0;
1255 bool check_global = FALSE;
1257 /* Protocol dictates that we must always send the received WHOWAS request
1258 to our router if we are normal server, so let's do it now unless we
1259 are standalone. We will not send any replies to the client until we
1260 have received reply from the router. */
1261 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1262 server->server_type == SILC_SERVER && !cmd->pending &&
1263 !server->standalone) {
1265 SilcUInt16 old_ident;
1267 old_ident = silc_command_get_ident(cmd->payload);
1268 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1269 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1271 /* Send WHOWAS command to our router */
1272 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
1273 SILC_PACKET_COMMAND, cmd->packet->flags,
1274 tmpbuf->data, tmpbuf->len, TRUE);
1276 /* Reprocess this packet after received reply from router */
1277 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1278 silc_command_get_ident(cmd->payload),
1279 silc_server_command_whowas,
1280 silc_server_command_dup(cmd));
1281 cmd->pending = TRUE;
1282 silc_command_set_ident(cmd->payload, old_ident);
1284 silc_buffer_free(tmpbuf);
1289 /* We are ready to process the command request. Let's search for the
1290 requested client and send reply to the requesting client. */
1292 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1293 check_global = TRUE;
1294 else if (server->server_type != SILC_SERVER)
1295 check_global = TRUE;
1297 /* Parse the whowas request */
1298 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1301 /* Get all clients matching that nickname from local list */
1302 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1304 &clients, &clients_count))
1305 silc_idlist_get_clients_by_hash(server->local_list,
1306 nick, server->md5hash,
1307 &clients, &clients_count);
1309 /* Check global list as well */
1311 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1313 &clients, &clients_count))
1314 silc_idlist_get_clients_by_hash(server->global_list,
1315 nick, server->md5hash,
1316 &clients, &clients_count);
1320 /* Such a client really does not exist in the SILC network. */
1321 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1322 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1323 3, nick, strlen(nick));
1327 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1332 /* Send the command reply to the client */
1333 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1338 silc_free(server_name);
1342 /* Server side of command WHOWAS. */
1344 SILC_SERVER_CMD_FUNC(whowas)
1346 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1349 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1351 ret = silc_server_command_whowas_process(cmd);
1352 silc_server_command_free(cmd);
1355 /******************************************************************************
1359 ******************************************************************************/
1362 silc_server_command_identify_send_router(SilcServerCommandContext cmd)
1364 SilcServer server = cmd->server;
1366 SilcUInt16 old_ident;
1368 old_ident = silc_command_get_ident(cmd->payload);
1369 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1370 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1372 /* Send IDENTIFY command to our router */
1373 silc_server_packet_send(server, (SilcSocketConnection)
1374 SILC_PRIMARY_ROUTE(server),
1375 SILC_PACKET_COMMAND, cmd->packet->flags,
1376 tmpbuf->data, tmpbuf->len, TRUE);
1378 /* Reprocess this packet after received reply from router */
1379 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1380 silc_command_get_ident(cmd->payload),
1381 silc_server_command_identify,
1382 silc_server_command_dup(cmd));
1383 cmd->pending = TRUE;
1384 silc_command_set_ident(cmd->payload, old_ident);
1385 silc_buffer_free(tmpbuf);
1389 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1390 SilcClientEntry **clients,
1391 SilcUInt32 *clients_count,
1392 SilcServerEntry **servers,
1393 SilcUInt32 *servers_count,
1394 SilcChannelEntry **channels,
1395 SilcUInt32 *channels_count,
1397 ResolveError *error_id,
1398 SilcUInt32 *error_id_count)
1400 SilcServer server = cmd->server;
1403 SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
1405 bool check_global = FALSE;
1409 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1410 check_global = TRUE;
1411 else if (server->server_type != SILC_SERVER)
1412 check_global = TRUE;
1414 /* If ID Payload is in the command it must be used instead of names */
1415 tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1417 /* No ID, get the names. */
1419 /* If we are normal server and have not resolved information from
1420 router yet, do so now. */
1421 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1422 server->server_type == SILC_SERVER && !cmd->pending &&
1423 !server->standalone) {
1424 silc_server_command_identify_send_router(cmd);
1428 /* Try to get nickname@server. */
1429 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1432 char *nick_server = NULL;
1434 silc_parse_userfqdn(tmp, &nick, &nick_server);
1436 if (!silc_idlist_get_clients_by_hash(server->local_list,
1437 nick, server->md5hash,
1438 clients, clients_count))
1439 silc_idlist_get_clients_by_nickname(server->local_list,
1441 clients, clients_count);
1443 if (!silc_idlist_get_clients_by_hash(server->global_list,
1444 nick, server->md5hash,
1445 clients, clients_count))
1446 silc_idlist_get_clients_by_nickname(server->global_list,
1448 clients, clients_count);
1452 silc_free(nick_server);
1455 /* the nickname does not exist, send error reply */
1456 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1457 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1458 3, tmp, strlen(tmp));
1463 /* Try to get server name */
1464 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1466 entry = silc_idlist_find_server_by_name(server->local_list,
1468 if (!entry && check_global)
1469 entry = silc_idlist_find_server_by_name(server->global_list,
1472 *servers = silc_realloc(*servers, sizeof(**servers) *
1473 (*servers_count + 1));
1474 (*servers)[(*servers_count)++] = entry;
1478 /* the server does not exist, send error reply */
1479 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1480 SILC_STATUS_ERR_NO_SUCH_SERVER,
1481 0, 3, tmp, strlen(tmp));
1486 /* Try to get channel name */
1487 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1489 entry = silc_idlist_find_channel_by_name(server->local_list,
1491 if (!entry && check_global)
1492 entry = silc_idlist_find_channel_by_name(server->global_list,
1495 *channels = silc_realloc(*channels, sizeof(**channels) *
1496 (*channels_count + 1));
1497 (*channels)[(*channels_count)++] = entry;
1501 /* The channel does not exist, send error reply */
1502 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1503 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1504 0, 3, tmp, strlen(tmp));
1509 if (!(*clients) && !(*servers) && !(*channels)) {
1510 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1511 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1516 /* Command includes ID, we must use that. Also check whether the command
1517 has more than one ID set - take them all. */
1519 /* Take all ID's from the command packet */
1520 for (i = 0; i < argc; i++) {
1523 tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
1527 idp = silc_id_payload_parse(tmp, len);
1529 ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1530 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1532 id = silc_id_payload_get_id(idp);
1533 switch (silc_id_payload_get_type(idp)) {
1535 case SILC_ID_CLIENT:
1536 entry = silc_idlist_find_client_by_id(server->local_list,
1538 if (!entry && check_global)
1539 entry = silc_idlist_find_client_by_id(server->global_list,
1542 *clients = silc_realloc(*clients, sizeof(**clients) *
1543 (*clients_count + 1));
1544 (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
1546 /* If we are normal server and have not resolved information from
1547 router yet, do so now. */
1548 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1549 server->server_type == SILC_SERVER && !cmd->pending &&
1550 !server->standalone) {
1551 silc_server_command_identify_send_router(cmd);
1552 silc_free(*clients);
1553 silc_free(*servers);
1554 silc_free(*channels);
1555 silc_free(*error_id);
1559 ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1560 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
1565 case SILC_ID_SERVER:
1566 entry = silc_idlist_find_server_by_id(server->local_list,
1568 if (!entry && check_global)
1569 entry = silc_idlist_find_server_by_id(server->global_list,
1572 *servers = silc_realloc(*servers, sizeof(**servers) *
1573 (*servers_count + 1));
1574 (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
1576 /* If we are normal server and have not resolved information from
1577 router yet, do so now. */
1578 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1579 server->server_type == SILC_SERVER && !cmd->pending &&
1580 !server->standalone) {
1581 silc_server_command_identify_send_router(cmd);
1582 silc_free(*clients);
1583 silc_free(*servers);
1584 silc_free(*channels);
1585 silc_free(*error_id);
1589 ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1590 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
1594 case SILC_ID_CHANNEL:
1595 entry = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
1596 if (!entry && check_global)
1597 entry = silc_idlist_find_channel_by_id(server->global_list, id,
1600 *channels = silc_realloc(*channels, sizeof(**channels) *
1601 (*channels_count + 1));
1602 (*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
1604 /* If we are normal server and have not resolved information from
1605 router yet, do so now. */
1606 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1607 server->server_type == SILC_SERVER && !cmd->pending &&
1608 !server->standalone) {
1609 silc_server_command_identify_send_router(cmd);
1610 silc_free(*clients);
1611 silc_free(*servers);
1612 silc_free(*channels);
1613 silc_free(*error_id);
1617 ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1618 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID);
1623 silc_id_payload_free(idp);
1628 /* Get the max count of reply messages allowed */
1629 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1631 SILC_GET32_MSB(*count, tmp);
1638 /* Checks that all mandatory fields in client entry are present. If not
1639 then send WHOIS request to the server who owns the client. We use
1640 WHOIS because we want to get as much information as possible at once. */
1643 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1644 SilcClientEntry *clients,
1645 SilcUInt32 clients_count)
1647 SilcServer server = cmd->server;
1648 SilcClientEntry entry;
1649 SilcServerResolveContext resolve = NULL, r = NULL;
1650 SilcUInt32 resolve_count = 0;
1654 for (i = 0; i < clients_count; i++) {
1659 if (entry->nickname ||
1660 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1664 /* If we are normal server, and we've not resolved this client from
1665 router and it is global client, we'll check whether it is on some
1666 channel. If not then we cannot be sure about its validity, and
1667 we'll resolve it from router. */
1668 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
1669 entry->connection || silc_hash_table_count(entry->channels))
1673 /* We need to resolve this entry since it is not complete */
1675 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1676 /* The entry is being resolved (and we are not the resolver) so attach
1677 to the command reply and we're done with this one. */
1678 silc_server_command_pending(server, SILC_COMMAND_NONE,
1679 entry->resolve_cmd_ident,
1680 silc_server_command_identify,
1681 silc_server_command_dup(cmd));
1684 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1685 /* We've resolved this and it still is not ready. We'll return
1686 and are that this will be handled again after it is resolved. */
1687 for (i = 0; i < resolve_count; i++) {
1688 for (k = 0; k < r->res_argc; k++)
1689 silc_free(r->res_argv[k]);
1690 silc_free(r->res_argv);
1691 silc_free(r->res_argv_lens);
1692 silc_free(r->res_argv_types);
1697 /* We'll resolve this client */
1701 for (k = 0; k < resolve_count; k++) {
1702 if (resolve[k].router == entry->router) {
1709 resolve = silc_realloc(resolve, sizeof(*resolve) *
1710 (resolve_count + 1));
1711 r = &resolve[resolve_count];
1712 memset(r, 0, sizeof(*r));
1713 r->router = entry->router;
1714 r->ident = ++server->cmd_ident;
1718 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1720 r->res_argv_lens = silc_realloc(r->res_argv_lens,
1721 sizeof(*r->res_argv_lens) *
1723 r->res_argv_types = silc_realloc(r->res_argv_types,
1724 sizeof(*r->res_argv_types) *
1726 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1727 r->res_argv[r->res_argc] = silc_calloc(idp->len,
1728 sizeof(**r->res_argv));
1729 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1730 r->res_argv_lens[r->res_argc] = idp->len;
1731 r->res_argv_types[r->res_argc] = r->res_argc + 4;
1733 silc_buffer_free(idp);
1735 entry->resolve_cmd_ident = r->ident;
1736 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1737 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1742 /* Do the resolving */
1743 for (i = 0; i < resolve_count; i++) {
1748 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1749 now anyway so make it a good one. */
1750 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1751 r->res_argc, r->res_argv,
1755 silc_server_packet_send(server, r->router->connection,
1756 SILC_PACKET_COMMAND, cmd->packet->flags,
1757 res_cmd->data, res_cmd->len, FALSE);
1759 /* Reprocess this packet after received reply */
1760 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1762 silc_server_command_identify,
1763 silc_server_command_dup(cmd));
1764 cmd->pending = TRUE;
1766 silc_buffer_free(res_cmd);
1767 for (k = 0; k < r->res_argc; k++)
1768 silc_free(r->res_argv[k]);
1769 silc_free(r->res_argv);
1770 silc_free(r->res_argv_lens);
1771 silc_free(r->res_argv_types);
1780 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1781 SilcClientEntry *clients,
1782 SilcUInt32 clients_count,
1783 SilcServerEntry *servers,
1784 SilcUInt32 servers_count,
1785 SilcChannelEntry *channels,
1786 SilcUInt32 channels_count,
1787 ResolveError errors,
1788 SilcUInt32 errors_count,
1791 SilcServer server = cmd->server;
1792 int i, k, valid_count;
1794 SilcBuffer packet, idp;
1796 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1797 char nh[256], uh[256];
1798 SilcSocketConnection hsock;
1801 status = SILC_STATUS_OK;
1804 SilcClientEntry entry;
1805 valid_count = clients_count;
1807 if (silc_argument_get_arg_type(cmd->args, 1, NULL)) {
1808 /* Process only valid clients and ignore those that are not registered.
1809 This is checked with nickname only because when resolved client IDs
1810 we check that they are registered earlier. */
1812 for (i = 0; i < clients_count; i++) {
1813 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1820 /* No valid entries found at all, just send error */
1821 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1822 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1823 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1824 3, tmp, tmp ? strlen(tmp) : 0);
1829 /* Process all valid client entries and send command replies */
1831 if (valid_count > 1)
1832 status = SILC_STATUS_LIST_START;
1834 for (i = 0, k = 0; i < clients_count; i++) {
1840 status = SILC_STATUS_LIST_ITEM;
1841 if (valid_count > 1 && k == valid_count - 1
1842 && !servers_count && !channels_count && !errors_count)
1843 status = SILC_STATUS_LIST_END;
1844 if (count && k - 1 == count)
1845 status = SILC_STATUS_LIST_END;
1847 /* Send IDENTIFY reply */
1849 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1850 memset(uh, 0, sizeof(uh));
1851 memset(nh, 0, sizeof(nh));
1852 strncat(nh, entry->nickname, strlen(entry->nickname));
1853 if (!strchr(entry->nickname, '@')) {
1854 strncat(nh, "@", 1);
1855 if (entry->servername) {
1856 strncat(nh, entry->servername, strlen(entry->servername));
1858 len = entry->router ? strlen(entry->router->server_name) :
1859 strlen(server->server_name);
1860 strncat(nh, entry->router ? entry->router->server_name :
1861 server->server_name, len);
1865 if (!entry->username) {
1866 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1867 status, 0, ident, 2,
1868 2, idp->data, idp->len,
1871 strncat(uh, entry->username, strlen(entry->username));
1872 if (!strchr(entry->username, '@') && entry->connection) {
1873 strncat(uh, "@", 1);
1874 hsock = (SilcSocketConnection)entry->connection;
1875 len = strlen(hsock->hostname);
1876 strncat(uh, hsock->hostname, len);
1879 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1880 status, 0, ident, 3,
1881 2, idp->data, idp->len,
1886 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1887 0, packet->data, packet->len, FALSE);
1889 silc_buffer_free(packet);
1890 silc_buffer_free(idp);
1892 if (status == SILC_STATUS_LIST_END)
1899 SilcServerEntry entry;
1901 if (status == SILC_STATUS_OK && servers_count > 1)
1902 status = SILC_STATUS_LIST_START;
1904 for (i = 0, k = 0; i < servers_count; i++) {
1908 status = SILC_STATUS_LIST_ITEM;
1909 if (servers_count > 1 && k == servers_count - 1 && !channels_count &&
1911 status = SILC_STATUS_LIST_END;
1912 if (count && k - 1 == count)
1913 status = SILC_STATUS_LIST_END;
1915 /* Send IDENTIFY reply */
1916 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1918 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1919 status, 0, ident, 2,
1920 2, idp->data, idp->len,
1921 3, entry->server_name,
1922 entry->server_name ?
1923 strlen(entry->server_name) : 0);
1924 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1925 0, packet->data, packet->len, FALSE);
1927 silc_buffer_free(packet);
1928 silc_buffer_free(idp);
1930 if (status == SILC_STATUS_LIST_END)
1937 SilcChannelEntry entry;
1939 if (status == SILC_STATUS_OK && channels_count > 1)
1940 status = SILC_STATUS_LIST_START;
1942 for (i = 0, k = 0; i < channels_count; i++) {
1943 entry = channels[i];
1946 status = SILC_STATUS_LIST_ITEM;
1947 if (channels_count > 1 && k == channels_count - 1 && !errors_count)
1948 status = SILC_STATUS_LIST_END;
1949 if (count && k - 1 == count)
1950 status = SILC_STATUS_LIST_END;
1952 /* Send IDENTIFY reply */
1953 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1955 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1956 status, 0, ident, 2,
1957 2, idp->data, idp->len,
1958 3, entry->channel_name,
1959 entry->channel_name ?
1960 strlen(entry->channel_name): 0);
1961 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1962 0, packet->data, packet->len, FALSE);
1964 silc_buffer_free(packet);
1965 silc_buffer_free(idp);
1967 if (status == SILC_STATUS_LIST_END)
1973 /* Send error replies */
1975 if (status == SILC_STATUS_OK && errors_count > 1)
1976 status = SILC_STATUS_LIST_START;
1979 for (i = 0, k = 0; i < errors_count; i++) {
1981 idp = silc_id_payload_encode(errors[i].id, SILC_ID_CLIENT);
1985 tmp = silc_argument_get_arg_type(cmd->args, errors[i].index, &len);
1989 status = SILC_STATUS_LIST_ITEM;
1990 if (errors_count > 1 && k == errors_count - 1)
1991 status = SILC_STATUS_LIST_END;
1992 if (count && k - 1 == count)
1993 status = SILC_STATUS_LIST_END;
1996 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1997 (status == SILC_STATUS_OK ?
1998 errors[i].error : status),
1999 (status == SILC_STATUS_OK ?
2000 0 : errors[i].error),
2002 silc_buffer_free(idp);
2005 if (status == SILC_STATUS_LIST_END)
2013 silc_server_command_identify_process(SilcServerCommandContext cmd)
2015 SilcUInt32 count = 0;
2017 SilcClientEntry *clients = NULL;
2018 SilcServerEntry *servers = NULL;
2019 SilcChannelEntry *channels = NULL;
2020 SilcUInt32 clients_count = 0, servers_count = 0, channels_count = 0;
2021 SilcUInt32 errors_count = 0;
2022 ResolveError errors = NULL;
2024 /* Parse the IDENTIFY request */
2025 ret = silc_server_command_identify_parse(cmd,
2026 &clients, &clients_count,
2027 &servers, &servers_count,
2028 &channels, &channels_count,
2029 &count, &errors, &errors_count);
2034 /* Check that all mandatory fields are present and request those data
2035 from the server who owns the client if necessary. */
2036 if (!silc_server_command_identify_check_client(cmd, clients,
2042 /* Send the command reply to the client */
2043 silc_server_command_identify_send_reply(cmd,
2044 clients, clients_count,
2045 servers, servers_count,
2046 channels, channels_count,
2047 errors, errors_count,
2053 silc_free(channels);
2058 SILC_SERVER_CMD_FUNC(identify)
2060 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2063 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
2065 ret = silc_server_command_identify_process(cmd);
2066 silc_server_command_free(cmd);
2069 /* Server side of command NICK. Sets nickname for user. Setting
2070 nickname causes generation of a new client ID for the client. The
2071 new client ID is sent to the client after changing the nickname. */
2073 SILC_SERVER_CMD_FUNC(nick)
2075 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2076 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2077 SilcServer server = cmd->server;
2078 SilcBuffer packet, nidp, oidp = NULL;
2079 SilcClientID *new_id;
2080 SilcUInt32 nick_len;
2082 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2085 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2088 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
2090 /* Check nickname */
2091 nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
2094 if (silc_server_name_bad_chars(nick, nick_len) == TRUE) {
2095 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2096 SILC_STATUS_ERR_BAD_NICKNAME, 0);
2100 /* Check for same nickname */
2101 if (!strcmp(client->nickname, nick)) {
2102 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2106 /* Create new Client ID */
2107 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
2109 cmd->server->md5hash, nick,
2113 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2114 SILC_STATUS_ERR_BAD_NICKNAME, 0);
2117 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2120 /* Send notify about nickname change to our router. We send the new
2121 ID and ask to replace it with the old one. If we are router the
2122 packet is broadcasted. Send NICK_CHANGE notify. */
2123 silc_server_send_notify_nick_change(server, SILC_PRIMARY_ROUTE(server),
2124 SILC_BROADCAST(server), client->id,
2127 /* Check if anyone is watching the old nickname */
2128 if (server->server_type == SILC_ROUTER)
2129 silc_server_check_watcher_list(server, client, nick,
2130 SILC_NOTIFY_TYPE_NICK_CHANGE);
2132 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2134 /* Remove old cache entry */
2135 silc_idcache_del_by_context(server->local_list->clients, client);
2137 silc_free(client->id);
2138 client->id = new_id;
2140 silc_free(client->nickname);
2141 client->nickname = strdup(nick);
2143 /* Update client cache */
2144 silc_idcache_add(server->local_list->clients, client->nickname,
2145 client->id, (void *)client, 0, NULL);
2147 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2149 /* Send NICK_CHANGE notify to the client's channels */
2150 silc_server_send_notify_on_channels(server, NULL, client,
2151 SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
2152 oidp->data, oidp->len,
2153 nidp->data, nidp->len,
2155 strlen(client->nickname));
2157 /* Check if anyone is watching the new nickname */
2158 if (server->server_type == SILC_ROUTER)
2159 silc_server_check_watcher_list(server, client, NULL,
2160 SILC_NOTIFY_TYPE_NICK_CHANGE);
2163 /* Send the new Client ID as reply command back to client */
2164 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
2165 SILC_STATUS_OK, 0, ident, 2,
2166 2, nidp->data, nidp->len,
2167 3, nick, strlen(nick));
2168 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2169 0, packet->data, packet->len, FALSE);
2171 silc_buffer_free(packet);
2172 silc_buffer_free(nidp);
2174 silc_buffer_free(oidp);
2177 silc_server_command_free(cmd);
2180 /* Sends the LIST command reply */
2183 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2184 SilcChannelEntry *lch,
2185 SilcUInt32 lch_count,
2186 SilcChannelEntry *gch,
2187 SilcUInt32 gch_count)
2190 SilcBuffer packet, idp;
2191 SilcChannelEntry entry;
2193 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2195 unsigned char usercount[4];
2197 int valid_lcount = 0, valid_rcount = 0;
2199 for (i = 0; i < lch_count; i++) {
2200 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2205 for (i = 0; i < gch_count; i++) {
2206 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2212 status = SILC_STATUS_OK;
2213 if ((lch_count + gch_count) > 1)
2214 status = SILC_STATUS_LIST_START;
2217 for (i = 0, k = 0; i < lch_count; i++) {
2223 status = SILC_STATUS_LIST_ITEM;
2224 if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
2225 status = SILC_STATUS_LIST_END;
2227 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2229 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2230 topic = "*private*";
2231 memset(usercount, 0, sizeof(usercount));
2233 topic = entry->topic;
2234 users = silc_hash_table_count(entry->user_list);
2235 SILC_PUT32_MSB(users, usercount);
2238 /* Send the reply */
2240 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2241 status, 0, ident, 4,
2242 2, idp->data, idp->len,
2243 3, entry->channel_name,
2244 strlen(entry->channel_name),
2245 4, topic, topic ? strlen(topic) : 0,
2247 silc_server_packet_send(cmd->server, cmd->sock,
2248 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2249 packet->len, FALSE);
2250 silc_buffer_free(packet);
2251 silc_buffer_free(idp);
2256 for (i = 0, k = 0; i < gch_count; i++) {
2262 status = SILC_STATUS_LIST_ITEM;
2263 if (valid_rcount > 1 && k == valid_rcount - 1)
2264 status = SILC_STATUS_LIST_END;
2266 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2268 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2269 topic = "*private*";
2270 memset(usercount, 0, sizeof(usercount));
2272 topic = entry->topic;
2273 users = entry->user_count;
2274 SILC_PUT32_MSB(users, usercount);
2277 /* Send the reply */
2279 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2280 status, 0, ident, 4,
2281 2, idp->data, idp->len,
2282 3, entry->channel_name,
2283 strlen(entry->channel_name),
2284 4, topic, topic ? strlen(topic) : 0,
2286 silc_server_packet_send(cmd->server, cmd->sock,
2287 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2288 packet->len, FALSE);
2289 silc_buffer_free(packet);
2290 silc_buffer_free(idp);
2295 /* Server side of LIST command. This lists the channel of the requested
2296 server. Secret channels are not listed. */
2298 SILC_SERVER_CMD_FUNC(list)
2300 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2301 SilcServer server = cmd->server;
2302 SilcChannelID *channel_id = NULL;
2305 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2306 SilcUInt32 lch_count = 0, gch_count = 0;
2308 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2310 /* If we are normal server, send the command to router, since we
2311 want to know all channels in the network. */
2312 if (!cmd->pending && server->server_type == SILC_SERVER &&
2313 !server->standalone) {
2315 SilcUInt16 old_ident;
2317 old_ident = silc_command_get_ident(cmd->payload);
2318 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2319 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2320 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
2321 SILC_PACKET_COMMAND, cmd->packet->flags,
2322 tmpbuf->data, tmpbuf->len, TRUE);
2324 /* Reprocess this packet after received reply from router */
2325 silc_server_command_pending(server, SILC_COMMAND_LIST,
2326 silc_command_get_ident(cmd->payload),
2327 silc_server_command_list,
2328 silc_server_command_dup(cmd));
2329 cmd->pending = TRUE;
2330 silc_command_set_ident(cmd->payload, old_ident);
2331 silc_buffer_free(tmpbuf);
2335 /* Get Channel ID */
2336 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2338 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2340 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2341 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2346 /* Get the channels from local list */
2347 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2350 /* Get the channels from global list */
2351 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2354 /* Send the reply */
2355 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2356 gchannels, gch_count);
2358 silc_free(lchannels);
2359 silc_free(gchannels);
2362 silc_server_command_free(cmd);
2365 /* Server side of TOPIC command. Sets topic for channel and/or returns
2366 current topic to client. */
2368 SILC_SERVER_CMD_FUNC(topic)
2370 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2371 SilcServer server = cmd->server;
2372 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2373 SilcChannelID *channel_id;
2374 SilcChannelEntry channel;
2375 SilcChannelClientEntry chl;
2376 SilcBuffer packet, idp;
2378 SilcUInt32 argc, tmp_len;
2379 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2381 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2383 argc = silc_argument_get_arg_num(cmd->args);
2385 /* Get Channel ID */
2386 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2388 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2389 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2392 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2394 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2395 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2399 /* Check whether the channel exists */
2400 channel = silc_idlist_find_channel_by_id(server->local_list,
2403 channel = silc_idlist_find_channel_by_id(server->global_list,
2406 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2407 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
2415 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2417 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2418 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2423 if (strlen(tmp) > 256) {
2424 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2425 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2430 /* See whether the client is on channel and has rights to change topic */
2431 if (!silc_server_client_on_channel(client, channel, &chl)) {
2432 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2433 SILC_STATUS_ERR_NOT_ON_CHANNEL,
2438 if (channel->mode & SILC_CHANNEL_MODE_TOPIC &&
2439 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
2440 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
2441 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2442 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
2447 if (!channel->topic || strcmp(channel->topic, tmp)) {
2448 /* Set the topic for channel */
2449 silc_free(channel->topic);
2450 channel->topic = strdup(tmp);
2452 /* Send TOPIC_SET notify type to the network */
2453 silc_server_send_notify_topic_set(server, SILC_PRIMARY_ROUTE(server),
2454 SILC_BROADCAST(server), channel,
2455 client->id, SILC_ID_CLIENT,
2458 /* Send notify about topic change to all clients on the channel */
2459 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2460 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2461 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2462 idp->data, idp->len,
2464 strlen(channel->topic));
2465 silc_buffer_free(idp);
2469 /* Send the topic to client as reply packet */
2470 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2471 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2472 SILC_STATUS_OK, 0, ident, 2,
2473 2, idp->data, idp->len,
2476 strlen(channel->topic) : 0);
2477 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2478 0, packet->data, packet->len, FALSE);
2480 silc_buffer_free(packet);
2481 silc_buffer_free(idp);
2482 silc_free(channel_id);
2485 silc_server_command_free(cmd);
2488 /* Server side of INVITE command. Invites some client to join some channel.
2489 This command is also used to manage the invite list of the channel. */
2491 SILC_SERVER_CMD_FUNC(invite)
2493 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2494 SilcServer server = cmd->server;
2495 SilcSocketConnection sock = cmd->sock, dest_sock;
2496 SilcChannelClientEntry chl;
2497 SilcClientEntry sender, dest;
2498 SilcClientID *dest_id = NULL;
2499 SilcChannelEntry channel;
2500 SilcChannelID *channel_id = NULL;
2501 SilcIDListData idata;
2502 SilcBuffer idp, idp2, packet;
2503 unsigned char *tmp, *add, *del;
2505 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2507 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2509 /* Get Channel ID */
2510 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2512 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2513 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2516 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
2518 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2519 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2523 /* Get the channel entry */
2524 channel = silc_idlist_find_channel_by_id(server->local_list,
2527 channel = silc_idlist_find_channel_by_id(server->global_list,
2530 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2531 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
2537 /* Check whether the sender of this command is on the channel. */
2538 sender = (SilcClientEntry)sock->user_data;
2539 if (!silc_server_client_on_channel(sender, channel, &chl)) {
2540 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2541 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
2545 /* Check whether the channel is invite-only channel. If yes then the
2546 sender of this command must be at least channel operator. */
2547 if (channel->mode & SILC_CHANNEL_MODE_INVITE &&
2548 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
2549 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
2550 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2551 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
2556 /* Get destination client ID */
2557 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2562 dest_id = silc_id_payload_parse_id(tmp, len, NULL);
2564 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2565 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
2569 /* Get the client entry */
2570 dest = silc_server_get_client_resolve(server, dest_id, FALSE, &resolve);
2572 if (server->server_type != SILC_SERVER || !resolve) {
2573 silc_server_command_send_status_reply(
2574 cmd, SILC_COMMAND_INVITE,
2575 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0);
2579 /* The client info is being resolved. Reprocess this packet after
2580 receiving the reply to the query. */
2581 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2583 silc_server_command_invite,
2584 silc_server_command_dup(cmd));
2585 cmd->pending = TRUE;
2586 silc_free(channel_id);
2591 /* Check whether the requested client is already on the channel. */
2592 if (silc_server_client_on_channel(dest, channel, NULL)) {
2593 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2594 SILC_STATUS_ERR_USER_ON_CHANNEL,
2599 /* Get route to the client */
2600 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id,
2603 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2604 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2609 memset(invite, 0, sizeof(invite));
2610 strncat(invite, dest->nickname, strlen(dest->nickname));
2611 strncat(invite, "!", 1);
2612 strncat(invite, dest->username, strlen(dest->username));
2613 if (!strchr(dest->username, '@')) {
2614 strncat(invite, "@", 1);
2615 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2618 len = strlen(invite);
2619 if (!channel->invite_list)
2620 channel->invite_list = silc_calloc(len + 2,
2621 sizeof(*channel->invite_list));
2623 channel->invite_list = silc_realloc(channel->invite_list,
2624 sizeof(*channel->invite_list) *
2626 strlen(channel->invite_list) + 2));
2627 strncat(channel->invite_list, invite, len);
2628 strncat(channel->invite_list, ",", 1);
2630 if (!(dest->mode & SILC_UMODE_BLOCK_INVITE)) {
2631 /* Send notify to the client that is invited to the channel */
2632 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2633 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2634 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2636 SILC_NOTIFY_TYPE_INVITE, 3,
2637 idp->data, idp->len,
2638 channel->channel_name,
2639 strlen(channel->channel_name),
2640 idp2->data, idp2->len);
2641 silc_buffer_free(idp);
2642 silc_buffer_free(idp2);
2646 /* Add the client to the invite list of the channel */
2647 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2649 if (!channel->invite_list)
2650 channel->invite_list = silc_calloc(len + 2,
2651 sizeof(*channel->invite_list));
2653 channel->invite_list = silc_realloc(channel->invite_list,
2654 sizeof(*channel->invite_list) *
2656 strlen(channel->invite_list) + 2));
2657 if (add[len - 1] == ',')
2658 add[len - 1] = '\0';
2660 strncat(channel->invite_list, add, len);
2661 strncat(channel->invite_list, ",", 1);
2664 /* Get the invite to be removed and remove it from the list */
2665 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2666 if (del && channel->invite_list) {
2667 char *start, *end, *n;
2669 if (!strncmp(channel->invite_list, del,
2670 strlen(channel->invite_list) - 1)) {
2671 silc_free(channel->invite_list);
2672 channel->invite_list = NULL;
2674 start = strstr(channel->invite_list, del);
2675 if (start && strlen(start) >= len) {
2677 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2678 strncat(n, channel->invite_list, start - channel->invite_list);
2679 strncat(n, end + 1, ((channel->invite_list +
2680 strlen(channel->invite_list)) - end) - 1);
2681 silc_free(channel->invite_list);
2682 channel->invite_list = n;
2687 /* Send notify to the primary router */
2688 silc_server_send_notify_invite(server, SILC_PRIMARY_ROUTE(server),
2689 SILC_BROADCAST(server), channel,
2690 sender->id, add, del);
2692 /* Send command reply */
2693 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2697 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2698 SILC_STATUS_OK, 0, ident, 2,
2700 3, channel->invite_list,
2701 channel->invite_list ?
2702 strlen(channel->invite_list) : 0);
2705 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2706 SILC_STATUS_OK, 0, ident, 1,
2708 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2709 packet->data, packet->len, FALSE);
2710 silc_buffer_free(packet);
2714 silc_free(channel_id);
2715 silc_server_command_free(cmd);
2720 SilcSocketConnection sock;
2724 /* Quits connection to client. This gets called if client won't
2725 close the connection even when it has issued QUIT command. */
2727 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2729 QuitInternal q = (QuitInternal)context;
2731 /* Free all client specific data, such as client entry and entires
2732 on channels this client may be on. */
2733 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2735 q->sock->user_data = NULL;
2737 /* Close the connection on our side */
2738 silc_server_close_connection(q->server, q->sock);
2740 silc_free(q->signoff);
2744 /* Quits SILC session. This is the normal way to disconnect client. */
2746 SILC_SERVER_CMD_FUNC(quit)
2748 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2749 SilcServer server = cmd->server;
2750 SilcSocketConnection sock = cmd->sock;
2752 unsigned char *tmp = NULL;
2755 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2757 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2761 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2765 q = silc_calloc(1, sizeof(*q));
2768 q->signoff = tmp ? strdup(tmp) : NULL;
2770 /* We quit the connection with little timeout */
2771 silc_schedule_task_add(server->schedule, sock->sock,
2772 silc_server_command_quit_cb, (void *)q,
2773 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2776 silc_server_command_free(cmd);
2779 /* Server side of command KILL. This command is used by router operator
2780 to remove an client from the SILC Network temporarily. */
2782 SILC_SERVER_CMD_FUNC(kill)
2784 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2785 SilcServer server = cmd->server;
2786 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2787 SilcClientEntry remote_client;
2788 SilcClientID *client_id;
2789 unsigned char *tmp, *comment;
2790 SilcUInt32 tmp_len, tmp_len2;
2793 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2795 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2798 /* KILL command works only on router */
2799 if (server->server_type != SILC_ROUTER) {
2800 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2801 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
2805 /* Check whether client has the permissions. */
2806 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2807 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2808 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
2812 /* Get the client ID */
2813 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2815 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2816 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2820 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2822 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2823 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2828 /* Get the client entry */
2829 remote_client = silc_idlist_find_client_by_id(server->local_list,
2830 client_id, TRUE, NULL);
2832 if (!remote_client) {
2833 remote_client = silc_idlist_find_client_by_id(server->global_list,
2834 client_id, TRUE, NULL);
2836 if (!remote_client) {
2837 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2838 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2845 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2849 /* Send reply to the sender */
2850 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2853 /* Check if anyone is watching this nickname */
2854 if (server->server_type == SILC_ROUTER)
2855 silc_server_check_watcher_list(server, client, NULL,
2856 SILC_NOTIFY_TYPE_KILLED);
2858 /* Now do the killing */
2859 silc_server_kill_client(server, remote_client, comment, client->id,
2863 silc_server_command_free(cmd);
2866 /* Server side of command INFO. This sends information about us to
2867 the client. If client requested specific server we will send the
2868 command to that server. */
2870 SILC_SERVER_CMD_FUNC(info)
2872 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2873 SilcServer server = cmd->server;
2874 SilcBuffer packet, idp;
2877 char *dest_server, *server_info = NULL, *server_name;
2878 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2879 SilcServerEntry entry = NULL;
2880 SilcServerID *server_id = NULL;
2882 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2884 /* Get server name */
2885 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2888 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2890 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2892 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2893 SILC_STATUS_ERR_NO_SERVER_ID, 0);
2899 /* Check whether we have this server cached */
2900 entry = silc_idlist_find_server_by_id(server->local_list,
2901 server_id, TRUE, NULL);
2903 entry = silc_idlist_find_server_by_id(server->global_list,
2904 server_id, TRUE, NULL);
2905 if (!entry && server->server_type != SILC_SERVER) {
2906 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2907 SILC_STATUS_ERR_NO_SUCH_SERVER,
2914 /* Some buggy servers has sent request to router about themselves. */
2915 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2918 if ((!dest_server && !server_id && !entry) || (entry &&
2919 entry == server->id_entry) ||
2920 (dest_server && !cmd->pending &&
2921 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2922 /* Send our reply */
2923 char info_string[256];
2925 memset(info_string, 0, sizeof(info_string));
2926 snprintf(info_string, sizeof(info_string),
2927 "location: %s server: %s admin: %s <%s>",
2928 server->config->server_info->location,
2929 server->config->server_info->server_type,
2930 server->config->server_info->admin,
2931 server->config->server_info->email);
2933 server_info = info_string;
2934 entry = server->id_entry;
2936 /* Check whether we have this server cached */
2937 if (!entry && dest_server) {
2938 entry = silc_idlist_find_server_by_name(server->global_list,
2939 dest_server, TRUE, NULL);
2941 entry = silc_idlist_find_server_by_name(server->local_list,
2942 dest_server, TRUE, NULL);
2946 if (!cmd->pending &&
2947 server->server_type != SILC_SERVER && entry && !entry->server_info) {
2948 /* Send to the server */
2950 SilcUInt16 old_ident;
2952 old_ident = silc_command_get_ident(cmd->payload);
2953 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2954 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2956 silc_server_packet_send(server, entry->connection,
2957 SILC_PACKET_COMMAND, cmd->packet->flags,
2958 tmpbuf->data, tmpbuf->len, TRUE);
2960 /* Reprocess this packet after received reply from router */
2961 silc_server_command_pending(server, SILC_COMMAND_INFO,
2962 silc_command_get_ident(cmd->payload),
2963 silc_server_command_info,
2964 silc_server_command_dup(cmd));
2965 cmd->pending = TRUE;
2966 silc_command_set_ident(cmd->payload, old_ident);
2967 silc_buffer_free(tmpbuf);
2971 if (!entry && !cmd->pending && !server->standalone) {
2972 /* Send to the primary router */
2974 SilcUInt16 old_ident;
2976 old_ident = silc_command_get_ident(cmd->payload);
2977 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2978 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2980 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
2981 SILC_PACKET_COMMAND, cmd->packet->flags,
2982 tmpbuf->data, tmpbuf->len, TRUE);
2984 /* Reprocess this packet after received reply from router */
2985 silc_server_command_pending(server, SILC_COMMAND_INFO,
2986 silc_command_get_ident(cmd->payload),
2987 silc_server_command_info,
2988 silc_server_command_dup(cmd));
2989 cmd->pending = TRUE;
2990 silc_command_set_ident(cmd->payload, old_ident);
2991 silc_buffer_free(tmpbuf);
2996 silc_free(server_id);
2999 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3000 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3004 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
3006 server_info = entry->server_info;
3007 server_name = entry->server_name;
3009 /* Send the reply */
3010 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
3011 SILC_STATUS_OK, 0, ident, 3,
3012 2, idp->data, idp->len,
3014 strlen(server_name),
3017 strlen(server_info) : 0);
3018 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3019 packet->data, packet->len, FALSE);
3021 silc_buffer_free(packet);
3022 silc_buffer_free(idp);
3025 silc_server_command_free(cmd);
3028 /* Server side of command PING. This just replies to the ping. */
3030 SILC_SERVER_CMD_FUNC(ping)
3032 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3033 SilcServer server = cmd->server;
3038 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
3041 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
3043 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3044 SILC_STATUS_ERR_NO_SERVER_ID, 0);
3047 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
3051 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
3052 /* Send our reply */
3053 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3056 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3057 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3064 silc_server_command_free(cmd);
3067 /* Server side of command STATS. */
3069 SILC_SERVER_CMD_FUNC(stats)
3071 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3072 SilcServer server = cmd->server;
3073 SilcServerID *server_id;
3076 SilcBuffer packet, stats;
3077 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3080 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1);
3083 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3085 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3086 SILC_STATUS_ERR_NO_SERVER_ID, 0);
3089 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3093 /* The ID must be ours */
3094 if (!SILC_ID_SERVER_COMPARE(server->id, server_id)) {
3095 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3096 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3097 silc_free(server_id);
3100 silc_free(server_id);
3102 /* If we are router then just send everything we got. If we are normal
3103 server then we'll send this to our router to get all the latest
3104 statistical information. */
3105 if (!cmd->pending && server->server_type != SILC_ROUTER &&
3106 !server->standalone) {
3107 /* Send request to our router */
3108 SilcBuffer idp = silc_id_payload_encode(server->router->id,
3110 packet = silc_command_payload_encode_va(SILC_COMMAND_STATS,
3111 ++server->cmd_ident, 1,
3112 1, idp->data, idp->len);
3113 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
3114 SILC_PACKET_COMMAND, 0, packet->data,
3115 packet->len, FALSE);
3117 /* Reprocess this packet after received reply from router */
3118 silc_server_command_pending(server, SILC_COMMAND_STATS,
3120 silc_server_command_stats,
3121 silc_server_command_dup(cmd));
3122 cmd->pending = TRUE;
3123 silc_buffer_free(packet);
3124 silc_buffer_free(idp);
3128 /* Send our reply to sender */
3129 uptime = time(NULL) - server->starttime;
3131 stats = silc_buffer_alloc_size(60);
3132 silc_buffer_format(stats,
3133 SILC_STR_UI_INT(server->starttime),
3134 SILC_STR_UI_INT(uptime),
3135 SILC_STR_UI_INT(server->stat.my_clients),
3136 SILC_STR_UI_INT(server->stat.my_channels),
3137 SILC_STR_UI_INT(server->stat.my_server_ops),
3138 SILC_STR_UI_INT(server->stat.my_router_ops),
3139 SILC_STR_UI_INT(server->stat.cell_clients),
3140 SILC_STR_UI_INT(server->stat.cell_channels),
3141 SILC_STR_UI_INT(server->stat.cell_servers),
3142 SILC_STR_UI_INT(server->stat.clients),
3143 SILC_STR_UI_INT(server->stat.channels),
3144 SILC_STR_UI_INT(server->stat.servers),
3145 SILC_STR_UI_INT(server->stat.routers),
3146 SILC_STR_UI_INT(server->stat.server_ops),
3147 SILC_STR_UI_INT(server->stat.router_ops),
3150 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_STATS,
3151 SILC_STATUS_OK, 0, ident, 2,
3153 3, stats->data, stats->len);
3154 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
3155 0, packet->data, packet->len, FALSE);
3156 silc_buffer_free(packet);
3157 silc_buffer_free(stats);
3160 silc_server_command_free(cmd);
3163 /* Internal routine to join channel. The channel sent to this function
3164 has been either created or resolved from ID lists. This joins the sent
3165 client to the channel. */
3167 static void silc_server_command_join_channel(SilcServer server,
3168 SilcServerCommandContext cmd,
3169 SilcChannelEntry channel,
3170 SilcClientID *client_id,
3174 const unsigned char *auth,
3175 SilcUInt32 auth_len)
3177 SilcSocketConnection sock = cmd->sock;
3179 SilcUInt32 tmp_len, user_count;
3180 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
3181 SilcClientEntry client;
3182 SilcChannelClientEntry chl;
3183 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
3184 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3185 char check[512], check2[512];
3186 bool founder = FALSE;
3188 unsigned char *fkey = NULL;
3189 SilcUInt32 fkey_len = 0;
3191 SILC_LOG_DEBUG(("Joining client to channel"));
3196 /* Get the client entry */
3197 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3198 client = (SilcClientEntry)sock->user_data;
3200 client = silc_server_get_client_resolve(server, client_id, FALSE,
3207 silc_server_command_send_status_reply(
3208 cmd, SILC_COMMAND_JOIN,
3209 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3213 /* The client info is being resolved. Reprocess this packet after
3214 receiving the reply to the query. */
3215 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
3217 silc_server_command_join,
3218 silc_server_command_dup(cmd));
3219 cmd->pending = TRUE;
3223 cmd->pending = FALSE;
3227 * Check founder auth payload if provided. If client can gain founder
3228 * privileges it can override various conditions on joining the channel,
3229 * and can have directly the founder mode set on the channel.
3231 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3232 SilcIDListData idata = (SilcIDListData)client;
3233 SilcChannelClientEntry chl2;
3234 SilcHashTableList htl;
3236 if (channel->founder_key && idata->public_key &&
3237 silc_pkcs_public_key_compare(channel->founder_key,
3238 idata->public_key)) {
3239 /* Check whether the client is to become founder */
3240 if (silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
3241 channel->founder_key, 0, server->sha1hash,
3242 client->id, SILC_ID_CLIENT)) {
3244 /* There cannot be anyone else as founder on the channel now. This
3245 client is definitely the founder due to this authentication */
3246 silc_hash_table_list(channel->user_list, &htl);
3247 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
3248 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
3249 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3250 silc_server_force_cumode_change(server, NULL, channel, chl2,
3254 silc_hash_table_list_reset(&htl);
3256 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3263 * Check channel modes
3267 memset(check, 0, sizeof(check));
3268 memset(check2, 0, sizeof(check2));
3269 strncat(check, client->nickname, strlen(client->nickname));
3270 strncat(check, "!", 1);
3271 strncat(check, client->username, strlen(client->username));
3272 if (!strchr(client->username, '@')) {
3273 strncat(check, "@", 1);
3274 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3277 strncat(check2, client->nickname, strlen(client->nickname));
3278 if (!strchr(client->nickname, '@')) {
3279 strncat(check2, "@", 1);
3280 strncat(check2, server->server_name, strlen(server->server_name));
3282 strncat(check2, "!", 1);
3283 strncat(check2, client->username, strlen(client->username));
3284 if (!strchr(client->username, '@')) {
3285 strncat(check2, "@", 1);
3286 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3289 /* Check invite list if channel is invite-only channel */
3290 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3291 if (!channel->invite_list ||
3292 (!silc_string_match(channel->invite_list, check) &&
3293 !silc_string_match(channel->invite_list, check2))) {
3294 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3295 SILC_STATUS_ERR_NOT_INVITED, 0);
3300 /* Check ban list if it exists. If the client's nickname, server,
3301 username and/or hostname is in the ban list the access to the
3302 channel is denied. */
3303 if (channel->ban_list) {
3304 if (silc_string_match(channel->ban_list, check) ||
3305 silc_string_match(channel->ban_list, check2)) {
3306 silc_server_command_send_status_reply(
3307 cmd, SILC_COMMAND_JOIN,
3308 SILC_STATUS_ERR_BANNED_FROM_CHANNEL, 0);
3313 /* Check user count limit if set. */
3314 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3315 if (silc_hash_table_count(channel->user_list) + 1 >
3316 channel->user_limit) {
3317 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3318 SILC_STATUS_ERR_CHANNEL_IS_FULL,
3325 /* Check the channel passphrase if set. */
3326 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3327 /* Get passphrase */
3328 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3330 passphrase = silc_memdup(tmp, tmp_len);
3332 if (!passphrase || !channel->passphrase ||
3333 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3334 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3335 SILC_STATUS_ERR_BAD_PASSWORD, 0);
3341 * Client is allowed to join to the channel. Make it happen.
3344 /* Check whether the client already is on the channel */
3345 if (silc_server_client_on_channel(client, channel, NULL)) {
3346 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3347 SILC_STATUS_ERR_USER_ON_CHANNEL, 0);
3351 /* Generate new channel key as protocol dictates */
3353 if (!silc_server_create_channel_key(server, channel, 0))
3356 /* Send the channel key. This is broadcasted to the channel but is not
3357 sent to the client who is joining to the channel. */
3358 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3359 silc_server_send_channel_key(server, NULL, channel,
3360 server->server_type == SILC_ROUTER ?
3361 FALSE : !server->standalone);
3364 /* Join the client to the channel by adding it to channel's user list.
3365 Add also the channel to client entry's channels list for fast cross-
3367 chl = silc_calloc(1, sizeof(*chl));
3369 chl->client = client;
3370 chl->channel = channel;
3371 silc_hash_table_add(channel->user_list, client, chl);
3372 silc_hash_table_add(client->channels, channel, chl);
3373 channel->user_count++;
3374 channel->disabled = FALSE;
3376 /* Get users on the channel */
3377 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3380 /* Encode Client ID Payload of the original client who wants to join */
3381 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3383 /* Encode command reply packet */
3384 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3385 SILC_PUT32_MSB(channel->mode, mode);
3386 SILC_PUT32_MSB(created, tmp2);
3387 SILC_PUT32_MSB(user_count, tmp3);
3389 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3390 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3391 keyp = silc_channel_key_payload_encode(silc_id_get_len(channel->id,
3394 strlen(channel->channel_key->
3396 channel->channel_key->cipher->name,
3397 channel->key_len / 8, channel->key);
3401 if (channel->founder_key)
3402 fkey = silc_pkcs_public_key_encode(channel->founder_key, &fkey_len);
3405 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3406 SILC_STATUS_OK, 0, ident, 14,
3407 2, channel->channel_name,
3408 strlen(channel->channel_name),
3409 3, chidp->data, chidp->len,
3410 4, clidp->data, clidp->len,
3413 7, keyp ? keyp->data : NULL,
3414 keyp ? keyp->len : 0,
3415 8, channel->ban_list,
3417 strlen(channel->ban_list) : 0,
3418 9, channel->invite_list,
3419 channel->invite_list ?
3420 strlen(channel->invite_list) : 0,
3423 strlen(channel->topic) : 0,
3424 11, silc_hmac_get_name(channel->hmac),
3425 strlen(silc_hmac_get_name(channel->
3428 13, user_list->data, user_list->len,
3429 14, mode_list->data,
3431 15, fkey, fkey_len);
3433 /* Send command reply */
3434 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3435 reply->data, reply->len, FALSE);
3437 /* Send JOIN notify to locally connected clients on the channel. If
3438 we are normal server then router will send or have sent JOIN notify
3439 already. However since we've added the client already to our channel
3440 we'll ignore it (in packet_receive.c) so we must send it here. If
3441 we are router then this will send it to local clients and local
3443 SILC_LOG_DEBUG(("Send JOIN notify to channel"));
3444 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3445 SILC_NOTIFY_TYPE_JOIN, 2,
3446 clidp->data, clidp->len,
3447 chidp->data, chidp->len);
3449 /* Update statistics */
3450 server->stat.my_chanclients++;
3451 if (server->server_type == SILC_ROUTER) {
3452 server->stat.cell_chanclients++;
3453 server->stat.chanclients++;
3456 if (!cmd->pending) {
3457 /* Send JOIN notify packet to our primary router */
3458 silc_server_send_notify_join(server, SILC_PRIMARY_ROUTE(server),
3459 SILC_BROADCAST(server), channel, client->id);
3462 /* Distribute the channel key to all backup routers. */
3463 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3464 keyp->data, keyp->len, FALSE, TRUE);
3466 /* If client became founder by providing correct founder auth data
3467 notify the mode change to the channel. */
3469 SILC_PUT32_MSB(chl->mode, mode);
3470 SILC_LOG_DEBUG(("Send CUMODE_CHANGE notify to channel"));
3471 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3472 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
3473 clidp->data, clidp->len,
3474 mode, 4, clidp->data, clidp->len,
3479 /* Set CUMODE notify type to network */
3481 silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
3482 SILC_BROADCAST(server), channel,
3483 chl->mode, client->id, SILC_ID_CLIENT,
3484 client->id, channel->founder_key);
3486 silc_buffer_free(reply);
3487 silc_buffer_free(clidp);
3488 silc_buffer_free(chidp);
3489 silc_buffer_free(keyp);
3490 silc_buffer_free(user_list);
3491 silc_buffer_free(mode_list);
3495 silc_free(passphrase);
3498 /* Server side of command JOIN. Joins client into requested channel. If
3499 the channel does not exist it will be created. */
3501 SILC_SERVER_CMD_FUNC(join)
3503 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3504 SilcServer server = cmd->server;
3505 unsigned char *auth;
3506 SilcUInt32 tmp_len, auth_len;
3507 char *tmp, *channel_name = NULL, *cipher, *hmac;
3508 SilcChannelEntry channel;
3509 SilcUInt32 umode = 0;
3510 bool created = FALSE, create_key = TRUE;
3511 SilcClientID *client_id;
3513 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3515 /* Get channel name */
3516 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3518 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3519 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3526 channel_name[255] = '\0';
3528 if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
3529 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3530 SILC_STATUS_ERR_BAD_CHANNEL, 0);
3534 /* Get Client ID of the client who is joining to the channel */
3535 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3537 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3538 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3542 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3544 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3545 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3550 /* Get cipher, hmac name and auth payload */
3551 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3552 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3553 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3555 /* See if the channel exists */
3556 channel = silc_idlist_find_channel_by_name(server->local_list,
3557 channel_name, NULL);
3559 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3560 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3561 silc_free(client_id);
3562 client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
3565 (channel->disabled && server->server_type != SILC_ROUTER)) {
3566 /* Channel not found */
3568 /* If we are standalone server we don't have a router, we just create
3569 the channel by ourselves. */
3570 if (server->standalone) {
3571 channel = silc_server_create_new_channel(server, server->id, cipher,
3572 hmac, channel_name, TRUE);
3574 silc_server_command_send_status_reply(
3575 cmd, SILC_COMMAND_JOIN,
3576 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
3578 silc_free(client_id);
3582 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3588 /* The channel does not exist on our server. If we are normal server
3589 we will send JOIN command to our router which will handle the
3590 joining procedure (either creates the channel if it doesn't exist
3591 or joins the client to it). */
3592 if (server->server_type != SILC_ROUTER) {
3594 SilcUInt16 old_ident;
3596 /* If this is pending command callback then we've resolved
3597 it and it didn't work, return since we've notified the
3598 client already in the command reply callback. */
3600 silc_free(client_id);
3604 old_ident = silc_command_get_ident(cmd->payload);
3605 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3606 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3608 /* Send JOIN command to our router */
3609 silc_server_packet_send(server, (SilcSocketConnection)
3610 SILC_PRIMARY_ROUTE(server),
3611 SILC_PACKET_COMMAND, cmd->packet->flags,
3612 tmpbuf->data, tmpbuf->len, TRUE);
3614 /* Reprocess this packet after received reply from router */
3615 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3616 silc_command_get_ident(cmd->payload),
3617 silc_server_command_join,
3618 silc_server_command_dup(cmd));
3619 cmd->pending = TRUE;
3620 silc_command_set_ident(cmd->payload, old_ident);
3621 silc_buffer_free(tmpbuf);
3622 silc_free(client_id);
3626 /* We are router and the channel does not seem exist so we will check
3627 our global list as well for the channel. */
3628 channel = silc_idlist_find_channel_by_name(server->global_list,
3629 channel_name, NULL);
3631 /* Channel really does not exist, create it */
3632 channel = silc_server_create_new_channel(server, server->id, cipher,
3633 hmac, channel_name, TRUE);
3635 silc_server_command_send_status_reply(
3636 cmd, SILC_COMMAND_JOIN,
3637 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
3638 silc_free(client_id);
3642 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3650 /* Channel not found */
3652 /* If the command came from router and we are normal server then
3653 something went wrong with the joining as the channel was not found.
3654 We can't do anything else but ignore this. */
3655 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3656 server->server_type != SILC_ROUTER) {
3657 silc_free(client_id);
3661 /* We are router and the channel does not seem exist so we will check
3662 our global list as well for the channel. */
3663 channel = silc_idlist_find_channel_by_name(server->global_list,
3664 channel_name, NULL);
3666 /* Channel really does not exist, create it */
3667 channel = silc_server_create_new_channel(server, server->id, cipher,
3668 hmac, channel_name, TRUE);
3670 silc_server_command_send_status_reply(
3671 cmd, SILC_COMMAND_JOIN,
3672 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
3673 silc_free(client_id);
3677 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3684 /* Check whether the channel was created by our router */
3685 if (cmd->pending && context2) {
3686 SilcServerCommandReplyContext reply = context2;
3688 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3689 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3690 SILC_GET32_MSB(created, tmp);
3691 if (silc_argument_get_arg_type(reply->args, 7, NULL))
3692 create_key = FALSE; /* Router returned the key already */
3694 if (silc_command_get_status(reply->payload, NULL, NULL) &&
3695 channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3696 /* Save channel passphrase, if user provided it successfully */
3699 pa = silc_argument_get_arg_type(cmd->args, 3, &pa_len);
3701 silc_free(channel->passphrase);
3702 channel->passphrase = silc_memdup(pa, pa_len);
3707 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
3708 !channel->disabled && !silc_hash_table_count(channel->user_list))
3712 /* If the channel does not have global users and is also empty the client
3713 will be the channel founder and operator. */
3714 if (!channel->disabled &&
3715 !channel->global_users && !silc_hash_table_count(channel->user_list))
3716 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3718 /* Join to the channel */
3719 silc_server_command_join_channel(server, cmd, channel, client_id,
3720 created, create_key, umode,
3723 silc_free(client_id);
3726 silc_server_command_free(cmd);
3729 /* Server side of command MOTD. Sends server's current "message of the
3730 day" to the client. */
3732 SILC_SERVER_CMD_FUNC(motd)
3734 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3735 SilcServer server = cmd->server;
3736 SilcBuffer packet, idp;
3737 char *motd, *dest_server;
3738 SilcUInt32 motd_len;
3739 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3741 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3743 /* Get server name */
3744 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3746 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3747 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3751 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3754 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3756 if (server->config && server->config->server_info &&
3757 server->config->server_info->motd_file) {
3759 motd = silc_file_readfile(server->config->server_info->motd_file,
3765 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3772 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3778 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3779 packet->data, packet->len, FALSE);
3780 silc_buffer_free(packet);
3781 silc_buffer_free(idp);
3783 SilcServerEntry entry;
3785 /* Check whether we have this server cached */
3786 entry = silc_idlist_find_server_by_name(server->global_list,
3787 dest_server, TRUE, NULL);
3789 entry = silc_idlist_find_server_by_name(server->local_list,
3790 dest_server, TRUE, NULL);
3793 if (server->server_type != SILC_SERVER && !cmd->pending &&
3794 entry && !entry->motd) {
3795 /* Send to the server */
3797 SilcUInt16 old_ident;
3799 old_ident = silc_command_get_ident(cmd->payload);
3800 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3801 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3803 silc_server_packet_send(server, entry->connection,
3804 SILC_PACKET_COMMAND, cmd->packet->flags,
3805 tmpbuf->data, tmpbuf->len, TRUE);
3807 /* Reprocess this packet after received reply from router */
3808 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3809 silc_command_get_ident(cmd->payload),
3810 silc_server_command_motd,
3811 silc_server_command_dup(cmd));
3812 cmd->pending = TRUE;
3813 silc_command_set_ident(cmd->payload, old_ident);
3814 silc_buffer_free(tmpbuf);
3818 if (!entry && !cmd->pending && !server->standalone) {
3819 /* Send to the primary router */
3821 SilcUInt16 old_ident;
3823 old_ident = silc_command_get_ident(cmd->payload);
3824 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3825 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3827 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
3828 SILC_PACKET_COMMAND, cmd->packet->flags,
3829 tmpbuf->data, tmpbuf->len, TRUE);
3831 /* Reprocess this packet after received reply from router */
3832 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3833 silc_command_get_ident(cmd->payload),
3834 silc_server_command_motd,
3835 silc_server_command_dup(cmd));
3836 cmd->pending = TRUE;
3837 silc_command_set_ident(cmd->payload, old_ident);
3838 silc_buffer_free(tmpbuf);
3843 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3844 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3848 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3849 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3850 SILC_STATUS_OK, 0, ident, 2,
3854 strlen(entry->motd) : 0);
3855 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3856 packet->data, packet->len, FALSE);
3857 silc_buffer_free(packet);
3858 silc_buffer_free(idp);
3862 silc_server_command_free(cmd);
3865 /* Server side of command UMODE. Client can use this command to set/unset
3866 user mode. Client actually cannot set itself to be as server/router
3867 operator so this can be used only to unset the modes. */
3869 SILC_SERVER_CMD_FUNC(umode)
3871 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3872 SilcServer server = cmd->server;
3873 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3875 unsigned char *tmp_mask, m[4];
3876 SilcUInt32 mask = 0;
3877 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3878 bool set_mask = FALSE;
3880 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3883 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2);
3885 /* Get the client's mode mask */
3886 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3888 SILC_GET32_MSB(mask, tmp_mask);
3893 /* Check that mode changing is allowed. */
3894 if (!silc_server_check_umode_rights(server, client, mask)) {
3895 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3896 SILC_STATUS_ERR_PERM_DENIED, 0);
3900 /* Anonymous mode cannot be set by client */
3901 if (mask & SILC_UMODE_ANONYMOUS) {
3902 if (!(client->mode & SILC_UMODE_ANONYMOUS)) {
3903 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3904 SILC_STATUS_ERR_PERM_DENIED, 0);
3908 if (client->mode & SILC_UMODE_ANONYMOUS) {
3909 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3910 SILC_STATUS_ERR_PERM_DENIED, 0);
3915 /* Update statistics */
3916 if (mask & SILC_UMODE_GONE) {
3917 if (!(client->mode & SILC_UMODE_GONE))
3918 server->stat.my_aways++;
3920 if (client->mode & SILC_UMODE_GONE)
3921 server->stat.my_aways--;
3924 /* Change the mode */
3925 client->mode = mask;
3927 /* Send UMODE change to primary router */
3928 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
3929 SILC_BROADCAST(server), client->id,
3932 /* Check if anyone is watching this nickname */
3933 if (server->server_type == SILC_ROUTER)
3934 silc_server_check_watcher_list(server, client, NULL,
3935 SILC_NOTIFY_TYPE_UMODE_CHANGE);
3938 /* Send command reply to sender */
3939 SILC_PUT32_MSB(client->mode, m);
3940 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3941 SILC_STATUS_OK, 0, ident, 1,
3943 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3944 packet->data, packet->len, FALSE);
3945 silc_buffer_free(packet);
3948 silc_server_command_free(cmd);
3951 /* Server side command of CMODE. Changes channel mode */
3953 SILC_SERVER_CMD_FUNC(cmode)
3955 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3956 SilcServer server = cmd->server;
3957 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3958 SilcIDListData idata = (SilcIDListData)client;
3959 SilcChannelID *channel_id = NULL;
3960 SilcChannelEntry channel;
3961 SilcChannelClientEntry chl;
3962 SilcBuffer packet, cidp;
3963 unsigned char *tmp, *tmp_id, *tmp_mask;
3964 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3965 SilcUInt32 mode_mask = 0, old_mask = 0, tmp_len, tmp_len2;
3966 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3967 bool set_mask = FALSE;
3968 SilcPublicKey founder_key = NULL;
3969 unsigned char *fkey = NULL;
3970 SilcUInt32 fkey_len = 0;
3972 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 7);
3974 /* Get Channel ID */
3975 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3977 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3978 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3979 silc_server_command_free(cmd);
3982 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
3984 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3985 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3986 silc_server_command_free(cmd);
3990 /* Get channel entry */
3991 channel = silc_idlist_find_channel_by_id(server->local_list,
3994 channel = silc_idlist_find_channel_by_id(server->global_list,
3997 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3998 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4000 silc_free(channel_id);
4001 silc_server_command_free(cmd);
4005 old_mask = channel->mode;
4007 /* Get the channel mode mask */
4008 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4010 SILC_GET32_MSB(mode_mask, tmp_mask);
4014 /* Check whether this client is on the channel */
4015 if (!silc_server_client_on_channel(client, channel, &chl)) {
4016 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4017 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4021 /* Check that client has rights to change any requested channel modes */
4022 if (set_mask && !silc_server_check_cmode_rights(server, channel, chl,
4024 SILC_LOG_DEBUG(("Client does not have rights to change mode"));
4025 silc_server_command_send_status_reply(
4026 cmd, SILC_COMMAND_CMODE,
4027 (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) ?
4028 SILC_STATUS_ERR_NO_CHANNEL_PRIV :
4029 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV), 0);
4033 /* If mode mask was not sent as argument then merely return the current
4034 mode mask to the sender. */
4037 SILC_PUT32_MSB(channel->mode, m);
4038 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4039 SILC_STATUS_OK, 0, ident, 2,
4040 2, tmp_id, tmp_len2,
4042 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4043 packet->data, packet->len, FALSE);
4044 silc_buffer_free(packet);
4049 * Check the modes. Modes that requires nothing special operation are
4053 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
4054 /* Channel uses private keys to protect traffic. Client(s) has set the
4055 key locally they want to use, server does not know that key. */
4056 /* Nothing interesting to do here */
4058 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
4059 /* The mode is removed and we need to generate and distribute
4060 new channel key. Clients are not using private channel keys
4061 anymore after this. */
4063 /* Re-generate channel key */
4064 if (!silc_server_create_channel_key(server, channel, 0))
4067 /* Send the channel key. This sends it to our local clients and if
4068 we are normal server to our router as well. */
4069 silc_server_send_channel_key(server, NULL, channel,
4070 server->server_type == SILC_ROUTER ?
4071 FALSE : !server->standalone);
4073 cipher = channel->channel_key->cipher->name;
4074 hmac = (char *)silc_hmac_get_name(channel->hmac);
4078 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
4079 /* User limit is set on channel */
4080 SilcUInt32 user_limit;
4082 /* Get user limit */
4083 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
4085 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
4086 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4087 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4091 SILC_GET32_MSB(user_limit, tmp);
4092 channel->user_limit = user_limit;
4095 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
4096 /* User limit mode is unset. Remove user limit */
4097 channel->user_limit = 0;
4100 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
4101 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
4102 /* Passphrase has been set to channel */
4104 /* Get the passphrase */
4105 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
4107 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4108 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4112 /* Save the passphrase */
4113 passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
4116 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
4117 /* Passphrase mode is unset. remove the passphrase */
4118 silc_free(channel->passphrase);
4119 channel->passphrase = NULL;
4123 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
4124 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
4125 /* Cipher to use protect the traffic */
4126 SilcCipher newkey, oldkey;
4129 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
4131 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4132 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4136 /* Delete old cipher and allocate the new one */
4137 if (!silc_cipher_alloc(cipher, &newkey)) {
4138 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4139 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4143 oldkey = channel->channel_key;
4144 channel->channel_key = newkey;
4146 /* Re-generate channel key */
4147 if (!silc_server_create_channel_key(server, channel, 0)) {
4148 /* We don't have new key, revert to old one */
4149 channel->channel_key = oldkey;
4153 /* Remove old channel key for good */
4154 silc_cipher_free(oldkey);
4156 /* Send the channel key. This sends it to our local clients and if
4157 we are normal server to our router as well. */
4158 silc_server_send_channel_key(server, NULL, channel,
4159 server->server_type == SILC_ROUTER ?
4160 FALSE : !server->standalone);
4163 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
4164 /* Cipher mode is unset. Remove the cipher and revert back to
4166 SilcCipher newkey, oldkey;
4167 cipher = channel->cipher;
4169 /* Delete old cipher and allocate default one */
4170 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
4171 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4172 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4176 oldkey = channel->channel_key;
4177 channel->channel_key = newkey;
4179 /* Re-generate channel key */
4180 if (!silc_server_create_channel_key(server, channel, 0)) {
4181 /* We don't have new key, revert to old one */
4182 channel->channel_key = oldkey;
4186 /* Remove old channel key for good */
4187 silc_cipher_free(oldkey);
4189 /* Send the channel key. This sends it to our local clients and if
4190 we are normal server to our router as well. */
4191 silc_server_send_channel_key(server, NULL, channel,
4192 server->server_type == SILC_ROUTER ?
4193 FALSE : !server->standalone);
4197 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
4198 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
4199 /* HMAC to use protect the traffic */
4200 unsigned char hash[32];
4204 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4206 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4207 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4211 /* Delete old hmac and allocate the new one */
4212 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4213 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4214 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4218 silc_hmac_free(channel->hmac);
4219 channel->hmac = newhmac;
4221 /* Set the HMAC key out of current channel key. The client must do
4223 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4224 channel->key_len / 8, hash);
4225 silc_hmac_set_key(channel->hmac, hash,
4226 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4227 memset(hash, 0, sizeof(hash));
4230 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4231 /* Hmac mode is unset. Remove the hmac and revert back to
4234 unsigned char hash[32];
4235 hmac = channel->hmac_name;
4237 /* Delete old hmac and allocate default one */
4238 silc_hmac_free(channel->hmac);
4239 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4240 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4241 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4245 silc_hmac_free(channel->hmac);
4246 channel->hmac = newhmac;
4248 /* Set the HMAC key out of current channel key. The client must do
4250 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4251 channel->key_len / 8,
4253 silc_hmac_set_key(channel->hmac, hash,
4254 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4255 memset(hash, 0, sizeof(hash));
4259 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4260 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4261 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4262 /* Set the founder authentication */
4263 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4265 silc_server_command_send_status_reply(
4266 cmd, SILC_COMMAND_CMODE,
4267 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4271 /* Verify the payload before setting the mode */
4272 if (!silc_auth_verify_data(tmp, tmp_len, SILC_AUTH_PUBLIC_KEY,
4273 idata->public_key, 0, server->sha1hash,
4274 client->id, SILC_ID_CLIENT)) {
4275 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4276 SILC_STATUS_ERR_AUTH_FAILED,
4281 /* Save the public key */
4282 channel->founder_key = silc_pkcs_public_key_copy(idata->public_key);
4283 if (!channel->founder_key) {
4284 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4285 SILC_STATUS_ERR_AUTH_FAILED,
4290 founder_key = channel->founder_key;
4291 fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
4293 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4294 SILC_STATUS_ERR_AUTH_FAILED,
4296 silc_pkcs_public_key_free(channel->founder_key);
4297 channel->founder_key = NULL;
4303 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4304 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4305 if (channel->founder_key)
4306 silc_pkcs_public_key_free(channel->founder_key);
4307 channel->founder_key = NULL;
4312 /* Finally, set the mode */
4313 old_mask = channel->mode = mode_mask;
4315 /* Send CMODE_CHANGE notify. */
4316 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4317 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4318 SILC_NOTIFY_TYPE_CMODE_CHANGE, 6,
4319 cidp->data, cidp->len,
4321 cipher, cipher ? strlen(cipher) : 0,
4322 hmac, hmac ? strlen(hmac) : 0,
4323 passphrase, passphrase ?
4324 strlen(passphrase) : 0,
4327 /* Set CMODE notify type to network */
4328 silc_server_send_notify_cmode(server, SILC_PRIMARY_ROUTE(server),
4329 SILC_BROADCAST(server), channel,
4330 mode_mask, client->id, SILC_ID_CLIENT,
4331 cipher, hmac, passphrase, founder_key);
4333 /* Send command reply to sender */
4334 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4335 SILC_STATUS_OK, 0, ident, 2,
4336 2, tmp_id, tmp_len2,
4338 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4339 packet->data, packet->len, FALSE);
4341 silc_buffer_free(packet);
4342 silc_buffer_free(cidp);
4345 channel->mode = old_mask;
4347 silc_free(channel_id);
4348 silc_server_command_free(cmd);
4351 /* Server side of CUMODE command. Changes client's mode on a channel. */
4353 SILC_SERVER_CMD_FUNC(cumode)
4355 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4356 SilcServer server = cmd->server;
4357 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4358 SilcIDListData idata = (SilcIDListData)client;
4359 SilcChannelID *channel_id;
4360 SilcClientID *client_id;
4361 SilcChannelEntry channel;
4362 SilcClientEntry target_client;
4363 SilcChannelClientEntry chl;
4364 SilcBuffer packet, idp;
4365 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4366 SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4368 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4369 SilcPublicKey founder_key = NULL;
4370 unsigned char *fkey = NULL;
4371 SilcUInt32 fkey_len = 0;
4373 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4375 /* Get Channel ID */
4376 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4378 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4379 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4382 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
4384 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4385 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4389 /* Get channel entry */
4390 channel = silc_idlist_find_channel_by_id(server->local_list,
4393 channel = silc_idlist_find_channel_by_id(server->global_list,
4396 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4397 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4403 /* Check whether sender is on the channel */
4404 if (!silc_server_client_on_channel(client, channel, &chl)) {
4405 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4406 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4409 sender_mask = chl->mode;
4411 /* Get the target client's channel mode mask */
4412 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4414 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4415 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4419 SILC_GET32_MSB(target_mask, tmp_mask);
4421 /* Get target Client ID */
4422 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4424 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4425 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4428 client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
4430 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4431 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4435 /* Get target client's entry */
4436 target_client = silc_idlist_find_client_by_id(server->local_list,
4437 client_id, TRUE, NULL);
4438 if (!target_client) {
4439 target_client = silc_idlist_find_client_by_id(server->global_list,
4440 client_id, TRUE, NULL);
4443 if (target_client != client &&
4444 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4445 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4446 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4447 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
4451 /* Check whether target client is on the channel */
4452 if (target_client != client) {
4453 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4454 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4455 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL, 0);
4464 /* If the target client is founder, no one else can change their mode
4466 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4467 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4468 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
4473 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4474 if (target_client != client) {
4475 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4476 SILC_STATUS_ERR_NOT_YOU, 0);
4480 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4481 /* The client tries to claim the founder rights. */
4482 unsigned char *tmp_auth;
4483 SilcUInt32 tmp_auth_len;
4484 SilcChannelClientEntry chl2;
4485 SilcHashTableList htl;
4487 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4488 !channel->founder_key || !idata->public_key ||
4489 !silc_pkcs_public_key_compare(channel->founder_key,
4490 idata->public_key)) {
4491 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4492 SILC_STATUS_ERR_AUTH_FAILED, 0);
4496 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4498 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4499 SILC_STATUS_ERR_AUTH_FAILED, 0);
4503 /* Verify the authentication payload */
4504 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len, SILC_AUTH_PUBLIC_KEY,
4505 channel->founder_key, 0, server->sha1hash,
4506 client->id, SILC_ID_CLIENT)) {
4507 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4508 SILC_STATUS_ERR_AUTH_FAILED, 0);
4513 founder_key = channel->founder_key;
4514 fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
4516 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4517 SILC_STATUS_ERR_AUTH_FAILED, 0);
4521 /* There cannot be anyone else as founder on the channel now. This
4522 client is definitely the founder due to this authentication */
4523 silc_hash_table_list(channel->user_list, &htl);
4524 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
4525 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
4526 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4527 silc_server_force_cumode_change(server, NULL, channel, chl2,
4531 silc_hash_table_list_reset(&htl);
4533 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4536 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4537 if (target_client == client) {
4538 /* Remove channel founder rights from itself */
4539 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4542 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4543 SILC_STATUS_ERR_NOT_YOU, 0);
4549 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4550 /* Promote to operator */
4551 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4552 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4553 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4554 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4555 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
4560 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4564 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4565 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4566 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4567 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4568 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
4573 /* Demote to normal user */
4574 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4579 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4580 if (target_client != client) {
4581 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4582 SILC_STATUS_ERR_NOT_YOU, 0);
4586 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
4587 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4591 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4592 if (target_client != client) {
4593 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4594 SILC_STATUS_ERR_NOT_YOU, 0);
4598 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4603 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4604 if (target_client != client) {
4605 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4606 SILC_STATUS_ERR_NOT_YOU, 0);
4610 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)) {
4611 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4615 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4616 if (target_client != client) {
4617 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4618 SILC_STATUS_ERR_NOT_YOU, 0);
4622 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4627 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4628 if (target_client != client) {
4629 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4630 SILC_STATUS_ERR_NOT_YOU, 0);
4634 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)) {
4635 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4639 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4640 if (target_client != client) {
4641 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4642 SILC_STATUS_ERR_NOT_YOU, 0);
4646 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4651 if (target_mask & SILC_CHANNEL_UMODE_QUIET) {
4652 if (!(chl->mode & SILC_CHANNEL_UMODE_QUIET)) {
4653 if (client == target_client) {
4654 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4655 SILC_STATUS_ERR_PERM_DENIED, 0);
4658 chl->mode |= SILC_CHANNEL_UMODE_QUIET;
4662 if (chl->mode & SILC_CHANNEL_UMODE_QUIET) {
4663 if (client == target_client) {
4664 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4665 SILC_STATUS_ERR_PERM_DENIED, 0);
4668 chl->mode &= ~SILC_CHANNEL_UMODE_QUIET;
4673 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4674 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4676 /* Send notify to channel, notify only if mode was actually changed. */
4678 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4679 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
4680 idp->data, idp->len,
4685 /* Set CUMODE notify type to network */
4686 silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
4687 SILC_BROADCAST(server), channel,
4688 target_mask, client->id, SILC_ID_CLIENT,
4689 target_client->id, founder_key);
4692 /* Send command reply to sender */
4693 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4694 SILC_STATUS_OK, 0, ident, 3,
4696 3, tmp_ch_id, tmp_ch_len,
4697 4, tmp_id, tmp_len);
4698 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4699 packet->data, packet->len, FALSE);
4701 silc_buffer_free(packet);
4702 silc_free(channel_id);
4703 silc_free(client_id);
4704 silc_buffer_free(idp);
4708 silc_server_command_free(cmd);
4711 /* Server side of KICK command. Kicks client out of channel. */
4713 SILC_SERVER_CMD_FUNC(kick)
4715 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4716 SilcServer server = cmd->server;
4717 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4718 SilcClientEntry target_client;
4719 SilcChannelID *channel_id;
4720 SilcClientID *client_id;
4721 SilcChannelEntry channel;
4722 SilcChannelClientEntry chl;
4724 SilcUInt32 tmp_len, target_idp_len;
4725 unsigned char *tmp, *comment, *target_idp;
4727 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4729 /* Get Channel ID */
4730 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4732 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4733 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4736 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4738 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4739 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4743 /* Get channel entry */
4744 channel = silc_idlist_find_channel_by_id(server->local_list,
4747 channel = silc_idlist_find_channel_by_id(server->local_list,
4750 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4751 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4757 /* Check whether sender is on the channel */
4758 if (!silc_server_client_on_channel(client, channel, &chl)) {
4759 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4760 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4764 /* Check that the kicker is channel operator or channel founder */
4765 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
4766 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4767 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4768 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
4772 /* Get target Client ID */
4773 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4775 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4776 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4779 client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
4781 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4782 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4786 /* Get target client's entry */
4787 target_client = silc_idlist_find_client_by_id(server->local_list,
4788 client_id, TRUE, NULL);
4789 if (!target_client) {
4790 target_client = silc_idlist_find_client_by_id(server->global_list,
4791 client_id, TRUE, NULL);
4794 /* Check whether target client is on the channel */
4795 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4796 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4797 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL,
4802 /* Check that the target client is not channel founder. Channel founder
4803 cannot be kicked from the channel. */
4804 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4805 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4806 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
4813 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4817 /* Send command reply to sender */
4818 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4821 /* Send KICKED notify to local clients on the channel */
4822 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4823 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4824 SILC_NOTIFY_TYPE_KICKED, 3,
4825 target_idp, target_idp_len,
4826 comment, comment ? strlen(comment) : 0,
4827 idp->data, idp->len);
4828 silc_buffer_free(idp);
4830 /* Send KICKED notify to primary route */
4831 silc_server_send_notify_kicked(server, SILC_PRIMARY_ROUTE(server),
4832 SILC_BROADCAST(server), channel,
4833 target_client->id, client->id, comment);
4835 /* Remove the client from the channel. If the channel does not exist
4836 after removing the client then the client kicked itself off the channel
4837 and we don't have to send anything after that. */
4838 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4839 target_client, FALSE))
4842 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4843 /* Re-generate channel key */
4844 if (!silc_server_create_channel_key(server, channel, 0))
4847 /* Send the channel key to the channel. The key of course is not sent
4848 to the client who was kicked off the channel. */
4849 silc_server_send_channel_key(server, target_client->connection, channel,
4850 server->server_type == SILC_ROUTER ?
4851 FALSE : !server->standalone);
4855 silc_server_command_free(cmd);
4858 /* Server side of OPER command. Client uses this comand to obtain server
4859 operator privileges to this server/router. */
4861 SILC_SERVER_CMD_FUNC(oper)
4863 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4864 SilcServer server = cmd->server;
4865 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4866 unsigned char *username, *auth;
4868 SilcServerConfigAdmin *admin;
4869 SilcIDListData idata = (SilcIDListData)client;
4870 bool result = FALSE;
4871 SilcPublicKey cached_key;
4873 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4875 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4878 /* Get the username */
4879 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4881 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4882 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4887 /* Get the admin configuration */
4888 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4889 username, client->nickname);
4891 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4892 username, client->nickname);
4894 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4895 SILC_STATUS_ERR_AUTH_FAILED,
4901 /* Get the authentication payload */
4902 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4904 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4905 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4910 /* Verify the authentication data. If both passphrase and public key
4911 is set then try both of them. */
4912 if (admin->passphrase)
4913 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4914 admin->passphrase, admin->passphrase_len,
4915 idata->hash, client->id, SILC_ID_CLIENT);
4916 if (!result && admin->publickeys) {
4917 cached_key = silc_server_get_public_key(server, admin->publickeys);
4920 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4921 cached_key, 0, idata->hash,
4922 client->id, SILC_ID_CLIENT);
4925 /* Authentication failed */
4926 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4927 SILC_STATUS_ERR_AUTH_FAILED,
4932 /* Client is now server operator */
4933 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4935 /* Update statistics */
4936 if (SILC_IS_LOCAL(client))
4937 server->stat.my_server_ops++;
4938 if (server->server_type == SILC_ROUTER)
4939 server->stat.server_ops++;
4941 /* Send UMODE change to primary router */
4942 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
4943 SILC_BROADCAST(server), client->id,
4946 /* Check if anyone is watching this nickname */
4947 if (server->server_type == SILC_ROUTER)
4948 silc_server_check_watcher_list(server, client, NULL,
4949 SILC_NOTIFY_TYPE_UMODE_CHANGE);
4951 /* Send reply to the sender */
4952 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4956 silc_server_command_free(cmd);
4959 SILC_TASK_CALLBACK(silc_server_command_detach_cb)
4961 QuitInternal q = (QuitInternal)context;
4962 SilcClientID *client_id = (SilcClientID *)q->sock;
4963 SilcClientEntry client;
4964 SilcSocketConnection sock;
4966 client = silc_idlist_find_client_by_id(q->server->local_list, client_id,
4968 if (client && client->connection) {
4969 sock = client->connection;
4971 /* If there is pending outgoing data for the client then purge it
4972 to the network before closing connection. */
4973 silc_server_packet_queue_purge(q->server, sock);
4975 /* Close the connection on our side */
4976 client->router = NULL;
4977 client->connection = NULL;
4978 sock->user_data = NULL;
4979 silc_server_close_connection(q->server, sock);
4982 silc_free(client_id);
4986 SILC_TASK_CALLBACK(silc_server_command_detach_timeout)
4988 QuitInternal q = (QuitInternal)context;
4989 SilcClientID *client_id = (SilcClientID *)q->sock;
4990 SilcClientEntry client;
4992 client = silc_idlist_find_client_by_id(q->server->local_list, client_id,
4994 if (client && client->mode & SILC_UMODE_DETACHED) {
4995 SILC_LOG_DEBUG(("Detach timeout"));
4996 silc_server_free_client_data(q->server, NULL, client, TRUE,
5000 silc_free(client_id);
5004 /* Server side of DETACH command. Detached the client from the network
5005 by closing the connection but preserving the session. */
5007 SILC_SERVER_CMD_FUNC(detach)
5009 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5010 SilcServer server = cmd->server;
5011 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5014 if (server->config->detach_disabled) {
5015 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
5016 SILC_STATUS_ERR_UNKNOWN_COMMAND, 0);
5020 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5023 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
5025 /* Remove operator privileges, since the client may resume in some
5026 other server which to it does not have operator privileges. */
5027 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
5028 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
5030 /* Send the user mode notify to notify that client is detached */
5031 client->mode |= SILC_UMODE_DETACHED;
5032 client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
5033 client->last_command = 0;
5034 client->fast_command = 0;
5035 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
5036 SILC_BROADCAST(server), client->id,
5038 server->stat.my_detached++;
5040 /* Check if anyone is watching this nickname */
5041 if (server->server_type == SILC_ROUTER)
5042 silc_server_check_watcher_list(server, client, NULL,
5043 SILC_NOTIFY_TYPE_UMODE_CHANGE);
5045 q = silc_calloc(1, sizeof(*q));
5047 q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
5048 silc_schedule_task_add(server->schedule, 0, silc_server_command_detach_cb,
5049 q, 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
5051 if (server->config->detach_timeout) {
5052 q = silc_calloc(1, sizeof(*q));
5054 q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
5055 silc_schedule_task_add(server->schedule, 0,
5056 silc_server_command_detach_timeout,
5057 q, server->config->detach_timeout * 60,
5058 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
5061 /* Send reply to the sender */
5062 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
5066 silc_server_command_free(cmd);
5069 /* Server side of WATCH command. */
5071 SILC_SERVER_CMD_FUNC(watch)
5073 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5074 SilcServer server = cmd->server;
5075 char *add_nick, *del_nick;
5076 SilcUInt32 add_nick_len, del_nick_len, tmp_len;
5078 unsigned char hash[16], *tmp;
5079 SilcClientEntry client;
5080 SilcClientID *client_id = NULL;
5082 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WATCH, cmd, 1, 3);
5084 if (server->server_type == SILC_SERVER && !server->standalone) {
5085 if (!cmd->pending) {
5086 /* Send the command to router */
5088 SilcUInt16 old_ident;
5090 old_ident = silc_command_get_ident(cmd->payload);
5091 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5092 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5094 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5095 SILC_PACKET_COMMAND, cmd->packet->flags,
5096 tmpbuf->data, tmpbuf->len, TRUE);
5098 /* Reprocess this packet after received reply from router */
5099 silc_server_command_pending(server, SILC_COMMAND_WATCH,
5100 silc_command_get_ident(cmd->payload),
5101 silc_server_command_watch,
5102 silc_server_command_dup(cmd));
5103 cmd->pending = TRUE;
5104 silc_command_set_ident(cmd->payload, old_ident);
5105 silc_buffer_free(tmpbuf);
5106 } else if (context2) {
5107 /* Received reply from router, just send same data to the client. */
5108 SilcServerCommandReplyContext reply = context2;
5110 silc_command_get_status(reply->payload, &status, NULL);
5111 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, status,
5118 /* We are router and keep the watch list for local cell */
5120 /* Get the client ID */
5121 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5123 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5124 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5128 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
5130 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5131 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5136 /* Get the client entry which must be in local list */
5137 client = silc_idlist_find_client_by_id(server->local_list,
5138 client_id, TRUE, NULL);
5140 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5141 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5147 add_nick = silc_argument_get_arg_type(cmd->args, 2, &add_nick_len);
5148 del_nick = silc_argument_get_arg_type(cmd->args, 3, &del_nick_len);
5149 if (!add_nick && !del_nick) {
5150 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5151 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5156 if (add_nick && add_nick_len > 128)
5157 add_nick[128] = '\0';
5158 if (del_nick && del_nick_len > 128)
5159 del_nick[128] = '\0';
5161 memset(nick, 0, sizeof(nick));
5163 /* Add new nickname to be watched in our cell */
5165 if (silc_server_name_bad_chars(add_nick, strlen(add_nick)) == TRUE) {
5166 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5167 SILC_STATUS_ERR_BAD_NICKNAME, 0);
5171 /* Hash the nick, we have the hash saved, not nicks because we can
5172 do one to one mapping to the nick from Client ID hash this way. */
5173 silc_to_lower(add_nick, nick, sizeof(nick) - 1);
5174 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
5176 /* Check whether this client is already watching this nickname */
5177 if (silc_hash_table_find_by_context(server->watcher_list, hash,
5179 /* Nickname is alredy being watched for this client */
5180 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5181 SILC_STATUS_ERR_NICKNAME_IN_USE,
5186 /* Get the nickname from the watcher list and use the same key in
5187 new entries as well. If key doesn't exist then create it. */
5188 if (!silc_hash_table_find(server->watcher_list, hash, (void **)&tmp, NULL))
5189 tmp = silc_memdup(hash, CLIENTID_HASH_LEN);
5191 /* Add the client to the watcher list with the specified nickname hash. */
5192 silc_hash_table_add(server->watcher_list, tmp, client);
5195 /* Delete nickname from watch list */
5197 if (silc_server_name_bad_chars(del_nick, strlen(del_nick)) == TRUE) {
5198 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5199 SILC_STATUS_ERR_BAD_NICKNAME, 0);
5203 /* Hash the nick, we have the hash saved, not nicks because we can
5204 do one to one mapping to the nick from Client ID hash this way. */
5205 silc_to_lower(del_nick, nick, sizeof(nick) - 1);
5206 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
5208 /* Check that this client is watching for this nickname */
5209 if (!silc_hash_table_find_by_context(server->watcher_list, hash,
5210 client, (void **)&tmp)) {
5211 /* Nickname is alredy being watched for this client */
5212 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5213 SILC_STATUS_ERR_NO_SUCH_NICK, 0);
5217 /* Delete the nickname from the watcher list. */
5218 silc_hash_table_del_by_context(server->watcher_list, hash, client);
5220 /* Now check whether there still exists entries with this key, if not
5221 then free the key to not leak memory. */
5222 if (!silc_hash_table_find(server->watcher_list, hash, NULL, NULL))
5226 /* Distribute the watch list to backup routers too */
5227 if (server->backup) {
5229 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5230 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5231 silc_server_backup_send(server, NULL, SILC_PACKET_COMMAND,
5232 cmd->packet->flags, tmpbuf->data, tmpbuf->len,
5234 silc_buffer_free(tmpbuf);
5237 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5241 silc_free(client_id);
5242 silc_server_command_free(cmd);
5245 /* Server side of SILCOPER command. Client uses this comand to obtain router
5246 operator privileges to this router. */
5248 SILC_SERVER_CMD_FUNC(silcoper)
5250 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5251 SilcServer server = cmd->server;
5252 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5253 unsigned char *username, *auth;
5255 SilcServerConfigAdmin *admin;
5256 SilcIDListData idata = (SilcIDListData)client;
5257 bool result = FALSE;
5258 SilcPublicKey cached_key;
5260 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
5262 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5265 if (server->server_type != SILC_ROUTER) {
5266 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5267 SILC_STATUS_ERR_AUTH_FAILED, 0);
5271 /* Get the username */
5272 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5274 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5275 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5280 /* Get the admin configuration */
5281 admin = silc_server_config_find_admin(server, cmd->sock->ip,
5282 username, client->nickname);
5284 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
5285 username, client->nickname);
5287 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5288 SILC_STATUS_ERR_AUTH_FAILED, 0);
5293 /* Get the authentication payload */
5294 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5296 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5297 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5302 /* Verify the authentication data. If both passphrase and public key
5303 is set then try both of them. */
5304 if (admin->passphrase)
5305 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
5306 admin->passphrase, admin->passphrase_len,
5307 idata->hash, client->id, SILC_ID_CLIENT);
5308 if (!result && admin->publickeys) {
5309 cached_key = silc_server_get_public_key(server, admin->publickeys);
5312 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
5313 cached_key, 0, idata->hash,
5314 client->id, SILC_ID_CLIENT);
5317 /* Authentication failed */
5318 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
5319 SILC_STATUS_ERR_AUTH_FAILED, 0);
5323 /* Client is now router operator */
5324 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
5326 /* Update statistics */
5327 if (SILC_IS_LOCAL(client))
5328 server->stat.my_router_ops++;
5329 if (server->server_type == SILC_ROUTER)
5330 server->stat.router_ops++;
5332 /* Send UMODE change to primary router */
5333 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
5334 SILC_BROADCAST(server), client->id,
5337 /* Check if anyone is watching this nickname */
5338 if (server->server_type == SILC_ROUTER)
5339 silc_server_check_watcher_list(server, client, NULL,
5340 SILC_NOTIFY_TYPE_UMODE_CHANGE);
5342 /* Send reply to the sender */
5343 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5347 silc_server_command_free(cmd);
5350 /* Server side of command BAN. This is used to manage the ban list of the
5351 channel. To add clients and remove clients from the ban list. */
5353 SILC_SERVER_CMD_FUNC(ban)
5355 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5356 SilcServer server = cmd->server;
5357 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5359 SilcChannelEntry channel;
5360 SilcChannelClientEntry chl;
5361 SilcChannelID *channel_id = NULL;
5362 unsigned char *id, *add, *del;
5363 SilcUInt32 id_len, tmp_len;
5364 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5366 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5369 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
5371 /* Get Channel ID */
5372 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
5374 channel_id = silc_id_payload_parse_id(id, id_len, NULL);
5376 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5377 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5382 /* Get channel entry. The server must know about the channel since the
5383 client is expected to be on the channel. */
5384 channel = silc_idlist_find_channel_by_id(server->local_list,
5387 channel = silc_idlist_find_channel_by_id(server->global_list,
5390 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5391 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5397 /* Check whether this client is on the channel */
5398 if (!silc_server_client_on_channel(client, channel, &chl)) {
5399 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5400 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5404 /* The client must be at least channel operator. */
5405 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
5406 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5407 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
5411 /* Get the new ban and add it to the ban list */
5412 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5414 if (!channel->ban_list)
5415 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
5417 channel->ban_list = silc_realloc(channel->ban_list,
5418 sizeof(*channel->ban_list) *
5420 strlen(channel->ban_list) + 2));
5421 if (add[tmp_len - 1] == ',')
5422 add[tmp_len - 1] = '\0';
5424 strncat(channel->ban_list, add, tmp_len);
5425 strncat(channel->ban_list, ",", 1);
5428 /* Get the ban to be removed and remove it from the list */
5429 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
5430 if (del && channel->ban_list) {
5431 char *start, *end, *n;
5433 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
5434 silc_free(channel->ban_list);
5435 channel->ban_list = NULL;
5437 start = strstr(channel->ban_list, del);
5438 if (start && strlen(start) >= tmp_len) {
5439 end = start + tmp_len;
5440 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
5441 strncat(n, channel->ban_list, start - channel->ban_list);
5442 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
5444 silc_free(channel->ban_list);
5445 channel->ban_list = n;
5450 /* Send the BAN notify type to our primary router. */
5452 silc_server_send_notify_ban(server, SILC_PRIMARY_ROUTE(server),
5453 SILC_BROADCAST(server), channel, add, del);
5455 /* Send the reply back to the client */
5457 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
5458 SILC_STATUS_OK, 0, ident, 2,
5460 3, channel->ban_list,
5462 strlen(channel->ban_list) -1 : 0);
5463 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5464 packet->data, packet->len, FALSE);
5466 silc_buffer_free(packet);
5469 silc_free(channel_id);
5470 silc_server_command_free(cmd);
5473 /* Server side command of LEAVE. Removes client from a channel. */
5475 SILC_SERVER_CMD_FUNC(leave)
5477 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5478 SilcServer server = cmd->server;
5479 SilcSocketConnection sock = cmd->sock;
5480 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
5481 SilcChannelID *id = NULL;
5482 SilcChannelEntry channel;
5486 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
5488 /* Get Channel ID */
5489 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
5491 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5492 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5495 id = silc_id_payload_parse_id(tmp, len, NULL);
5497 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5498 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5502 /* Get channel entry */
5503 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5505 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5507 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5508 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5514 /* Check whether this client is on the channel */
5515 if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
5516 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5517 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5521 /* Notify routers that they should remove this client from their list
5522 of clients on the channel. Send LEAVE notify type. */
5523 silc_server_send_notify_leave(server, SILC_PRIMARY_ROUTE(server),
5524 SILC_BROADCAST(server), channel, id_entry->id);
5526 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
5527 SILC_STATUS_OK, 0, 2, tmp, len);
5529 /* Remove client from channel */
5530 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5532 /* If the channel does not exist anymore we won't send anything */
5535 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5536 /* Re-generate channel key */
5537 if (!silc_server_create_channel_key(server, channel, 0))
5540 /* Send the channel key */
5541 silc_server_send_channel_key(server, NULL, channel,
5542 server->server_type == SILC_ROUTER ?
5543 FALSE : !server->standalone);
5548 silc_server_command_free(cmd);
5551 /* Server side of command USERS. Resolves clients and their USERS currently
5552 joined on the requested channel. The list of Client ID's and their modes
5553 on the channel is sent back. */
5555 SILC_SERVER_CMD_FUNC(users)
5557 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5558 SilcServer server = cmd->server;
5559 SilcChannelEntry channel;
5560 SilcChannelID *id = NULL;
5561 SilcBuffer packet, idp;
5562 unsigned char *channel_id;
5563 SilcUInt32 channel_id_len;
5564 SilcBuffer client_id_list;
5565 SilcBuffer client_mode_list;
5566 unsigned char lc[4];
5567 SilcUInt32 list_count = 0;
5568 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5571 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5573 /* Get Channel ID */
5574 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5576 /* Get channel name */
5577 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5579 if (!channel_id && !channel_name) {
5580 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5581 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5586 id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
5588 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5589 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5594 /* If we are server and we don't know about this channel we will send
5595 the command to our router. If we know about the channel then we also
5596 have the list of users already. */
5598 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5600 channel = silc_idlist_find_channel_by_name(server->local_list,
5601 channel_name, NULL);
5603 if (!channel || (!server->standalone && (channel->disabled ||
5604 !channel->users_resolved))) {
5605 if (server->server_type != SILC_ROUTER && !server->standalone &&
5609 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5610 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5612 /* Send USERS command */
5613 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5614 SILC_PACKET_COMMAND, cmd->packet->flags,
5615 tmpbuf->data, tmpbuf->len, TRUE);
5617 /* Reprocess this packet after received reply */
5618 silc_server_command_pending(server, SILC_COMMAND_USERS,
5619 silc_command_get_ident(cmd->payload),
5620 silc_server_command_users,
5621 silc_server_command_dup(cmd));
5622 cmd->pending = TRUE;
5623 silc_command_set_ident(cmd->payload, ident);
5624 silc_buffer_free(tmpbuf);
5629 /* Check the global list as well. */
5631 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5633 channel = silc_idlist_find_channel_by_name(server->global_list,
5634 channel_name, NULL);
5636 /* Channel really does not exist */
5637 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5638 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5644 /* If the channel is private or secret do not send anything, unless the
5645 user requesting this command is on the channel or is server */
5646 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5647 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5648 && !silc_server_client_on_channel(cmd->sock->user_data, channel,
5650 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5651 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5657 /* Get the users list */
5658 if (!silc_server_get_users_on_channel(server, channel, &client_id_list,
5659 &client_mode_list, &list_count)) {
5661 client_id_list = NULL;
5662 client_mode_list = NULL;
5666 SILC_PUT32_MSB(list_count, lc);
5669 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5670 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5671 SILC_STATUS_OK, 0, ident, 4,
5672 2, idp->data, idp->len,
5675 client_id_list->data : NULL,
5677 client_id_list->len : 0,
5678 5, client_mode_list ?
5679 client_mode_list->data : NULL,
5681 client_mode_list->len : 0);
5682 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5683 packet->data, packet->len, FALSE);
5685 silc_buffer_free(idp);
5686 silc_buffer_free(packet);
5688 silc_buffer_free(client_id_list);
5689 if (client_mode_list)
5690 silc_buffer_free(client_mode_list);
5694 silc_server_command_free(cmd);
5697 /* Server side of command GETKEY. This fetches the client's public key
5698 from the server where to the client is connected. */
5700 SILC_SERVER_CMD_FUNC(getkey)
5702 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5703 SilcServer server = cmd->server;
5705 SilcClientEntry client;
5706 SilcServerEntry server_entry;
5707 SilcClientID *client_id = NULL;
5708 SilcServerID *server_id = NULL;
5709 SilcIDPayload idp = NULL;
5710 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5711 unsigned char *tmp, *pkdata;
5712 SilcUInt32 tmp_len, pklen;
5713 SilcBuffer pk = NULL;
5715 SilcPublicKey public_key;
5717 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5719 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5720 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5724 idp = silc_id_payload_parse(tmp, tmp_len);
5726 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5727 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5732 id_type = silc_id_payload_get_type(idp);
5733 if (id_type == SILC_ID_CLIENT) {
5734 client_id = silc_id_payload_get_id(idp);
5736 /* If the client is not found from local list there is no chance it
5737 would be locally connected client so send the command further. */
5738 client = silc_idlist_find_client_by_id(server->local_list,
5739 client_id, TRUE, NULL);
5741 client = silc_idlist_find_client_by_id(server->global_list,
5742 client_id, TRUE, NULL);
5744 if ((!client && !cmd->pending && !server->standalone) ||
5745 (client && !client->connection && !cmd->pending &&
5746 !(client->mode & SILC_UMODE_DETACHED)) ||
5747 (client && !client->data.public_key && !cmd->pending)) {
5749 SilcUInt16 old_ident;
5750 SilcSocketConnection dest_sock;
5752 dest_sock = silc_server_get_client_route(server, NULL, 0,
5753 client_id, NULL, NULL);
5757 old_ident = silc_command_get_ident(cmd->payload);
5758 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5759 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5761 silc_server_packet_send(server, dest_sock,
5762 SILC_PACKET_COMMAND, cmd->packet->flags,
5763 tmpbuf->data, tmpbuf->len, TRUE);
5765 /* Reprocess this packet after received reply from router */
5766 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5767 silc_command_get_ident(cmd->payload),
5768 silc_server_command_getkey,
5769 silc_server_command_dup(cmd));
5770 cmd->pending = TRUE;
5771 silc_command_set_ident(cmd->payload, old_ident);
5772 silc_buffer_free(tmpbuf);
5777 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5778 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5783 /* The client is locally connected, just get the public key and
5784 send it back. If they key does not exist then do not send it,
5785 send just OK reply */
5786 public_key = client->data.public_key;
5791 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5792 pk = silc_buffer_alloc(4 + tmp_len);
5793 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5794 silc_buffer_format(pk,
5795 SILC_STR_UI_SHORT(tmp_len),
5796 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5797 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5803 } else if (id_type == SILC_ID_SERVER) {
5804 server_id = silc_id_payload_get_id(idp);
5806 /* If the server is not found from local list there is no chance it
5807 would be locally connected server so send the command further. */
5808 server_entry = silc_idlist_find_server_by_id(server->local_list,
5809 server_id, TRUE, NULL);
5811 server_entry = silc_idlist_find_server_by_id(server->global_list,
5812 server_id, TRUE, NULL);
5814 if (server_entry != server->id_entry &&
5815 ((!server_entry && !cmd->pending && !server->standalone) ||
5816 (server_entry && !server_entry->connection && !cmd->pending &&
5817 !server->standalone) ||
5818 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5819 !server->standalone))) {
5821 SilcUInt16 old_ident;
5823 old_ident = silc_command_get_ident(cmd->payload);
5824 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5825 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5827 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5828 SILC_PACKET_COMMAND, cmd->packet->flags,
5829 tmpbuf->data, tmpbuf->len, TRUE);
5831 /* Reprocess this packet after received reply from router */
5832 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5833 silc_command_get_ident(cmd->payload),
5834 silc_server_command_getkey,
5835 silc_server_command_dup(cmd));
5836 cmd->pending = TRUE;
5837 silc_command_set_ident(cmd->payload, old_ident);
5838 silc_buffer_free(tmpbuf);
5842 if (!server_entry) {
5843 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5844 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
5849 /* If they key does not exist then do not send it, send just OK reply */
5850 public_key = (!server_entry->data.public_key ?
5851 (server_entry == server->id_entry ? server->public_key :
5852 NULL) : server_entry->data.public_key);
5857 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5858 pk = silc_buffer_alloc(4 + tmp_len);
5859 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5860 silc_buffer_format(pk,
5861 SILC_STR_UI_SHORT(tmp_len),
5862 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5863 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5873 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5874 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5875 SILC_STATUS_OK, 0, ident,
5879 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5880 packet->data, packet->len, FALSE);
5881 silc_buffer_free(packet);
5884 silc_buffer_free(pk);
5888 silc_id_payload_free(idp);
5889 silc_free(client_id);
5890 silc_free(server_id);
5891 silc_server_command_free(cmd);
5895 /* Private range commands, specific to this implementation */
5897 /* Server side command of CONNECT. Connects us to the specified remote
5898 server or router. */
5900 SILC_SERVER_CMD_FUNC(connect)
5902 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5903 SilcServer server = cmd->server;
5904 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5905 unsigned char *tmp, *host;
5907 SilcUInt32 port = SILC_PORT;
5909 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
5911 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5914 /* Check whether client has the permissions. */
5915 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5916 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5917 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5918 SILC_STATUS_ERR_NO_SERVER_PRIV, 0);
5922 if (server->server_type == SILC_ROUTER &&
5923 client->mode & SILC_UMODE_SERVER_OPERATOR) {
5924 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5925 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
5929 /* Get the remote server */
5930 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5932 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5933 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5939 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5941 SILC_GET32_MSB(port, tmp);
5943 /* Create the connection. It is done with timeout and is async. */
5944 silc_server_create_connection(server, host, port);
5946 /* Send reply to the sender */
5947 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5951 silc_server_command_free(cmd);
5954 /* Server side command of CLOSE. Closes connection to a specified server. */
5956 SILC_SERVER_CMD_FUNC(close)
5958 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5959 SilcServer server = cmd->server;
5960 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5961 SilcServerEntry server_entry;
5962 SilcSocketConnection sock;
5965 unsigned char *name;
5966 SilcUInt32 port = SILC_PORT;
5968 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
5970 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5973 /* Check whether client has the permissions. */
5974 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5975 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5976 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5977 SILC_STATUS_ERR_NO_SERVER_PRIV,
5982 /* Get the remote server */
5983 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5985 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5986 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5992 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5994 SILC_GET32_MSB(port, tmp);
5996 server_entry = silc_idlist_find_server_by_conn(server->local_list,
5997 name, port, FALSE, NULL);
5999 server_entry = silc_idlist_find_server_by_conn(server->global_list,
6000 name, port, FALSE, NULL);
6001 if (!server_entry) {
6002 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
6003 SILC_STATUS_ERR_NO_SERVER_ID, 0);
6007 /* Send reply to the sender */
6008 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
6011 /* Close the connection to the server */
6012 sock = (SilcSocketConnection)server_entry->connection;
6014 /* If we shutdown primary router connection manually then don't trigger
6015 any reconnect or backup router connections, by setting the router
6017 if (server->router == server_entry) {
6018 server->id_entry->router = NULL;
6019 server->router = NULL;
6020 server->standalone = TRUE;
6022 silc_server_free_sock_user_data(server, sock, NULL);
6023 silc_server_close_connection(server, sock);
6026 silc_server_command_free(cmd);
6029 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
6030 active connections. */
6032 SILC_SERVER_CMD_FUNC(shutdown)
6034 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
6035 SilcServer server = cmd->server;
6036 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
6038 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
6040 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
6043 /* Check whether client has the permission. */
6044 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
6045 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
6046 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
6047 SILC_STATUS_ERR_NO_SERVER_PRIV,
6052 /* Send reply to the sender */
6053 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
6056 /* Then, gracefully, or not, bring the server down. */
6057 silc_server_stop(server);
6061 silc_server_command_free(cmd);