5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2002 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
22 #include "serverincludes.h"
23 #include "server_internal.h"
25 static int silc_server_is_registered(SilcServer server,
26 SilcSocketConnection sock,
27 SilcServerCommandContext cmd,
30 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
35 silc_server_command_send_status_data(SilcServerCommandContext cmd,
40 const unsigned char *arg,
43 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
44 SilcServerCommandReplyContext cmdr,
46 SILC_TASK_CALLBACK(silc_server_command_process_timeout);
48 /* Server command list. */
49 SilcServerCommand silc_command_list[] =
51 SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
52 SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
53 SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
54 SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
55 SILC_SERVER_CMD(list, LIST, SILC_CF_LAG_STRICT | SILC_CF_REG),
56 SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
57 SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
58 SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
59 SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG_STRICT | SILC_CF_REG | SILC_CF_OPER),
60 SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
61 SILC_SERVER_CMD(stats, STATS, SILC_CF_LAG | SILC_CF_REG),
62 SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
63 SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
64 SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG_STRICT | SILC_CF_REG),
65 SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
66 SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
67 SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG_STRICT | SILC_CF_REG),
68 SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
69 SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
70 SILC_SERVER_CMD(ban, BAN, SILC_CF_LAG_STRICT | SILC_CF_REG),
71 SILC_SERVER_CMD(detach, DETACH, SILC_CF_LAG_STRICT | SILC_CF_REG),
72 SILC_SERVER_CMD(watch, WATCH, SILC_CF_LAG | SILC_CF_REG),
73 SILC_SERVER_CMD(silcoper, SILCOPER,
74 SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
75 SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
76 SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
77 SILC_SERVER_CMD(getkey, GETKEY, SILC_CF_LAG | SILC_CF_REG),
79 SILC_SERVER_CMD(connect, PRIV_CONNECT,
80 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
81 SILC_SERVER_CMD(close, PRIV_CLOSE,
82 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
83 SILC_SERVER_CMD(shutdown, PRIV_SHUTDOWN, SILC_CF_LAG | SILC_CF_REG |
89 /* Performs several checks to the command. It first checks whether this
90 command was called as pending command callback. If it was then it checks
91 whether error occurred in the command reply where the pending command
94 It also checks that the requested command includes correct amount
96 #define SILC_SERVER_COMMAND_CHECK(command, context, min, max) \
100 if (silc_server_command_pending_error_check(cmd, context2, command)) { \
101 SILC_LOG_DEBUG(("Error occurred in command reply, command not called")); \
102 silc_server_command_free(cmd); \
106 _argc = silc_argument_get_arg_num(cmd->args); \
108 SILC_LOG_DEBUG(("Not enough parameters in command")); \
109 silc_server_command_send_status_reply(cmd, command, \
110 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, \
112 silc_server_command_free(cmd); \
116 SILC_LOG_DEBUG(("Too many parameters in command")); \
117 silc_server_command_send_status_reply(cmd, command, \
118 SILC_STATUS_ERR_TOO_MANY_PARAMS, \
120 silc_server_command_free(cmd); \
125 /* Returns TRUE if the connection is registered. Unregistered connections
126 usually cannot send commands hence the check. */
128 static int silc_server_is_registered(SilcServer server,
129 SilcSocketConnection sock,
130 SilcServerCommandContext cmd,
133 SilcIDListData idata = (SilcIDListData)sock->user_data;
138 if (idata->status & SILC_IDLIST_STATUS_REGISTERED)
141 silc_server_command_send_status_reply(cmd, command,
142 SILC_STATUS_ERR_NOT_REGISTERED, 0);
146 /* Internal context to hold data when executed command with timeout. */
148 SilcServerCommandContext ctx;
149 SilcServerCommand *cmd;
150 } *SilcServerCommandTimeout;
152 /* Timeout callback to process commands with timeout for client. Client's
153 commands are always executed with timeout. */
155 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
157 SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
158 SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data;
161 SILC_LOG_DEBUG(("Client entry is invalid"));
162 silc_server_command_free(timeout->ctx);
166 /* Update access time */
167 client->last_command = time(NULL);
169 if (!(timeout->cmd->flags & SILC_CF_REG)) {
170 SILC_LOG_DEBUG(("Calling %s command",
171 silc_get_command_name(timeout->cmd->cmd)));
172 timeout->cmd->cb(timeout->ctx, NULL);
173 } else if (silc_server_is_registered(timeout->ctx->server,
176 timeout->cmd->cmd)) {
177 SILC_LOG_DEBUG(("Calling %s command",
178 silc_get_command_name(timeout->cmd->cmd)));
179 timeout->cmd->cb(timeout->ctx, NULL);
181 SILC_LOG_DEBUG(("Client is not registered"));
182 silc_server_command_free(timeout->ctx);
188 /* Processes received command packet. */
190 void silc_server_command_process(SilcServer server,
191 SilcSocketConnection sock,
192 SilcPacketContext *packet)
194 SilcServerCommandContext ctx;
195 SilcServerCommand *cmd;
198 /* Allocate command context. This must be free'd by the
199 command routine receiving it. */
200 ctx = silc_server_command_alloc();
201 ctx->server = server;
202 ctx->sock = silc_socket_dup(sock);
203 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
205 /* Parse the command payload in the packet */
206 ctx->payload = silc_command_payload_parse(packet->buffer->data,
207 packet->buffer->len);
209 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
210 silc_packet_context_free(packet);
211 silc_socket_free(ctx->sock);
215 ctx->args = silc_command_get_args(ctx->payload);
217 /* Get the command */
218 command = silc_command_get(ctx->payload);
219 for (cmd = silc_command_list; cmd->cb; cmd++)
220 if (cmd->cmd == command)
223 if (!cmd || !cmd->cb) {
224 SILC_LOG_DEBUG(("Unknown command %d", command));
225 silc_server_command_send_status_reply(ctx, command,
226 SILC_STATUS_ERR_UNKNOWN_COMMAND, 0);
227 silc_server_command_free(ctx);
231 /* Execute client's commands always with timeout. Normally they are
232 executed with zero (0) timeout but if client is sending command more
233 frequently than once in 2 seconds, then the timeout may be 0 to 2
235 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
236 SilcClientEntry client = (SilcClientEntry)sock->user_data;
237 SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
243 if (client->last_command && (time(NULL) - client->last_command) < 2) {
244 client->fast_command++;
247 if (client->fast_command - 2 <= 0)
248 client->fast_command = 0;
250 client->fast_command -= 2;
254 if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
255 (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
256 silc_schedule_task_add(server->schedule, sock->sock,
257 silc_server_command_process_timeout, timeout,
258 (client->fast_command < 3 ? 0 :
259 2 - (time(NULL) - client->last_command)),
260 (client->fast_command < 3 ? 200000 : 0),
261 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
263 silc_schedule_task_add(server->schedule, sock->sock,
264 silc_server_command_process_timeout, timeout,
265 0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
269 /* Execute for server */
271 if (!(cmd->flags & SILC_CF_REG)) {
272 SILC_LOG_DEBUG(("Calling %s command", silc_get_command_name(cmd->cmd)));
274 } else if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) {
275 SILC_LOG_DEBUG(("Calling %s command", silc_get_command_name(cmd->cmd)));
278 SILC_LOG_DEBUG(("Server is not registered"));
279 silc_server_command_free(ctx);
283 /* Allocate Command Context */
285 SilcServerCommandContext silc_server_command_alloc()
287 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
292 /* Free's the command context allocated before executing the command */
294 void silc_server_command_free(SilcServerCommandContext ctx)
297 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
299 if (ctx->users < 1) {
301 silc_command_payload_free(ctx->payload);
303 silc_packet_context_free(ctx->packet);
305 silc_socket_free(ctx->sock); /* Decrease reference counter */
310 /* Duplicate Command Context by adding reference counter. The context won't
311 be free'd untill it hits zero. */
313 SilcServerCommandContext
314 silc_server_command_dup(SilcServerCommandContext ctx)
317 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
322 /* Add new pending command to be executed when reply to a command has been
323 received. The `reply_cmd' is the command that will call the `callback'
324 with `context' when reply has been received. It can be SILC_COMMAND_NONE
325 to match any command with the `ident'. If `ident' is non-zero
326 the `callback' will be executed when received reply with command
327 identifier `ident'. If there already exists pending command for the
328 specified command, ident, callback and context this function has no
331 bool silc_server_command_pending(SilcServer server,
332 SilcCommand reply_cmd,
334 SilcCommandCb callback,
337 SilcServerCommandPending *reply;
339 /* Check whether identical pending already exists for same command,
340 ident, callback and callback context. If it does then it would be
341 error to register it again. */
342 silc_dlist_start(server->pending_commands);
343 while ((reply = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
344 if (reply->reply_cmd == reply_cmd && reply->ident == ident &&
345 reply->callback == callback && reply->context == context)
349 reply = silc_calloc(1, sizeof(*reply));
350 reply->reply_cmd = reply_cmd;
351 reply->ident = ident;
352 reply->context = context;
353 reply->callback = callback;
354 silc_dlist_add(server->pending_commands, reply);
359 /* Deletes pending command by reply command type. */
361 void silc_server_command_pending_del(SilcServer server,
362 SilcCommand reply_cmd,
365 SilcServerCommandPending *r;
367 silc_dlist_start(server->pending_commands);
368 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
369 if (r->reply_cmd == reply_cmd && r->ident == ident) {
370 silc_dlist_del(server->pending_commands, r);
376 /* Checks for pending commands and marks callbacks to be called from
377 the command reply function. Returns TRUE if there were pending command. */
379 SilcServerCommandPendingCallbacks
380 silc_server_command_pending_check(SilcServer server,
381 SilcServerCommandReplyContext ctx,
384 SilcUInt32 *callbacks_count)
386 SilcServerCommandPending *r;
387 SilcServerCommandPendingCallbacks callbacks = NULL;
390 silc_dlist_start(server->pending_commands);
391 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
392 if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE)
393 && r->ident == ident) {
394 callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
395 callbacks[i].context = r->context;
396 callbacks[i].callback = r->callback;
402 *callbacks_count = i;
406 /* Sends simple status message as command reply packet */
409 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
416 SILC_LOG_DEBUG(("Sending command status %d", status));
419 silc_command_reply_payload_encode_va(command, status, error,
420 silc_command_get_ident(cmd->payload),
422 silc_server_packet_send(cmd->server, cmd->sock,
423 SILC_PACKET_COMMAND_REPLY, 0,
424 buffer->data, buffer->len, FALSE);
425 silc_buffer_free(buffer);
428 /* Sends command status reply with one extra argument. The argument
429 type must be sent as argument. */
432 silc_server_command_send_status_data(SilcServerCommandContext cmd,
437 const unsigned char *arg,
442 SILC_LOG_DEBUG(("Sending command status %d", status));
445 silc_command_reply_payload_encode_va(command, status, 0,
446 silc_command_get_ident(cmd->payload),
447 1, arg_type, arg, arg_len);
448 silc_server_packet_send(cmd->server, cmd->sock,
449 SILC_PACKET_COMMAND_REPLY, 0,
450 buffer->data, buffer->len, FALSE);
451 silc_buffer_free(buffer);
454 /* This function can be called to check whether in the command reply
455 an error occurred. This function has no effect if this is called
456 when the command function was not called as pending command callback.
457 This returns TRUE if error had occurred. */
460 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
461 SilcServerCommandReplyContext cmdr,
464 if (!cmd->pending || !cmdr)
467 if (!silc_command_get_status(cmdr->payload, NULL, NULL)) {
470 /* Send the same command reply payload */
471 silc_command_set_ident(cmdr->payload,
472 silc_command_get_ident(cmd->payload));
473 buffer = silc_command_payload_encode_payload(cmdr->payload);
474 silc_server_packet_send(cmd->server, cmd->sock,
475 SILC_PACKET_COMMAND_REPLY, 0,
476 buffer->data, buffer->len, FALSE);
477 silc_buffer_free(buffer);
484 /******************************************************************************
488 ******************************************************************************/
497 #define ADD_ERROR(errptr, errptr_count, _id, _id_type, _index, _status) \
499 errptr = silc_realloc(errptr, sizeof(*errptr) * (errptr_count + 1)); \
502 errptr[errptr_count].id = _id; \
503 errptr[errptr_count].id_type = _id_type; \
504 errptr[errptr_count].index = _index; \
505 errptr[errptr_count].error = _status; \
510 silc_server_command_whois_parse(SilcServerCommandContext cmd,
511 SilcClientID ***client_id,
512 SilcUInt32 *client_id_count,
516 ResolveError *error_client,
517 SilcUInt32 *error_client_count)
521 SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
525 /* If client ID is in the command it must be used instead of nickname */
526 tmp = silc_argument_get_arg_type(cmd->args, 4, &len);
528 /* No ID, get the nickname@server string and parse it. */
529 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
531 silc_parse_userfqdn(tmp, nickname, server_name);
533 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
534 SILC_STATUS_ERR_BAD_NICKNAME, 0);
538 /* Command includes ID, we must use that. Take all ID's from the
540 for (k = 0, i = 0; i < argc; i++) {
541 tmp = silc_argument_get_arg_type(cmd->args, i + 4, &len);
544 id = silc_id_payload_parse_id(tmp, len, NULL);
546 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
547 (*client_id_count + 1));
548 (*client_id)[k] = id;
549 (*client_id_count)++;
552 ADD_ERROR((*error_client), (*error_client_count), NULL, 0, i + 4,
553 SILC_STATUS_ERR_BAD_CLIENT_ID);
558 /* Get the max count of reply messages allowed */
559 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
561 SILC_GET32_MSB(*count, tmp);
568 /* Resolve context used by both WHOIS and IDENTIFY commands */
570 SilcServerEntry router;
572 unsigned char **res_argv;
573 SilcUInt32 *res_argv_lens;
574 SilcUInt32 *res_argv_types;
576 } *SilcServerResolveContext;
579 silc_server_command_whois_check(SilcServerCommandContext cmd,
580 SilcClientEntry *clients,
581 SilcUInt32 clients_count)
583 SilcServer server = cmd->server;
584 SilcClientEntry entry;
585 SilcServerResolveContext resolve = NULL, r = NULL;
586 SilcUInt32 resolve_count = 0;
590 SILC_LOG_DEBUG(("Start"));
592 for (i = 0; i < clients_count; i++) {
597 if ((entry->nickname && entry->username && entry->userinfo) ||
598 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
602 /* If we are normal server, and we've not resolved this client from
603 router and it is global client, we'll check whether it is on some
604 channel. If not then we cannot be sure about its validity, and
605 we'll resolve it from router. */
606 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
607 entry->connection || silc_hash_table_count(entry->channels))
611 /* We need to resolve this entry since it is not complete */
613 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
614 /* The entry is being resolved (and we are not the resolver) so attach
615 to the command reply and we're done with this one. */
616 silc_server_command_pending(server, SILC_COMMAND_NONE,
617 entry->resolve_cmd_ident,
618 silc_server_command_whois,
619 silc_server_command_dup(cmd));
622 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
623 /* We've resolved this and it still is not ready. We'll return
624 and are that this will be handled again after it is resolved. */
625 for (i = 0; i < resolve_count; i++) {
626 for (k = 0; k < r->res_argc; k++)
627 silc_free(r->res_argv[k]);
628 silc_free(r->res_argv);
629 silc_free(r->res_argv_lens);
630 silc_free(r->res_argv_types);
635 /* We'll resolve this client */
639 for (k = 0; k < resolve_count; k++) {
640 if (resolve[k].router == entry->router) {
647 resolve = silc_realloc(resolve, sizeof(*resolve) *
648 (resolve_count + 1));
649 r = &resolve[resolve_count];
650 memset(r, 0, sizeof(*r));
651 r->router = entry->router;
652 r->ident = ++server->cmd_ident;
656 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
658 r->res_argv_lens = silc_realloc(r->res_argv_lens,
659 sizeof(*r->res_argv_lens) *
661 r->res_argv_types = silc_realloc(r->res_argv_types,
662 sizeof(*r->res_argv_types) *
664 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
665 r->res_argv[r->res_argc] = silc_calloc(idp->len,
666 sizeof(**r->res_argv));
667 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
668 r->res_argv_lens[r->res_argc] = idp->len;
669 r->res_argv_types[r->res_argc] = r->res_argc + 4;
671 silc_buffer_free(idp);
673 entry->resolve_cmd_ident = r->ident;
674 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
675 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
680 /* Do the resolving */
681 for (i = 0; i < resolve_count; i++) {
686 /* Send WHOIS request. We send WHOIS since we're doing the requesting
687 now anyway so make it a good one. */
688 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
689 r->res_argc, r->res_argv,
693 silc_server_packet_send(server, r->router->connection,
694 SILC_PACKET_COMMAND, cmd->packet->flags,
695 res_cmd->data, res_cmd->len, FALSE);
697 /* Reprocess this packet after received reply */
698 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
700 silc_server_command_whois,
701 silc_server_command_dup(cmd));
704 silc_buffer_free(res_cmd);
705 for (k = 0; k < r->res_argc; k++)
706 silc_free(r->res_argv[k]);
707 silc_free(r->res_argv);
708 silc_free(r->res_argv_lens);
709 silc_free(r->res_argv_types);
718 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
719 SilcClientEntry *clients,
720 SilcUInt32 clients_count,
722 SilcUInt32 errors_count,
723 int count, const char *nickname,
724 SilcClientID **client_ids)
726 SilcServer server = cmd->server;
728 int i, k, valid_count = clients_count;
730 SilcBuffer packet, idp, channels, umode_list = NULL;
731 SilcClientEntry entry;
733 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
734 char nh[256], uh[256];
735 unsigned char idle[4], mode[4];
736 unsigned char *fingerprint;
737 SilcSocketConnection hsock;
740 /* Process only valid clients and ignore those that are not registered.
741 This is checked with nickname only because when resolved client IDs
742 we check that they are registered earlier. */
744 for (i = 0; i < clients_count; i++)
745 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
751 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
752 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
753 3, nickname, strlen(nickname));
758 /* Start processing found clients. */
759 status = SILC_STATUS_OK;
761 status = SILC_STATUS_LIST_START;
763 for (i = 0, k = 0; i < clients_count; i++) {
769 status = SILC_STATUS_LIST_ITEM;
770 if (valid_count > 1 && k == valid_count - 1 && !errors_count)
771 status = SILC_STATUS_LIST_END;
772 if (count && k - 1 == count)
773 status = SILC_STATUS_LIST_END;
775 /* Send WHOIS reply */
776 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
777 tmp = silc_argument_get_first_arg(cmd->args, NULL);
779 memset(uh, 0, sizeof(uh));
780 memset(nh, 0, sizeof(nh));
781 memset(idle, 0, sizeof(idle));
783 strncat(nh, entry->nickname, strlen(entry->nickname));
784 if (!strchr(entry->nickname, '@')) {
786 if (entry->servername) {
787 strncat(nh, entry->servername, strlen(entry->servername));
789 len = entry->router ? strlen(entry->router->server_name) :
790 strlen(server->server_name);
791 strncat(nh, entry->router ? entry->router->server_name :
792 server->server_name, len);
796 strncat(uh, entry->username, strlen(entry->username));
797 if (!strchr(entry->username, '@') && entry->connection) {
799 hsock = (SilcSocketConnection)entry->connection;
800 len = strlen(hsock->hostname);
801 strncat(uh, hsock->hostname, len);
804 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
805 channels = silc_server_get_client_channel_list(server, entry, FALSE,
808 channels = silc_server_get_client_channel_list(server, entry, TRUE,
811 if (entry->data.fingerprint[0] != 0 && entry->data.fingerprint[1] != 0)
812 fingerprint = entry->data.fingerprint;
816 SILC_PUT32_MSB(entry->mode, mode);
817 if (entry->connection)
818 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
821 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
823 2, idp->data, idp->len,
827 strlen(entry->userinfo),
828 6, channels ? channels->data : NULL,
829 channels ? channels->len : 0,
833 fingerprint ? 20 : 0,
834 10, umode_list ? umode_list->data :
835 NULL, umode_list ? umode_list->len :
838 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
839 0, packet->data, packet->len, FALSE);
841 silc_buffer_free(packet);
842 silc_buffer_free(idp);
844 silc_buffer_free(channels);
846 silc_buffer_free(umode_list);
850 if (status == SILC_STATUS_LIST_END)
855 /* Send error replies */
856 if (status == SILC_STATUS_OK && errors_count > 1)
857 status = SILC_STATUS_LIST_START;
860 for (i = 0, k = 0; i < errors_count; i++) {
862 idp = silc_id_payload_encode(errors[i].id, SILC_ID_CLIENT);
866 tmp = silc_argument_get_arg_type(cmd->args, errors[i].index, &len);
870 status = SILC_STATUS_LIST_ITEM;
871 if (errors_count > 1 && k == errors_count - 1)
872 status = SILC_STATUS_LIST_END;
873 if (count && k - 1 == count)
874 status = SILC_STATUS_LIST_END;
877 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
878 (status == SILC_STATUS_OK ?
879 errors[i].error : status),
880 (status == SILC_STATUS_OK ?
881 0 : errors[i].error),
883 silc_buffer_free(idp);
886 if (status == SILC_STATUS_LIST_END)
893 silc_server_command_whois_send_router(SilcServerCommandContext cmd)
895 SilcServer server = cmd->server;
897 SilcUInt16 old_ident;
899 old_ident = silc_command_get_ident(cmd->payload);
900 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
901 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
903 /* Send WHOIS command to our router */
904 silc_server_packet_send(server, (SilcSocketConnection)
905 SILC_PRIMARY_ROUTE(server),
906 SILC_PACKET_COMMAND, cmd->packet->flags,
907 tmpbuf->data, tmpbuf->len, TRUE);
909 /* Reprocess this packet after received reply from router */
910 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
911 silc_command_get_ident(cmd->payload),
912 silc_server_command_whois,
913 silc_server_command_dup(cmd));
915 silc_command_set_ident(cmd->payload, old_ident);
916 silc_buffer_free(tmpbuf);
920 silc_server_command_whois_process(SilcServerCommandContext cmd)
922 SilcServer server = cmd->server;
923 char *nick = NULL, *server_name = NULL;
925 SilcClientEntry *clients = NULL, entry;
926 SilcClientID **client_id = NULL;
927 SilcUInt32 client_id_count = 0, clients_count = 0, error_client_count = 0;
928 ResolveError error_client = NULL;
930 bool check_global = FALSE;
932 /* Parse the whois request */
933 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
934 &nick, &server_name, &count,
935 &error_client, &error_client_count))
938 /* Send the WHOIS request to the router only if it included nickname.
939 Since nicknames can be expanded into many clients we need to send it
940 to router. If the WHOIS included only client ID's we will check them
941 first locally since we just might have them. */
942 if (nick && !client_id_count && cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
943 server->server_type == SILC_SERVER && !cmd->pending &&
944 !server->standalone) {
945 silc_server_command_whois_send_router(cmd);
950 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
952 else if (server->server_type != SILC_SERVER)
955 /* Get all clients matching that ID or nickname from local list */
956 if (client_id_count) {
957 /* Check all Client ID's received in the command packet */
958 for (i = 0; i < client_id_count; i++) {
959 entry = silc_idlist_find_client_by_id(server->local_list,
960 client_id[i], TRUE, NULL);
961 if (!entry && check_global)
962 entry = silc_idlist_find_client_by_id(server->global_list,
963 client_id[i], TRUE, NULL);
965 clients = silc_realloc(clients, sizeof(*clients) *
966 (clients_count + 1));
967 clients[clients_count++] = entry;
969 /* If we are normal server and did not send the request first to router
970 do it now, since we do not have the Client ID information. */
971 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
972 server->server_type == SILC_SERVER && !cmd->pending &&
973 !server->standalone) {
974 silc_server_command_whois_send_router(cmd);
979 ADD_ERROR(error_client, error_client_count, client_id[i],
980 SILC_ID_CLIENT, 0, SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
984 /* Find by nickname */
985 if (!silc_idlist_get_clients_by_hash(server->local_list,
986 nick, server->md5hash,
987 &clients, &clients_count))
988 silc_idlist_get_clients_by_nickname(server->local_list,
990 &clients, &clients_count);
992 if (!silc_idlist_get_clients_by_hash(server->global_list,
993 nick, server->md5hash,
994 &clients, &clients_count))
995 silc_idlist_get_clients_by_nickname(server->global_list,
997 &clients, &clients_count);
1001 if (!clients && (client_id_count || nick)) {
1002 /* If we are normal server and did not send the request first to router
1003 do it now, since we do not have the information. */
1004 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1005 server->server_type == SILC_SERVER && !cmd->pending &&
1006 !server->standalone) {
1007 silc_server_command_whois_send_router(cmd);
1012 /* Such client(s) really does not exist in the SILC network. */
1013 if (!client_id_count)
1014 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
1015 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1016 3, nick, strlen(nick));
1018 silc_server_command_whois_send_reply(cmd, NULL, 0,
1019 error_client, error_client_count,
1024 /* Router always finds the client entry if it exists in the SILC network.
1025 However, it might be incomplete entry and does not include all the
1026 mandatory fields that WHOIS command reply requires. Check for these and
1027 make query from the server who owns the client if some fields are
1029 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
1034 /* Send the command reply */
1035 silc_server_command_whois_send_reply(cmd, clients, clients_count,
1036 error_client, error_client_count,
1037 count, nick, client_id);
1040 if (client_id_count) {
1041 for (i = 0; i < client_id_count; i++)
1042 silc_free(client_id[i]);
1043 silc_free(client_id);
1046 silc_free(error_client);
1048 silc_free(server_name);
1053 /* Server side of command WHOIS. Processes user's query and sends found
1054 results as command replies back to the client. */
1056 SILC_SERVER_CMD_FUNC(whois)
1058 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1061 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 3328);
1063 ret = silc_server_command_whois_process(cmd);
1064 silc_server_command_free(cmd);
1067 /******************************************************************************
1071 ******************************************************************************/
1074 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
1082 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1084 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
1085 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1090 /* Get the nickname@server string and parse it. */
1091 silc_parse_userfqdn(tmp, nickname, server_name);
1093 /* Get the max count of reply messages allowed */
1094 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1096 SILC_GET32_MSB(*count, tmp);
1104 silc_server_command_whowas_check(SilcServerCommandContext cmd,
1105 SilcClientEntry *clients,
1106 SilcUInt32 clients_count)
1108 SilcServer server = cmd->server;
1110 SilcClientEntry entry;
1112 for (i = 0; i < clients_count; i++) {
1115 if (!entry->nickname || !entry->username) {
1117 SilcUInt16 old_ident;
1122 old_ident = silc_command_get_ident(cmd->payload);
1123 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1124 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1126 /* Send WHOWAS command */
1127 silc_server_packet_send(server, entry->router->connection,
1128 SILC_PACKET_COMMAND, cmd->packet->flags,
1129 tmpbuf->data, tmpbuf->len, TRUE);
1131 /* Reprocess this packet after received reply */
1132 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1133 silc_command_get_ident(cmd->payload),
1134 silc_server_command_whowas,
1135 silc_server_command_dup(cmd));
1136 cmd->pending = TRUE;
1137 silc_command_set_ident(cmd->payload, old_ident);
1139 silc_buffer_free(tmpbuf);
1148 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1149 SilcClientEntry *clients,
1150 SilcUInt32 clients_count)
1152 SilcServer server = cmd->server;
1154 int i, k, count = 0, len;
1155 SilcBuffer packet, idp;
1156 SilcClientEntry entry = NULL;
1158 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1159 char nh[256], uh[256];
1162 status = SILC_STATUS_OK;
1164 /* Process only entries that are not registered anymore. */
1166 for (i = 0; i < clients_count; i++) {
1167 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1174 /* No valid entries found at all, just send error */
1175 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1176 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1177 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1178 3, tmp, tmp ? strlen(tmp) : 0);
1182 if (valid_count > 1)
1183 status = SILC_STATUS_LIST_START;
1185 for (i = 0, k = 0; i < clients_count; i++) {
1191 status = SILC_STATUS_LIST_ITEM;
1192 if (valid_count > 1 && k == valid_count - 1)
1193 status = SILC_STATUS_LIST_END;
1194 if (count && k - 1 == count)
1195 status = SILC_STATUS_LIST_END;
1197 /* Send WHOWAS reply */
1198 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1199 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1200 memset(uh, 0, sizeof(uh));
1201 memset(nh, 0, sizeof(nh));
1203 strncat(nh, entry->nickname, strlen(entry->nickname));
1204 if (!strchr(entry->nickname, '@')) {
1205 strncat(nh, "@", 1);
1206 if (entry->servername) {
1207 strncat(nh, entry->servername, strlen(entry->servername));
1209 len = entry->router ? strlen(entry->router->server_name) :
1210 strlen(server->server_name);
1211 strncat(nh, entry->router ? entry->router->server_name :
1212 server->server_name, len);
1216 strncat(uh, entry->username, strlen(entry->username));
1217 if (!strchr(entry->username, '@')) {
1218 strncat(uh, "@", 1);
1219 strcat(uh, "*private*");
1223 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1224 status, 0, ident, 4,
1225 2, idp->data, idp->len,
1230 strlen(entry->userinfo) : 0);
1231 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1232 0, packet->data, packet->len, FALSE);
1234 silc_buffer_free(packet);
1235 silc_buffer_free(idp);
1237 if (status == SILC_STATUS_LIST_END)
1244 silc_server_command_whowas_process(SilcServerCommandContext cmd)
1246 SilcServer server = cmd->server;
1247 char *nick = NULL, *server_name = NULL;
1249 SilcClientEntry *clients = NULL;
1250 SilcUInt32 clients_count = 0;
1252 bool check_global = FALSE;
1254 /* Protocol dictates that we must always send the received WHOWAS request
1255 to our router if we are normal server, so let's do it now unless we
1256 are standalone. We will not send any replies to the client until we
1257 have received reply from the router. */
1258 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1259 server->server_type == SILC_SERVER && !cmd->pending &&
1260 !server->standalone) {
1262 SilcUInt16 old_ident;
1264 old_ident = silc_command_get_ident(cmd->payload);
1265 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1266 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1268 /* Send WHOWAS command to our router */
1269 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
1270 SILC_PACKET_COMMAND, cmd->packet->flags,
1271 tmpbuf->data, tmpbuf->len, TRUE);
1273 /* Reprocess this packet after received reply from router */
1274 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1275 silc_command_get_ident(cmd->payload),
1276 silc_server_command_whowas,
1277 silc_server_command_dup(cmd));
1278 cmd->pending = TRUE;
1279 silc_command_set_ident(cmd->payload, old_ident);
1281 silc_buffer_free(tmpbuf);
1286 /* We are ready to process the command request. Let's search for the
1287 requested client and send reply to the requesting client. */
1289 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1290 check_global = TRUE;
1291 else if (server->server_type != SILC_SERVER)
1292 check_global = TRUE;
1294 /* Parse the whowas request */
1295 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1298 /* Get all clients matching that nickname from local list */
1299 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1301 &clients, &clients_count))
1302 silc_idlist_get_clients_by_hash(server->local_list,
1303 nick, server->md5hash,
1304 &clients, &clients_count);
1306 /* Check global list as well */
1308 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1310 &clients, &clients_count))
1311 silc_idlist_get_clients_by_hash(server->global_list,
1312 nick, server->md5hash,
1313 &clients, &clients_count);
1317 /* Such a client really does not exist in the SILC network. */
1318 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1319 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1320 3, nick, strlen(nick));
1324 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1329 /* Send the command reply to the client */
1330 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1335 silc_free(server_name);
1339 /* Server side of command WHOWAS. */
1341 SILC_SERVER_CMD_FUNC(whowas)
1343 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1346 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1348 ret = silc_server_command_whowas_process(cmd);
1349 silc_server_command_free(cmd);
1352 /******************************************************************************
1356 ******************************************************************************/
1359 silc_server_command_identify_send_router(SilcServerCommandContext cmd)
1361 SilcServer server = cmd->server;
1363 SilcUInt16 old_ident;
1365 old_ident = silc_command_get_ident(cmd->payload);
1366 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1367 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1369 /* Send IDENTIFY command to our router */
1370 silc_server_packet_send(server, (SilcSocketConnection)
1371 SILC_PRIMARY_ROUTE(server),
1372 SILC_PACKET_COMMAND, cmd->packet->flags,
1373 tmpbuf->data, tmpbuf->len, TRUE);
1375 /* Reprocess this packet after received reply from router */
1376 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1377 silc_command_get_ident(cmd->payload),
1378 silc_server_command_identify,
1379 silc_server_command_dup(cmd));
1380 cmd->pending = TRUE;
1381 silc_command_set_ident(cmd->payload, old_ident);
1382 silc_buffer_free(tmpbuf);
1386 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1387 SilcClientEntry **clients,
1388 SilcUInt32 *clients_count,
1389 SilcServerEntry **servers,
1390 SilcUInt32 *servers_count,
1391 SilcChannelEntry **channels,
1392 SilcUInt32 *channels_count,
1394 ResolveError *error_id,
1395 SilcUInt32 *error_id_count)
1397 SilcServer server = cmd->server;
1400 SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
1402 bool check_global = FALSE;
1406 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1407 check_global = TRUE;
1408 else if (server->server_type != SILC_SERVER)
1409 check_global = TRUE;
1411 /* If ID Payload is in the command it must be used instead of names */
1412 tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1414 /* No ID, get the names. */
1416 /* If we are normal server and have not resolved information from
1417 router yet, do so now. */
1418 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1419 server->server_type == SILC_SERVER && !cmd->pending &&
1420 !server->standalone) {
1421 silc_server_command_identify_send_router(cmd);
1425 /* Try to get nickname@server. */
1426 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1429 char *nick_server = NULL;
1431 silc_parse_userfqdn(tmp, &nick, &nick_server);
1433 if (!silc_idlist_get_clients_by_hash(server->local_list,
1434 nick, server->md5hash,
1435 clients, clients_count))
1436 silc_idlist_get_clients_by_nickname(server->local_list,
1438 clients, clients_count);
1440 if (!silc_idlist_get_clients_by_hash(server->global_list,
1441 nick, server->md5hash,
1442 clients, clients_count))
1443 silc_idlist_get_clients_by_nickname(server->global_list,
1445 clients, clients_count);
1449 silc_free(nick_server);
1452 /* the nickname does not exist, send error reply */
1453 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1454 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1455 3, tmp, strlen(tmp));
1460 /* Try to get server name */
1461 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1463 entry = silc_idlist_find_server_by_name(server->local_list,
1465 if (!entry && check_global)
1466 entry = silc_idlist_find_server_by_name(server->global_list,
1469 *servers = silc_realloc(*servers, sizeof(**servers) *
1470 (*servers_count + 1));
1471 (*servers)[(*servers_count)++] = entry;
1475 /* the server does not exist, send error reply */
1476 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1477 SILC_STATUS_ERR_NO_SUCH_SERVER,
1478 0, 3, tmp, strlen(tmp));
1483 /* Try to get channel name */
1484 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1486 entry = silc_idlist_find_channel_by_name(server->local_list,
1488 if (!entry && check_global)
1489 entry = silc_idlist_find_channel_by_name(server->global_list,
1492 *channels = silc_realloc(*channels, sizeof(**channels) *
1493 (*channels_count + 1));
1494 (*channels)[(*channels_count)++] = entry;
1498 /* The channel does not exist, send error reply */
1499 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1500 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1501 0, 3, tmp, strlen(tmp));
1506 if (!(*clients) && !(*servers) && !(*channels)) {
1507 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1508 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1513 /* Command includes ID, we must use that. Also check whether the command
1514 has more than one ID set - take them all. */
1516 /* Take all ID's from the command packet */
1517 for (i = 0; i < argc; i++) {
1520 tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
1524 idp = silc_id_payload_parse(tmp, len);
1526 ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1527 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1529 id = silc_id_payload_get_id(idp);
1530 switch (silc_id_payload_get_type(idp)) {
1532 case SILC_ID_CLIENT:
1533 entry = silc_idlist_find_client_by_id(server->local_list,
1535 if (!entry && check_global)
1536 entry = silc_idlist_find_client_by_id(server->global_list,
1539 *clients = silc_realloc(*clients, sizeof(**clients) *
1540 (*clients_count + 1));
1541 (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
1543 /* If we are normal server and have not resolved information from
1544 router yet, do so now. */
1545 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1546 server->server_type == SILC_SERVER && !cmd->pending &&
1547 !server->standalone) {
1548 silc_server_command_identify_send_router(cmd);
1549 silc_free(*clients);
1550 silc_free(*servers);
1551 silc_free(*channels);
1552 silc_free(*error_id);
1556 ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1557 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
1562 case SILC_ID_SERVER:
1563 entry = silc_idlist_find_server_by_id(server->local_list,
1565 if (!entry && check_global)
1566 entry = silc_idlist_find_server_by_id(server->global_list,
1569 *servers = silc_realloc(*servers, sizeof(**servers) *
1570 (*servers_count + 1));
1571 (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
1573 /* If we are normal server and have not resolved information from
1574 router yet, do so now. */
1575 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1576 server->server_type == SILC_SERVER && !cmd->pending &&
1577 !server->standalone) {
1578 silc_server_command_identify_send_router(cmd);
1579 silc_free(*clients);
1580 silc_free(*servers);
1581 silc_free(*channels);
1582 silc_free(*error_id);
1586 ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1587 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
1591 case SILC_ID_CHANNEL:
1592 entry = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
1593 if (!entry && check_global)
1594 entry = silc_idlist_find_channel_by_id(server->global_list, id,
1597 *channels = silc_realloc(*channels, sizeof(**channels) *
1598 (*channels_count + 1));
1599 (*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
1601 /* If we are normal server and have not resolved information from
1602 router yet, do so now. */
1603 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1604 server->server_type == SILC_SERVER && !cmd->pending &&
1605 !server->standalone) {
1606 silc_server_command_identify_send_router(cmd);
1607 silc_free(*clients);
1608 silc_free(*servers);
1609 silc_free(*channels);
1610 silc_free(*error_id);
1614 ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1615 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID);
1624 /* Get the max count of reply messages allowed */
1625 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1627 SILC_GET32_MSB(*count, tmp);
1634 /* Checks that all mandatory fields in client entry are present. If not
1635 then send WHOIS request to the server who owns the client. We use
1636 WHOIS because we want to get as much information as possible at once. */
1639 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1640 SilcClientEntry *clients,
1641 SilcUInt32 clients_count)
1643 SilcServer server = cmd->server;
1644 SilcClientEntry entry;
1645 SilcServerResolveContext resolve = NULL, r = NULL;
1646 SilcUInt32 resolve_count = 0;
1650 for (i = 0; i < clients_count; i++) {
1655 if (entry->nickname ||
1656 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1660 /* If we are normal server, and we've not resolved this client from
1661 router and it is global client, we'll check whether it is on some
1662 channel. If not then we cannot be sure about its validity, and
1663 we'll resolve it from router. */
1664 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
1665 entry->connection || silc_hash_table_count(entry->channels))
1669 /* We need to resolve this entry since it is not complete */
1671 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1672 /* The entry is being resolved (and we are not the resolver) so attach
1673 to the command reply and we're done with this one. */
1674 silc_server_command_pending(server, SILC_COMMAND_NONE,
1675 entry->resolve_cmd_ident,
1676 silc_server_command_identify,
1677 silc_server_command_dup(cmd));
1680 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1681 /* We've resolved this and it still is not ready. We'll return
1682 and are that this will be handled again after it is resolved. */
1683 for (i = 0; i < resolve_count; i++) {
1684 for (k = 0; k < r->res_argc; k++)
1685 silc_free(r->res_argv[k]);
1686 silc_free(r->res_argv);
1687 silc_free(r->res_argv_lens);
1688 silc_free(r->res_argv_types);
1693 /* We'll resolve this client */
1697 for (k = 0; k < resolve_count; k++) {
1698 if (resolve[k].router == entry->router) {
1705 resolve = silc_realloc(resolve, sizeof(*resolve) *
1706 (resolve_count + 1));
1707 r = &resolve[resolve_count];
1708 memset(r, 0, sizeof(*r));
1709 r->router = entry->router;
1710 r->ident = ++server->cmd_ident;
1714 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1716 r->res_argv_lens = silc_realloc(r->res_argv_lens,
1717 sizeof(*r->res_argv_lens) *
1719 r->res_argv_types = silc_realloc(r->res_argv_types,
1720 sizeof(*r->res_argv_types) *
1722 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1723 r->res_argv[r->res_argc] = silc_calloc(idp->len,
1724 sizeof(**r->res_argv));
1725 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1726 r->res_argv_lens[r->res_argc] = idp->len;
1727 r->res_argv_types[r->res_argc] = r->res_argc + 4;
1729 silc_buffer_free(idp);
1731 entry->resolve_cmd_ident = r->ident;
1732 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1733 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1738 /* Do the resolving */
1739 for (i = 0; i < resolve_count; i++) {
1744 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1745 now anyway so make it a good one. */
1746 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1747 r->res_argc, r->res_argv,
1751 silc_server_packet_send(server, r->router->connection,
1752 SILC_PACKET_COMMAND, cmd->packet->flags,
1753 res_cmd->data, res_cmd->len, FALSE);
1755 /* Reprocess this packet after received reply */
1756 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1758 silc_server_command_identify,
1759 silc_server_command_dup(cmd));
1760 cmd->pending = TRUE;
1762 silc_buffer_free(res_cmd);
1763 for (k = 0; k < r->res_argc; k++)
1764 silc_free(r->res_argv[k]);
1765 silc_free(r->res_argv);
1766 silc_free(r->res_argv_lens);
1767 silc_free(r->res_argv_types);
1776 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1777 SilcClientEntry *clients,
1778 SilcUInt32 clients_count,
1779 SilcServerEntry *servers,
1780 SilcUInt32 servers_count,
1781 SilcChannelEntry *channels,
1782 SilcUInt32 channels_count,
1783 ResolveError errors,
1784 SilcUInt32 errors_count,
1787 SilcServer server = cmd->server;
1788 int i, k, valid_count;
1790 SilcBuffer packet, idp;
1792 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1793 char nh[256], uh[256];
1794 SilcSocketConnection hsock;
1797 status = SILC_STATUS_OK;
1800 SilcClientEntry entry;
1801 valid_count = clients_count;
1803 if (silc_argument_get_arg_type(cmd->args, 1, NULL)) {
1804 /* Process only valid clients and ignore those that are not registered.
1805 This is checked with nickname only because when resolved client IDs
1806 we check that they are registered earlier. */
1808 for (i = 0; i < clients_count; i++) {
1809 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1816 /* No valid entries found at all, just send error */
1817 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1818 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1819 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1820 3, tmp, tmp ? strlen(tmp) : 0);
1825 /* Process all valid client entries and send command replies */
1827 if (valid_count > 1)
1828 status = SILC_STATUS_LIST_START;
1830 for (i = 0, k = 0; i < clients_count; i++) {
1836 status = SILC_STATUS_LIST_ITEM;
1837 if (valid_count > 1 && k == valid_count - 1
1838 && !servers_count && !channels_count && !errors_count)
1839 status = SILC_STATUS_LIST_END;
1840 if (count && k - 1 == count)
1841 status = SILC_STATUS_LIST_END;
1843 /* Send IDENTIFY reply */
1845 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1846 memset(uh, 0, sizeof(uh));
1847 memset(nh, 0, sizeof(nh));
1848 strncat(nh, entry->nickname, strlen(entry->nickname));
1849 if (!strchr(entry->nickname, '@')) {
1850 strncat(nh, "@", 1);
1851 if (entry->servername) {
1852 strncat(nh, entry->servername, strlen(entry->servername));
1854 len = entry->router ? strlen(entry->router->server_name) :
1855 strlen(server->server_name);
1856 strncat(nh, entry->router ? entry->router->server_name :
1857 server->server_name, len);
1861 if (!entry->username) {
1862 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1863 status, 0, ident, 2,
1864 2, idp->data, idp->len,
1867 strncat(uh, entry->username, strlen(entry->username));
1868 if (!strchr(entry->username, '@') && entry->connection) {
1869 strncat(uh, "@", 1);
1870 hsock = (SilcSocketConnection)entry->connection;
1871 len = strlen(hsock->hostname);
1872 strncat(uh, hsock->hostname, len);
1875 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1876 status, 0, ident, 3,
1877 2, idp->data, idp->len,
1882 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1883 0, packet->data, packet->len, FALSE);
1885 silc_buffer_free(packet);
1886 silc_buffer_free(idp);
1888 if (status == SILC_STATUS_LIST_END)
1895 SilcServerEntry entry;
1897 if (status == SILC_STATUS_OK && servers_count > 1)
1898 status = SILC_STATUS_LIST_START;
1900 for (i = 0, k = 0; i < servers_count; i++) {
1904 status = SILC_STATUS_LIST_ITEM;
1905 if (servers_count > 1 && k == servers_count - 1 && !channels_count &&
1907 status = SILC_STATUS_LIST_END;
1908 if (count && k - 1 == count)
1909 status = SILC_STATUS_LIST_END;
1911 /* Send IDENTIFY reply */
1912 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1914 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1915 status, 0, ident, 2,
1916 2, idp->data, idp->len,
1917 3, entry->server_name,
1918 entry->server_name ?
1919 strlen(entry->server_name) : 0);
1920 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1921 0, packet->data, packet->len, FALSE);
1923 silc_buffer_free(packet);
1924 silc_buffer_free(idp);
1926 if (status == SILC_STATUS_LIST_END)
1933 SilcChannelEntry entry;
1935 if (status == SILC_STATUS_OK && channels_count > 1)
1936 status = SILC_STATUS_LIST_START;
1938 for (i = 0, k = 0; i < channels_count; i++) {
1939 entry = channels[i];
1942 status = SILC_STATUS_LIST_ITEM;
1943 if (channels_count > 1 && k == channels_count - 1 && !errors_count)
1944 status = SILC_STATUS_LIST_END;
1945 if (count && k - 1 == count)
1946 status = SILC_STATUS_LIST_END;
1948 /* Send IDENTIFY reply */
1949 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1951 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1952 status, 0, ident, 2,
1953 2, idp->data, idp->len,
1954 3, entry->channel_name,
1955 entry->channel_name ?
1956 strlen(entry->channel_name): 0);
1957 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1958 0, packet->data, packet->len, FALSE);
1960 silc_buffer_free(packet);
1961 silc_buffer_free(idp);
1963 if (status == SILC_STATUS_LIST_END)
1969 /* Send error replies */
1971 if (status == SILC_STATUS_OK && errors_count > 1)
1972 status = SILC_STATUS_LIST_START;
1975 for (i = 0, k = 0; i < errors_count; i++) {
1977 idp = silc_id_payload_encode(errors[i].id, SILC_ID_CLIENT);
1981 tmp = silc_argument_get_arg_type(cmd->args, errors[i].index, &len);
1985 status = SILC_STATUS_LIST_ITEM;
1986 if (errors_count > 1 && k == errors_count - 1)
1987 status = SILC_STATUS_LIST_END;
1988 if (count && k - 1 == count)
1989 status = SILC_STATUS_LIST_END;
1992 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1993 (status == SILC_STATUS_OK ?
1994 errors[i].error : status),
1995 (status == SILC_STATUS_OK ?
1996 0 : errors[i].error),
1998 silc_buffer_free(idp);
2001 if (status == SILC_STATUS_LIST_END)
2009 silc_server_command_identify_process(SilcServerCommandContext cmd)
2011 SilcUInt32 count = 0;
2013 SilcClientEntry *clients = NULL;
2014 SilcServerEntry *servers = NULL;
2015 SilcChannelEntry *channels = NULL;
2016 SilcUInt32 clients_count = 0, servers_count = 0, channels_count = 0;
2017 SilcUInt32 errors_count = 0;
2018 ResolveError errors = NULL;
2020 /* Parse the IDENTIFY request */
2021 ret = silc_server_command_identify_parse(cmd,
2022 &clients, &clients_count,
2023 &servers, &servers_count,
2024 &channels, &channels_count,
2025 &count, &errors, &errors_count);
2030 /* Check that all mandatory fields are present and request those data
2031 from the server who owns the client if necessary. */
2032 if (!silc_server_command_identify_check_client(cmd, clients,
2038 /* Send the command reply to the client */
2039 silc_server_command_identify_send_reply(cmd,
2040 clients, clients_count,
2041 servers, servers_count,
2042 channels, channels_count,
2043 errors, errors_count,
2049 silc_free(channels);
2054 SILC_SERVER_CMD_FUNC(identify)
2056 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2059 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
2061 ret = silc_server_command_identify_process(cmd);
2062 silc_server_command_free(cmd);
2065 /* Server side of command NICK. Sets nickname for user. Setting
2066 nickname causes generation of a new client ID for the client. The
2067 new client ID is sent to the client after changing the nickname. */
2069 SILC_SERVER_CMD_FUNC(nick)
2071 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2072 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2073 SilcServer server = cmd->server;
2074 SilcBuffer packet, nidp, oidp = NULL;
2075 SilcClientID *new_id;
2076 SilcUInt32 nick_len;
2078 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2081 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2084 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
2086 /* Check nickname */
2087 nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
2090 if (silc_server_name_bad_chars(nick, nick_len) == TRUE) {
2091 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2092 SILC_STATUS_ERR_BAD_NICKNAME, 0);
2096 /* Check for same nickname */
2097 if (!strcmp(client->nickname, nick)) {
2098 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2102 /* Create new Client ID */
2103 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
2105 cmd->server->md5hash, nick,
2109 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2110 SILC_STATUS_ERR_BAD_NICKNAME, 0);
2113 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2116 /* Send notify about nickname change to our router. We send the new
2117 ID and ask to replace it with the old one. If we are router the
2118 packet is broadcasted. Send NICK_CHANGE notify. */
2119 silc_server_send_notify_nick_change(server, SILC_PRIMARY_ROUTE(server),
2120 SILC_BROADCAST(server), client->id,
2123 /* Check if anyone is watching the old nickname */
2124 if (server->server_type == SILC_ROUTER)
2125 silc_server_check_watcher_list(server, client, nick,
2126 SILC_NOTIFY_TYPE_NICK_CHANGE);
2128 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2130 /* Remove old cache entry */
2131 silc_idcache_del_by_context(server->local_list->clients, client);
2133 silc_free(client->id);
2134 client->id = new_id;
2136 silc_free(client->nickname);
2137 client->nickname = strdup(nick);
2139 /* Update client cache */
2140 silc_idcache_add(server->local_list->clients, client->nickname,
2141 client->id, (void *)client, 0, NULL);
2143 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2145 /* Send NICK_CHANGE notify to the client's channels */
2146 silc_server_send_notify_on_channels(server, NULL, client,
2147 SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
2148 oidp->data, oidp->len,
2149 nidp->data, nidp->len,
2151 strlen(client->nickname));
2153 /* Check if anyone is watching the new nickname */
2154 if (server->server_type == SILC_ROUTER)
2155 silc_server_check_watcher_list(server, client, NULL,
2156 SILC_NOTIFY_TYPE_NICK_CHANGE);
2159 /* Send the new Client ID as reply command back to client */
2160 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
2161 SILC_STATUS_OK, 0, ident, 2,
2162 2, nidp->data, nidp->len,
2163 3, nick, strlen(nick));
2164 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2165 0, packet->data, packet->len, FALSE);
2167 silc_buffer_free(packet);
2168 silc_buffer_free(nidp);
2170 silc_buffer_free(oidp);
2173 silc_server_command_free(cmd);
2176 /* Sends the LIST command reply */
2179 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2180 SilcChannelEntry *lch,
2181 SilcUInt32 lch_count,
2182 SilcChannelEntry *gch,
2183 SilcUInt32 gch_count)
2186 SilcBuffer packet, idp;
2187 SilcChannelEntry entry;
2189 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2191 unsigned char usercount[4];
2193 int valid_lcount = 0, valid_rcount = 0;
2195 for (i = 0; i < lch_count; i++) {
2196 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2201 for (i = 0; i < gch_count; i++) {
2202 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2208 status = SILC_STATUS_OK;
2209 if ((lch_count + gch_count) > 1)
2210 status = SILC_STATUS_LIST_START;
2213 for (i = 0, k = 0; i < lch_count; i++) {
2219 status = SILC_STATUS_LIST_ITEM;
2220 if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
2221 status = SILC_STATUS_LIST_END;
2223 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2225 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2226 topic = "*private*";
2227 memset(usercount, 0, sizeof(usercount));
2229 topic = entry->topic;
2230 users = silc_hash_table_count(entry->user_list);
2231 SILC_PUT32_MSB(users, usercount);
2234 /* Send the reply */
2236 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2237 status, 0, ident, 4,
2238 2, idp->data, idp->len,
2239 3, entry->channel_name,
2240 strlen(entry->channel_name),
2241 4, topic, topic ? strlen(topic) : 0,
2243 silc_server_packet_send(cmd->server, cmd->sock,
2244 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2245 packet->len, FALSE);
2246 silc_buffer_free(packet);
2247 silc_buffer_free(idp);
2252 for (i = 0, k = 0; i < gch_count; i++) {
2258 status = SILC_STATUS_LIST_ITEM;
2259 if (valid_rcount > 1 && k == valid_rcount - 1)
2260 status = SILC_STATUS_LIST_END;
2262 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2264 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2265 topic = "*private*";
2266 memset(usercount, 0, sizeof(usercount));
2268 topic = entry->topic;
2269 users = entry->user_count;
2270 SILC_PUT32_MSB(users, usercount);
2273 /* Send the reply */
2275 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2276 status, 0, ident, 4,
2277 2, idp->data, idp->len,
2278 3, entry->channel_name,
2279 strlen(entry->channel_name),
2280 4, topic, topic ? strlen(topic) : 0,
2282 silc_server_packet_send(cmd->server, cmd->sock,
2283 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2284 packet->len, FALSE);
2285 silc_buffer_free(packet);
2286 silc_buffer_free(idp);
2291 /* Server side of LIST command. This lists the channel of the requested
2292 server. Secret channels are not listed. */
2294 SILC_SERVER_CMD_FUNC(list)
2296 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2297 SilcServer server = cmd->server;
2298 SilcChannelID *channel_id = NULL;
2301 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2302 SilcUInt32 lch_count = 0, gch_count = 0;
2304 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2306 /* If we are normal server, send the command to router, since we
2307 want to know all channels in the network. */
2308 if (!cmd->pending && server->server_type == SILC_SERVER &&
2309 !server->standalone) {
2311 SilcUInt16 old_ident;
2313 old_ident = silc_command_get_ident(cmd->payload);
2314 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2315 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2316 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
2317 SILC_PACKET_COMMAND, cmd->packet->flags,
2318 tmpbuf->data, tmpbuf->len, TRUE);
2320 /* Reprocess this packet after received reply from router */
2321 silc_server_command_pending(server, SILC_COMMAND_LIST,
2322 silc_command_get_ident(cmd->payload),
2323 silc_server_command_list,
2324 silc_server_command_dup(cmd));
2325 cmd->pending = TRUE;
2326 silc_command_set_ident(cmd->payload, old_ident);
2327 silc_buffer_free(tmpbuf);
2331 /* Get Channel ID */
2332 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2334 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2336 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2337 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2342 /* Get the channels from local list */
2343 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2346 /* Get the channels from global list */
2347 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2350 /* Send the reply */
2351 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2352 gchannels, gch_count);
2354 silc_free(lchannels);
2355 silc_free(gchannels);
2358 silc_server_command_free(cmd);
2361 /* Server side of TOPIC command. Sets topic for channel and/or returns
2362 current topic to client. */
2364 SILC_SERVER_CMD_FUNC(topic)
2366 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2367 SilcServer server = cmd->server;
2368 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2369 SilcChannelID *channel_id;
2370 SilcChannelEntry channel;
2371 SilcChannelClientEntry chl;
2372 SilcBuffer packet, idp;
2374 SilcUInt32 argc, tmp_len;
2375 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2377 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2379 argc = silc_argument_get_arg_num(cmd->args);
2381 /* Get Channel ID */
2382 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2384 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2385 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2388 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2390 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2391 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2395 /* Check whether the channel exists */
2396 channel = silc_idlist_find_channel_by_id(server->local_list,
2399 channel = silc_idlist_find_channel_by_id(server->global_list,
2402 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2403 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
2411 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2413 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2414 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2419 if (strlen(tmp) > 256) {
2420 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2421 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2426 /* See whether the client is on channel and has rights to change topic */
2427 if (!silc_server_client_on_channel(client, channel, &chl)) {
2428 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2429 SILC_STATUS_ERR_NOT_ON_CHANNEL,
2434 if (channel->mode & SILC_CHANNEL_MODE_TOPIC &&
2435 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
2436 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
2437 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2438 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
2443 if (!channel->topic || strcmp(channel->topic, tmp)) {
2444 /* Set the topic for channel */
2445 silc_free(channel->topic);
2446 channel->topic = strdup(tmp);
2448 /* Send TOPIC_SET notify type to the network */
2449 silc_server_send_notify_topic_set(server, SILC_PRIMARY_ROUTE(server),
2450 SILC_BROADCAST(server), channel,
2451 client->id, SILC_ID_CLIENT,
2454 /* Send notify about topic change to all clients on the channel */
2455 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2456 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2457 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2458 idp->data, idp->len,
2460 strlen(channel->topic));
2461 silc_buffer_free(idp);
2465 /* Send the topic to client as reply packet */
2466 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2467 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2468 SILC_STATUS_OK, 0, ident, 2,
2469 2, idp->data, idp->len,
2472 strlen(channel->topic) : 0);
2473 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2474 0, packet->data, packet->len, FALSE);
2476 silc_buffer_free(packet);
2477 silc_buffer_free(idp);
2478 silc_free(channel_id);
2481 silc_server_command_free(cmd);
2484 /* Server side of INVITE command. Invites some client to join some channel.
2485 This command is also used to manage the invite list of the channel. */
2487 SILC_SERVER_CMD_FUNC(invite)
2489 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2490 SilcServer server = cmd->server;
2491 SilcSocketConnection sock = cmd->sock, dest_sock;
2492 SilcChannelClientEntry chl;
2493 SilcClientEntry sender, dest;
2494 SilcClientID *dest_id = NULL;
2495 SilcChannelEntry channel;
2496 SilcChannelID *channel_id = NULL;
2497 SilcIDListData idata;
2498 SilcBuffer idp, idp2, packet;
2499 unsigned char *tmp, *add, *del;
2501 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2503 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2505 /* Get Channel ID */
2506 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2508 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2509 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2512 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
2514 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2515 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2519 /* Get the channel entry */
2520 channel = silc_idlist_find_channel_by_id(server->local_list,
2523 channel = silc_idlist_find_channel_by_id(server->global_list,
2526 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2527 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
2533 /* Check whether the sender of this command is on the channel. */
2534 sender = (SilcClientEntry)sock->user_data;
2535 if (!silc_server_client_on_channel(sender, channel, &chl)) {
2536 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2537 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
2541 /* Check whether the channel is invite-only channel. If yes then the
2542 sender of this command must be at least channel operator. */
2543 if (channel->mode & SILC_CHANNEL_MODE_INVITE &&
2544 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
2545 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
2546 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2547 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
2552 /* Get destination client ID */
2553 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2558 dest_id = silc_id_payload_parse_id(tmp, len, NULL);
2560 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2561 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
2565 /* Get the client entry */
2566 dest = silc_server_get_client_resolve(server, dest_id, FALSE, &resolve);
2568 if (server->server_type != SILC_SERVER || !resolve) {
2569 silc_server_command_send_status_reply(
2570 cmd, SILC_COMMAND_INVITE,
2571 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0);
2575 /* The client info is being resolved. Reprocess this packet after
2576 receiving the reply to the query. */
2577 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2579 silc_server_command_invite,
2580 silc_server_command_dup(cmd));
2581 cmd->pending = TRUE;
2582 silc_free(channel_id);
2587 /* Check whether the requested client is already on the channel. */
2588 if (silc_server_client_on_channel(dest, channel, NULL)) {
2589 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2590 SILC_STATUS_ERR_USER_ON_CHANNEL,
2595 /* Get route to the client */
2596 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id,
2599 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2600 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2605 memset(invite, 0, sizeof(invite));
2606 strncat(invite, dest->nickname, strlen(dest->nickname));
2607 strncat(invite, "!", 1);
2608 strncat(invite, dest->username, strlen(dest->username));
2609 if (!strchr(dest->username, '@')) {
2610 strncat(invite, "@", 1);
2611 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2614 len = strlen(invite);
2615 if (!channel->invite_list)
2616 channel->invite_list = silc_calloc(len + 2,
2617 sizeof(*channel->invite_list));
2619 channel->invite_list = silc_realloc(channel->invite_list,
2620 sizeof(*channel->invite_list) *
2622 strlen(channel->invite_list) + 2));
2623 strncat(channel->invite_list, invite, len);
2624 strncat(channel->invite_list, ",", 1);
2626 if (!(dest->mode & SILC_UMODE_BLOCK_INVITE)) {
2627 /* Send notify to the client that is invited to the channel */
2628 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2629 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2630 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2632 SILC_NOTIFY_TYPE_INVITE, 3,
2633 idp->data, idp->len,
2634 channel->channel_name,
2635 strlen(channel->channel_name),
2636 idp2->data, idp2->len);
2637 silc_buffer_free(idp);
2638 silc_buffer_free(idp2);
2642 /* Add the client to the invite list of the channel */
2643 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2645 if (!channel->invite_list)
2646 channel->invite_list = silc_calloc(len + 2,
2647 sizeof(*channel->invite_list));
2649 channel->invite_list = silc_realloc(channel->invite_list,
2650 sizeof(*channel->invite_list) *
2652 strlen(channel->invite_list) + 2));
2653 if (add[len - 1] == ',')
2654 add[len - 1] = '\0';
2656 strncat(channel->invite_list, add, len);
2657 strncat(channel->invite_list, ",", 1);
2660 /* Get the invite to be removed and remove it from the list */
2661 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2662 if (del && channel->invite_list) {
2663 char *start, *end, *n;
2665 if (!strncmp(channel->invite_list, del,
2666 strlen(channel->invite_list) - 1)) {
2667 silc_free(channel->invite_list);
2668 channel->invite_list = NULL;
2670 start = strstr(channel->invite_list, del);
2671 if (start && strlen(start) >= len) {
2673 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2674 strncat(n, channel->invite_list, start - channel->invite_list);
2675 strncat(n, end + 1, ((channel->invite_list +
2676 strlen(channel->invite_list)) - end) - 1);
2677 silc_free(channel->invite_list);
2678 channel->invite_list = n;
2683 /* Send notify to the primary router */
2684 silc_server_send_notify_invite(server, SILC_PRIMARY_ROUTE(server),
2685 SILC_BROADCAST(server), channel,
2686 sender->id, add, del);
2688 /* Send command reply */
2689 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2693 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2694 SILC_STATUS_OK, 0, ident, 2,
2696 3, channel->invite_list,
2697 channel->invite_list ?
2698 strlen(channel->invite_list) : 0);
2701 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2702 SILC_STATUS_OK, 0, ident, 1,
2704 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2705 packet->data, packet->len, FALSE);
2706 silc_buffer_free(packet);
2710 silc_free(channel_id);
2711 silc_server_command_free(cmd);
2716 SilcSocketConnection sock;
2720 /* Quits connection to client. This gets called if client won't
2721 close the connection even when it has issued QUIT command. */
2723 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2725 QuitInternal q = (QuitInternal)context;
2727 /* Free all client specific data, such as client entry and entires
2728 on channels this client may be on. */
2729 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2731 q->sock->user_data = NULL;
2733 /* Close the connection on our side */
2734 silc_server_close_connection(q->server, q->sock);
2736 silc_free(q->signoff);
2740 /* Quits SILC session. This is the normal way to disconnect client. */
2742 SILC_SERVER_CMD_FUNC(quit)
2744 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2745 SilcServer server = cmd->server;
2746 SilcSocketConnection sock = cmd->sock;
2748 unsigned char *tmp = NULL;
2751 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2753 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2757 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2761 q = silc_calloc(1, sizeof(*q));
2764 q->signoff = tmp ? strdup(tmp) : NULL;
2766 /* We quit the connection with little timeout */
2767 silc_schedule_task_add(server->schedule, sock->sock,
2768 silc_server_command_quit_cb, (void *)q,
2769 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2772 silc_server_command_free(cmd);
2775 /* Server side of command KILL. This command is used by router operator
2776 to remove an client from the SILC Network temporarily. */
2778 SILC_SERVER_CMD_FUNC(kill)
2780 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2781 SilcServer server = cmd->server;
2782 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2783 SilcClientEntry remote_client;
2784 SilcClientID *client_id;
2785 unsigned char *tmp, *comment;
2786 SilcUInt32 tmp_len, tmp_len2;
2789 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2791 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2794 /* KILL command works only on router */
2795 if (server->server_type != SILC_ROUTER) {
2796 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2797 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
2801 /* Check whether client has the permissions. */
2802 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2803 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2804 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
2808 /* Get the client ID */
2809 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2811 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2812 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2816 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2818 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2819 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2824 /* Get the client entry */
2825 remote_client = silc_idlist_find_client_by_id(server->local_list,
2826 client_id, TRUE, NULL);
2828 if (!remote_client) {
2829 remote_client = silc_idlist_find_client_by_id(server->global_list,
2830 client_id, TRUE, NULL);
2832 if (!remote_client) {
2833 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2834 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2841 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2845 /* Send reply to the sender */
2846 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2849 /* Check if anyone is watching this nickname */
2850 if (server->server_type == SILC_ROUTER)
2851 silc_server_check_watcher_list(server, client, NULL,
2852 SILC_NOTIFY_TYPE_KILLED);
2854 /* Now do the killing */
2855 silc_server_kill_client(server, remote_client, comment, client->id,
2859 silc_server_command_free(cmd);
2862 /* Server side of command INFO. This sends information about us to
2863 the client. If client requested specific server we will send the
2864 command to that server. */
2866 SILC_SERVER_CMD_FUNC(info)
2868 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2869 SilcServer server = cmd->server;
2870 SilcBuffer packet, idp;
2873 char *dest_server, *server_info = NULL, *server_name;
2874 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2875 SilcServerEntry entry = NULL;
2876 SilcServerID *server_id = NULL;
2878 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2880 /* Get server name */
2881 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2884 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2886 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2888 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2889 SILC_STATUS_ERR_NO_SERVER_ID, 0);
2895 /* Check whether we have this server cached */
2896 entry = silc_idlist_find_server_by_id(server->local_list,
2897 server_id, TRUE, NULL);
2899 entry = silc_idlist_find_server_by_id(server->global_list,
2900 server_id, TRUE, NULL);
2901 if (!entry && server->server_type != SILC_SERVER) {
2902 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2903 SILC_STATUS_ERR_NO_SUCH_SERVER,
2910 /* Some buggy servers has sent request to router about themselves. */
2911 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2914 if ((!dest_server && !server_id && !entry) || (entry &&
2915 entry == server->id_entry) ||
2916 (dest_server && !cmd->pending &&
2917 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2918 /* Send our reply */
2919 char info_string[256];
2921 memset(info_string, 0, sizeof(info_string));
2922 snprintf(info_string, sizeof(info_string),
2923 "location: %s server: %s admin: %s <%s>",
2924 server->config->server_info->location,
2925 server->config->server_info->server_type,
2926 server->config->server_info->admin,
2927 server->config->server_info->email);
2929 server_info = info_string;
2930 entry = server->id_entry;
2932 /* Check whether we have this server cached */
2933 if (!entry && dest_server) {
2934 entry = silc_idlist_find_server_by_name(server->global_list,
2935 dest_server, TRUE, NULL);
2937 entry = silc_idlist_find_server_by_name(server->local_list,
2938 dest_server, TRUE, NULL);
2942 if (!cmd->pending &&
2943 server->server_type != SILC_SERVER && entry && !entry->server_info) {
2944 /* Send to the server */
2946 SilcUInt16 old_ident;
2948 old_ident = silc_command_get_ident(cmd->payload);
2949 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2950 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2952 silc_server_packet_send(server, entry->connection,
2953 SILC_PACKET_COMMAND, cmd->packet->flags,
2954 tmpbuf->data, tmpbuf->len, TRUE);
2956 /* Reprocess this packet after received reply from router */
2957 silc_server_command_pending(server, SILC_COMMAND_INFO,
2958 silc_command_get_ident(cmd->payload),
2959 silc_server_command_info,
2960 silc_server_command_dup(cmd));
2961 cmd->pending = TRUE;
2962 silc_command_set_ident(cmd->payload, old_ident);
2963 silc_buffer_free(tmpbuf);
2967 if (!entry && !cmd->pending && !server->standalone) {
2968 /* Send to the primary router */
2970 SilcUInt16 old_ident;
2972 old_ident = silc_command_get_ident(cmd->payload);
2973 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2974 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2976 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
2977 SILC_PACKET_COMMAND, cmd->packet->flags,
2978 tmpbuf->data, tmpbuf->len, TRUE);
2980 /* Reprocess this packet after received reply from router */
2981 silc_server_command_pending(server, SILC_COMMAND_INFO,
2982 silc_command_get_ident(cmd->payload),
2983 silc_server_command_info,
2984 silc_server_command_dup(cmd));
2985 cmd->pending = TRUE;
2986 silc_command_set_ident(cmd->payload, old_ident);
2987 silc_buffer_free(tmpbuf);
2992 silc_free(server_id);
2995 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2996 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3000 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
3002 server_info = entry->server_info;
3003 server_name = entry->server_name;
3005 /* Send the reply */
3006 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
3007 SILC_STATUS_OK, 0, ident, 3,
3008 2, idp->data, idp->len,
3010 strlen(server_name),
3013 strlen(server_info) : 0);
3014 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3015 packet->data, packet->len, FALSE);
3017 silc_buffer_free(packet);
3018 silc_buffer_free(idp);
3021 silc_server_command_free(cmd);
3024 /* Server side of command PING. This just replies to the ping. */
3026 SILC_SERVER_CMD_FUNC(ping)
3028 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3029 SilcServer server = cmd->server;
3034 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
3037 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
3039 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3040 SILC_STATUS_ERR_NO_SERVER_ID, 0);
3043 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
3047 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
3048 /* Send our reply */
3049 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3052 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3053 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3060 silc_server_command_free(cmd);
3063 /* Server side of command STATS. */
3065 SILC_SERVER_CMD_FUNC(stats)
3067 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3068 SilcServer server = cmd->server;
3069 SilcServerID *server_id;
3072 SilcBuffer packet, stats;
3073 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3076 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1);
3079 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3081 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3082 SILC_STATUS_ERR_NO_SERVER_ID, 0);
3085 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3089 /* The ID must be ours */
3090 if (!SILC_ID_SERVER_COMPARE(server->id, server_id)) {
3091 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3092 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3093 silc_free(server_id);
3096 silc_free(server_id);
3098 /* If we are router then just send everything we got. If we are normal
3099 server then we'll send this to our router to get all the latest
3100 statistical information. */
3101 if (!cmd->pending && server->server_type != SILC_ROUTER &&
3102 !server->standalone) {
3103 /* Send request to our router */
3104 SilcBuffer idp = silc_id_payload_encode(server->router->id,
3106 packet = silc_command_payload_encode_va(SILC_COMMAND_STATS,
3107 ++server->cmd_ident, 1,
3108 1, idp->data, idp->len);
3109 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
3110 SILC_PACKET_COMMAND, 0, packet->data,
3111 packet->len, FALSE);
3113 /* Reprocess this packet after received reply from router */
3114 silc_server_command_pending(server, SILC_COMMAND_STATS,
3116 silc_server_command_stats,
3117 silc_server_command_dup(cmd));
3118 cmd->pending = TRUE;
3119 silc_buffer_free(packet);
3120 silc_buffer_free(idp);
3124 /* Send our reply to sender */
3125 uptime = time(NULL) - server->starttime;
3127 stats = silc_buffer_alloc_size(60);
3128 silc_buffer_format(stats,
3129 SILC_STR_UI_INT(server->starttime),
3130 SILC_STR_UI_INT(uptime),
3131 SILC_STR_UI_INT(server->stat.my_clients),
3132 SILC_STR_UI_INT(server->stat.my_channels),
3133 SILC_STR_UI_INT(server->stat.my_server_ops),
3134 SILC_STR_UI_INT(server->stat.my_router_ops),
3135 SILC_STR_UI_INT(server->stat.cell_clients),
3136 SILC_STR_UI_INT(server->stat.cell_channels),
3137 SILC_STR_UI_INT(server->stat.cell_servers),
3138 SILC_STR_UI_INT(server->stat.clients),
3139 SILC_STR_UI_INT(server->stat.channels),
3140 SILC_STR_UI_INT(server->stat.servers),
3141 SILC_STR_UI_INT(server->stat.routers),
3142 SILC_STR_UI_INT(server->stat.server_ops),
3143 SILC_STR_UI_INT(server->stat.router_ops),
3146 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_STATS,
3147 SILC_STATUS_OK, 0, ident, 2,
3149 3, stats->data, stats->len);
3150 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
3151 0, packet->data, packet->len, FALSE);
3152 silc_buffer_free(packet);
3153 silc_buffer_free(stats);
3156 silc_server_command_free(cmd);
3159 /* Internal routine to join channel. The channel sent to this function
3160 has been either created or resolved from ID lists. This joins the sent
3161 client to the channel. */
3163 static void silc_server_command_join_channel(SilcServer server,
3164 SilcServerCommandContext cmd,
3165 SilcChannelEntry channel,
3166 SilcClientID *client_id,
3170 const unsigned char *auth,
3171 SilcUInt32 auth_len)
3173 SilcSocketConnection sock = cmd->sock;
3175 SilcUInt32 tmp_len, user_count;
3176 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
3177 SilcClientEntry client;
3178 SilcChannelClientEntry chl;
3179 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
3180 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3181 char check[512], check2[512];
3182 bool founder = FALSE;
3184 unsigned char *fkey = NULL;
3185 SilcUInt32 fkey_len = 0;
3187 SILC_LOG_DEBUG(("Joining client to channel"));
3192 /* Get the client entry */
3193 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3194 client = (SilcClientEntry)sock->user_data;
3196 client = silc_server_get_client_resolve(server, client_id, FALSE,
3203 silc_server_command_send_status_reply(
3204 cmd, SILC_COMMAND_JOIN,
3205 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3209 /* The client info is being resolved. Reprocess this packet after
3210 receiving the reply to the query. */
3211 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
3213 silc_server_command_join,
3214 silc_server_command_dup(cmd));
3215 cmd->pending = TRUE;
3219 cmd->pending = FALSE;
3223 * Check founder auth payload if provided. If client can gain founder
3224 * privileges it can override various conditions on joining the channel,
3225 * and can have directly the founder mode set on the channel.
3227 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3228 SilcIDListData idata = (SilcIDListData)client;
3229 SilcChannelClientEntry chl2;
3230 SilcHashTableList htl;
3232 if (channel->founder_key && idata->public_key &&
3233 silc_pkcs_public_key_compare(channel->founder_key,
3234 idata->public_key)) {
3235 /* Check whether the client is to become founder */
3236 if (silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
3237 channel->founder_key, 0, server->sha1hash,
3238 client->id, SILC_ID_CLIENT)) {
3240 /* There cannot be anyone else as founder on the channel now. This
3241 client is definitely the founder due to this authentication */
3242 silc_hash_table_list(channel->user_list, &htl);
3243 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
3244 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
3245 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3246 silc_server_force_cumode_change(server, NULL, channel, chl2,
3250 silc_hash_table_list_reset(&htl);
3252 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3259 * Check channel modes
3263 memset(check, 0, sizeof(check));
3264 memset(check2, 0, sizeof(check2));
3265 strncat(check, client->nickname, strlen(client->nickname));
3266 strncat(check, "!", 1);
3267 strncat(check, client->username, strlen(client->username));
3268 if (!strchr(client->username, '@')) {
3269 strncat(check, "@", 1);
3270 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3273 strncat(check2, client->nickname, strlen(client->nickname));
3274 if (!strchr(client->nickname, '@')) {
3275 strncat(check2, "@", 1);
3276 strncat(check2, server->server_name, strlen(server->server_name));
3278 strncat(check2, "!", 1);
3279 strncat(check2, client->username, strlen(client->username));
3280 if (!strchr(client->username, '@')) {
3281 strncat(check2, "@", 1);
3282 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3285 /* Check invite list if channel is invite-only channel */
3286 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3287 if (!channel->invite_list ||
3288 (!silc_string_match(channel->invite_list, check) &&
3289 !silc_string_match(channel->invite_list, check2))) {
3290 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3291 SILC_STATUS_ERR_NOT_INVITED, 0);
3296 /* Check ban list if it exists. If the client's nickname, server,
3297 username and/or hostname is in the ban list the access to the
3298 channel is denied. */
3299 if (channel->ban_list) {
3300 if (silc_string_match(channel->ban_list, check) ||
3301 silc_string_match(channel->ban_list, check2)) {
3302 silc_server_command_send_status_reply(
3303 cmd, SILC_COMMAND_JOIN,
3304 SILC_STATUS_ERR_BANNED_FROM_CHANNEL, 0);
3309 /* Check user count limit if set. */
3310 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3311 if (silc_hash_table_count(channel->user_list) + 1 >
3312 channel->user_limit) {
3313 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3314 SILC_STATUS_ERR_CHANNEL_IS_FULL,
3321 /* Check the channel passphrase if set. */
3322 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3323 /* Get passphrase */
3324 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3326 passphrase = silc_memdup(tmp, tmp_len);
3328 if (!passphrase || !channel->passphrase ||
3329 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3330 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3331 SILC_STATUS_ERR_BAD_PASSWORD, 0);
3337 * Client is allowed to join to the channel. Make it happen.
3340 /* Check whether the client already is on the channel */
3341 if (silc_server_client_on_channel(client, channel, NULL)) {
3342 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3343 SILC_STATUS_ERR_USER_ON_CHANNEL, 0);
3347 /* Generate new channel key as protocol dictates */
3349 if (!silc_server_create_channel_key(server, channel, 0))
3352 /* Send the channel key. This is broadcasted to the channel but is not
3353 sent to the client who is joining to the channel. */
3354 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3355 silc_server_send_channel_key(server, NULL, channel,
3356 server->server_type == SILC_ROUTER ?
3357 FALSE : !server->standalone);
3360 /* Join the client to the channel by adding it to channel's user list.
3361 Add also the channel to client entry's channels list for fast cross-
3363 chl = silc_calloc(1, sizeof(*chl));
3365 chl->client = client;
3366 chl->channel = channel;
3367 silc_hash_table_add(channel->user_list, client, chl);
3368 silc_hash_table_add(client->channels, channel, chl);
3369 channel->user_count++;
3370 channel->disabled = FALSE;
3372 /* Get users on the channel */
3373 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3376 /* Encode Client ID Payload of the original client who wants to join */
3377 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3379 /* Encode command reply packet */
3380 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3381 SILC_PUT32_MSB(channel->mode, mode);
3382 SILC_PUT32_MSB(created, tmp2);
3383 SILC_PUT32_MSB(user_count, tmp3);
3385 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3386 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3387 keyp = silc_channel_key_payload_encode(silc_id_get_len(channel->id,
3390 strlen(channel->channel_key->
3392 channel->channel_key->cipher->name,
3393 channel->key_len / 8, channel->key);
3397 if (channel->founder_key)
3398 fkey = silc_pkcs_public_key_encode(channel->founder_key, &fkey_len);
3401 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3402 SILC_STATUS_OK, 0, ident, 14,
3403 2, channel->channel_name,
3404 strlen(channel->channel_name),
3405 3, chidp->data, chidp->len,
3406 4, clidp->data, clidp->len,
3409 7, keyp ? keyp->data : NULL,
3410 keyp ? keyp->len : 0,
3411 8, channel->ban_list,
3413 strlen(channel->ban_list) : 0,
3414 9, channel->invite_list,
3415 channel->invite_list ?
3416 strlen(channel->invite_list) : 0,
3419 strlen(channel->topic) : 0,
3420 11, silc_hmac_get_name(channel->hmac),
3421 strlen(silc_hmac_get_name(channel->
3424 13, user_list->data, user_list->len,
3425 14, mode_list->data,
3427 15, fkey, fkey_len);
3429 /* Send command reply */
3430 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3431 reply->data, reply->len, FALSE);
3433 /* Send JOIN notify to locally connected clients on the channel. If
3434 we are normal server then router will send or have sent JOIN notify
3435 already. However since we've added the client already to our channel
3436 we'll ignore it (in packet_receive.c) so we must send it here. If
3437 we are router then this will send it to local clients and local
3439 SILC_LOG_DEBUG(("Send JOIN notify to channel"));
3440 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3441 SILC_NOTIFY_TYPE_JOIN, 2,
3442 clidp->data, clidp->len,
3443 chidp->data, chidp->len);
3445 /* Update statistics */
3446 server->stat.my_chanclients++;
3447 if (server->server_type == SILC_ROUTER) {
3448 server->stat.cell_chanclients++;
3449 server->stat.chanclients++;
3452 if (!cmd->pending) {
3453 /* Send JOIN notify packet to our primary router */
3454 silc_server_send_notify_join(server, SILC_PRIMARY_ROUTE(server),
3455 SILC_BROADCAST(server), channel, client->id);
3458 /* Distribute the channel key to all backup routers. */
3459 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3460 keyp->data, keyp->len, FALSE, TRUE);
3462 /* If client became founder by providing correct founder auth data
3463 notify the mode change to the channel. */
3465 SILC_PUT32_MSB(chl->mode, mode);
3466 SILC_LOG_DEBUG(("Send CUMODE_CHANGE notify to channel"));
3467 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3468 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
3469 clidp->data, clidp->len,
3470 mode, 4, clidp->data, clidp->len,
3475 /* Set CUMODE notify type to network */
3477 silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
3478 SILC_BROADCAST(server), channel,
3479 chl->mode, client->id, SILC_ID_CLIENT,
3480 client->id, channel->founder_key);
3482 silc_buffer_free(reply);
3483 silc_buffer_free(clidp);
3484 silc_buffer_free(chidp);
3485 silc_buffer_free(keyp);
3486 silc_buffer_free(user_list);
3487 silc_buffer_free(mode_list);
3491 silc_free(passphrase);
3494 /* Server side of command JOIN. Joins client into requested channel. If
3495 the channel does not exist it will be created. */
3497 SILC_SERVER_CMD_FUNC(join)
3499 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3500 SilcServer server = cmd->server;
3501 unsigned char *auth;
3502 SilcUInt32 tmp_len, auth_len;
3503 char *tmp, *channel_name = NULL, *cipher, *hmac;
3504 SilcChannelEntry channel;
3505 SilcUInt32 umode = 0;
3506 bool created = FALSE, create_key = TRUE;
3507 SilcClientID *client_id;
3509 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3511 /* Get channel name */
3512 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3514 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3515 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3522 channel_name[255] = '\0';
3524 if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
3525 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3526 SILC_STATUS_ERR_BAD_CHANNEL, 0);
3530 /* Get Client ID of the client who is joining to the channel */
3531 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3533 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3534 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3538 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3540 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3541 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3546 /* Get cipher, hmac name and auth payload */
3547 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3548 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3549 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3551 /* See if the channel exists */
3552 channel = silc_idlist_find_channel_by_name(server->local_list,
3553 channel_name, NULL);
3555 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3556 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3557 silc_free(client_id);
3558 client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
3561 (channel->disabled && server->server_type != SILC_ROUTER)) {
3562 /* Channel not found */
3564 /* If we are standalone server we don't have a router, we just create
3565 the channel by ourselves. */
3566 if (server->standalone) {
3567 channel = silc_server_create_new_channel(server, server->id, cipher,
3568 hmac, channel_name, TRUE);
3570 silc_server_command_send_status_reply(
3571 cmd, SILC_COMMAND_JOIN,
3572 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
3574 silc_free(client_id);
3578 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3584 /* The channel does not exist on our server. If we are normal server
3585 we will send JOIN command to our router which will handle the
3586 joining procedure (either creates the channel if it doesn't exist
3587 or joins the client to it). */
3588 if (server->server_type != SILC_ROUTER) {
3590 SilcUInt16 old_ident;
3592 /* If this is pending command callback then we've resolved
3593 it and it didn't work, return since we've notified the
3594 client already in the command reply callback. */
3596 silc_free(client_id);
3600 old_ident = silc_command_get_ident(cmd->payload);
3601 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3602 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3604 /* Send JOIN command to our router */
3605 silc_server_packet_send(server, (SilcSocketConnection)
3606 SILC_PRIMARY_ROUTE(server),
3607 SILC_PACKET_COMMAND, cmd->packet->flags,
3608 tmpbuf->data, tmpbuf->len, TRUE);
3610 /* Reprocess this packet after received reply from router */
3611 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3612 silc_command_get_ident(cmd->payload),
3613 silc_server_command_join,
3614 silc_server_command_dup(cmd));
3615 cmd->pending = TRUE;
3616 silc_command_set_ident(cmd->payload, old_ident);
3617 silc_buffer_free(tmpbuf);
3618 silc_free(client_id);
3622 /* We are router and the channel does not seem exist so we will check
3623 our global list as well for the channel. */
3624 channel = silc_idlist_find_channel_by_name(server->global_list,
3625 channel_name, NULL);
3627 /* Channel really does not exist, create it */
3628 channel = silc_server_create_new_channel(server, server->id, cipher,
3629 hmac, channel_name, TRUE);
3631 silc_server_command_send_status_reply(
3632 cmd, SILC_COMMAND_JOIN,
3633 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
3634 silc_free(client_id);
3638 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3646 /* Channel not found */
3648 /* If the command came from router and we are normal server then
3649 something went wrong with the joining as the channel was not found.
3650 We can't do anything else but ignore this. */
3651 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3652 server->server_type != SILC_ROUTER) {
3653 silc_free(client_id);
3657 /* We are router and the channel does not seem exist so we will check
3658 our global list as well for the channel. */
3659 channel = silc_idlist_find_channel_by_name(server->global_list,
3660 channel_name, NULL);
3662 /* Channel really does not exist, create it */
3663 channel = silc_server_create_new_channel(server, server->id, cipher,
3664 hmac, channel_name, TRUE);
3666 silc_server_command_send_status_reply(
3667 cmd, SILC_COMMAND_JOIN,
3668 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
3669 silc_free(client_id);
3673 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3680 /* Check whether the channel was created by our router */
3681 if (cmd->pending && context2) {
3682 SilcServerCommandReplyContext reply = context2;
3684 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3685 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3686 SILC_GET32_MSB(created, tmp);
3687 if (silc_argument_get_arg_type(reply->args, 7, NULL))
3688 create_key = FALSE; /* Router returned the key already */
3690 if (silc_command_get_status(reply->payload, NULL, NULL) &&
3691 channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3692 /* Save channel passphrase, if user provided it successfully */
3695 pa = silc_argument_get_arg_type(reply->args, 3, &pa_len);
3697 silc_free(channel->passphrase);
3698 channel->passphrase = silc_memdup(pa, pa_len);
3703 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
3704 !channel->disabled && !silc_hash_table_count(channel->user_list))
3708 /* If the channel does not have global users and is also empty the client
3709 will be the channel founder and operator. */
3710 if (!channel->disabled &&
3711 !channel->global_users && !silc_hash_table_count(channel->user_list))
3712 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3714 /* Join to the channel */
3715 silc_server_command_join_channel(server, cmd, channel, client_id,
3716 created, create_key, umode,
3719 silc_free(client_id);
3722 silc_server_command_free(cmd);
3725 /* Server side of command MOTD. Sends server's current "message of the
3726 day" to the client. */
3728 SILC_SERVER_CMD_FUNC(motd)
3730 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3731 SilcServer server = cmd->server;
3732 SilcBuffer packet, idp;
3733 char *motd, *dest_server;
3734 SilcUInt32 motd_len;
3735 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3737 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3739 /* Get server name */
3740 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3742 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3743 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3747 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3750 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3752 if (server->config && server->config->server_info &&
3753 server->config->server_info->motd_file) {
3755 motd = silc_file_readfile(server->config->server_info->motd_file,
3761 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3768 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3774 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3775 packet->data, packet->len, FALSE);
3776 silc_buffer_free(packet);
3777 silc_buffer_free(idp);
3779 SilcServerEntry entry;
3781 /* Check whether we have this server cached */
3782 entry = silc_idlist_find_server_by_name(server->global_list,
3783 dest_server, TRUE, NULL);
3785 entry = silc_idlist_find_server_by_name(server->local_list,
3786 dest_server, TRUE, NULL);
3789 if (server->server_type != SILC_SERVER && !cmd->pending &&
3790 entry && !entry->motd) {
3791 /* Send to the server */
3793 SilcUInt16 old_ident;
3795 old_ident = silc_command_get_ident(cmd->payload);
3796 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3797 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3799 silc_server_packet_send(server, entry->connection,
3800 SILC_PACKET_COMMAND, cmd->packet->flags,
3801 tmpbuf->data, tmpbuf->len, TRUE);
3803 /* Reprocess this packet after received reply from router */
3804 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3805 silc_command_get_ident(cmd->payload),
3806 silc_server_command_motd,
3807 silc_server_command_dup(cmd));
3808 cmd->pending = TRUE;
3809 silc_command_set_ident(cmd->payload, old_ident);
3810 silc_buffer_free(tmpbuf);
3814 if (!entry && !cmd->pending && !server->standalone) {
3815 /* Send to the primary router */
3817 SilcUInt16 old_ident;
3819 old_ident = silc_command_get_ident(cmd->payload);
3820 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3821 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3823 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
3824 SILC_PACKET_COMMAND, cmd->packet->flags,
3825 tmpbuf->data, tmpbuf->len, TRUE);
3827 /* Reprocess this packet after received reply from router */
3828 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3829 silc_command_get_ident(cmd->payload),
3830 silc_server_command_motd,
3831 silc_server_command_dup(cmd));
3832 cmd->pending = TRUE;
3833 silc_command_set_ident(cmd->payload, old_ident);
3834 silc_buffer_free(tmpbuf);
3839 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3840 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3844 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3845 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3846 SILC_STATUS_OK, 0, ident, 2,
3850 strlen(entry->motd) : 0);
3851 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3852 packet->data, packet->len, FALSE);
3853 silc_buffer_free(packet);
3854 silc_buffer_free(idp);
3858 silc_server_command_free(cmd);
3861 /* Server side of command UMODE. Client can use this command to set/unset
3862 user mode. Client actually cannot set itself to be as server/router
3863 operator so this can be used only to unset the modes. */
3865 SILC_SERVER_CMD_FUNC(umode)
3867 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3868 SilcServer server = cmd->server;
3869 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3871 unsigned char *tmp_mask, m[4];
3872 SilcUInt32 mask = 0;
3873 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3874 bool set_mask = FALSE;
3876 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3879 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2);
3881 /* Get the client's mode mask */
3882 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3884 SILC_GET32_MSB(mask, tmp_mask);
3889 /* Check that mode changing is allowed. */
3890 if (!silc_server_check_umode_rights(server, client, mask)) {
3891 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3892 SILC_STATUS_ERR_PERM_DENIED, 0);
3896 /* Anonymous mode cannot be set by client */
3897 if (mask & SILC_UMODE_ANONYMOUS) {
3898 if (!(client->mode & SILC_UMODE_ANONYMOUS)) {
3899 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3900 SILC_STATUS_ERR_PERM_DENIED, 0);
3904 if (client->mode & SILC_UMODE_ANONYMOUS) {
3905 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3906 SILC_STATUS_ERR_PERM_DENIED, 0);
3911 /* Update statistics */
3912 if (mask & SILC_UMODE_GONE) {
3913 if (!(client->mode & SILC_UMODE_GONE))
3914 server->stat.my_aways++;
3916 if (client->mode & SILC_UMODE_GONE)
3917 server->stat.my_aways--;
3920 /* Change the mode */
3921 client->mode = mask;
3923 /* Send UMODE change to primary router */
3924 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
3925 SILC_BROADCAST(server), client->id,
3928 /* Check if anyone is watching this nickname */
3929 if (server->server_type == SILC_ROUTER)
3930 silc_server_check_watcher_list(server, client, NULL,
3931 SILC_NOTIFY_TYPE_UMODE_CHANGE);
3934 /* Send command reply to sender */
3935 SILC_PUT32_MSB(client->mode, m);
3936 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3937 SILC_STATUS_OK, 0, ident, 1,
3939 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3940 packet->data, packet->len, FALSE);
3941 silc_buffer_free(packet);
3944 silc_server_command_free(cmd);
3947 /* Server side command of CMODE. Changes channel mode */
3949 SILC_SERVER_CMD_FUNC(cmode)
3951 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3952 SilcServer server = cmd->server;
3953 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3954 SilcIDListData idata = (SilcIDListData)client;
3955 SilcChannelID *channel_id = NULL;
3956 SilcChannelEntry channel;
3957 SilcChannelClientEntry chl;
3958 SilcBuffer packet, cidp;
3959 unsigned char *tmp, *tmp_id, *tmp_mask;
3960 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3961 SilcUInt32 mode_mask = 0, tmp_len, tmp_len2;
3962 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3963 bool set_mask = FALSE;
3964 SilcPublicKey founder_key = NULL;
3965 unsigned char *fkey = NULL;
3966 SilcUInt32 fkey_len = 0;
3968 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 7);
3970 /* Get Channel ID */
3971 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3973 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3974 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3977 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
3979 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3980 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3984 /* Get the channel mode mask */
3985 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3987 SILC_GET32_MSB(mode_mask, tmp_mask);
3991 /* Get channel entry */
3992 channel = silc_idlist_find_channel_by_id(server->local_list,
3995 channel = silc_idlist_find_channel_by_id(server->global_list,
3998 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3999 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4005 /* Check whether this client is on the channel */
4006 if (!silc_server_client_on_channel(client, channel, &chl)) {
4007 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4008 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4012 /* Check that client has rights to change any requested channel modes */
4013 if (set_mask && !silc_server_check_cmode_rights(server, channel, chl,
4015 SILC_LOG_DEBUG(("Client does not have rights to change mode"));
4016 silc_server_command_send_status_reply(
4017 cmd, SILC_COMMAND_CMODE,
4018 (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) ?
4019 SILC_STATUS_ERR_NO_CHANNEL_PRIV :
4020 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV), 0);
4024 /* If mode mask was not sent as argument then merely return the current
4025 mode mask to the sender. */
4028 SILC_PUT32_MSB(channel->mode, m);
4029 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4030 SILC_STATUS_OK, 0, ident, 2,
4031 2, tmp_id, tmp_len2,
4033 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4034 packet->data, packet->len, FALSE);
4035 silc_buffer_free(packet);
4040 * Check the modes. Modes that requires nothing special operation are
4044 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
4045 /* Channel uses private keys to protect traffic. Client(s) has set the
4046 key locally they want to use, server does not know that key. */
4047 /* Nothing interesting to do here */
4049 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
4050 /* The mode is removed and we need to generate and distribute
4051 new channel key. Clients are not using private channel keys
4052 anymore after this. */
4054 /* Re-generate channel key */
4055 if (!silc_server_create_channel_key(server, channel, 0))
4058 /* Send the channel key. This sends it to our local clients and if
4059 we are normal server to our router as well. */
4060 silc_server_send_channel_key(server, NULL, channel,
4061 server->server_type == SILC_ROUTER ?
4062 FALSE : !server->standalone);
4064 cipher = channel->channel_key->cipher->name;
4065 hmac = (char *)silc_hmac_get_name(channel->hmac);
4069 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
4070 /* User limit is set on channel */
4071 SilcUInt32 user_limit;
4073 /* Get user limit */
4074 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
4076 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
4077 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4078 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4082 SILC_GET32_MSB(user_limit, tmp);
4083 channel->user_limit = user_limit;
4086 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
4087 /* User limit mode is unset. Remove user limit */
4088 channel->user_limit = 0;
4091 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
4092 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
4093 /* Passphrase has been set to channel */
4095 /* Get the passphrase */
4096 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
4098 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4099 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4103 /* Save the passphrase */
4104 passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
4107 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
4108 /* Passphrase mode is unset. remove the passphrase */
4109 silc_free(channel->passphrase);
4110 channel->passphrase = NULL;
4114 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
4115 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
4116 /* Cipher to use protect the traffic */
4117 SilcCipher newkey, oldkey;
4120 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
4122 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4123 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4127 /* Delete old cipher and allocate the new one */
4128 if (!silc_cipher_alloc(cipher, &newkey)) {
4129 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4130 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4134 oldkey = channel->channel_key;
4135 channel->channel_key = newkey;
4137 /* Re-generate channel key */
4138 if (!silc_server_create_channel_key(server, channel, 0)) {
4139 /* We don't have new key, revert to old one */
4140 channel->channel_key = oldkey;
4144 /* Remove old channel key for good */
4145 silc_cipher_free(oldkey);
4147 /* Send the channel key. This sends it to our local clients and if
4148 we are normal server to our router as well. */
4149 silc_server_send_channel_key(server, NULL, channel,
4150 server->server_type == SILC_ROUTER ?
4151 FALSE : !server->standalone);
4154 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
4155 /* Cipher mode is unset. Remove the cipher and revert back to
4157 SilcCipher newkey, oldkey;
4158 cipher = channel->cipher;
4160 /* Delete old cipher and allocate default one */
4161 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
4162 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4163 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4167 oldkey = channel->channel_key;
4168 channel->channel_key = newkey;
4170 /* Re-generate channel key */
4171 if (!silc_server_create_channel_key(server, channel, 0)) {
4172 /* We don't have new key, revert to old one */
4173 channel->channel_key = oldkey;
4177 /* Remove old channel key for good */
4178 silc_cipher_free(oldkey);
4180 /* Send the channel key. This sends it to our local clients and if
4181 we are normal server to our router as well. */
4182 silc_server_send_channel_key(server, NULL, channel,
4183 server->server_type == SILC_ROUTER ?
4184 FALSE : !server->standalone);
4188 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
4189 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
4190 /* HMAC to use protect the traffic */
4191 unsigned char hash[32];
4195 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4197 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4198 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4202 /* Delete old hmac and allocate the new one */
4203 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4204 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4205 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4209 silc_hmac_free(channel->hmac);
4210 channel->hmac = newhmac;
4212 /* Set the HMAC key out of current channel key. The client must do
4214 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4215 channel->key_len / 8, hash);
4216 silc_hmac_set_key(channel->hmac, hash,
4217 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4218 memset(hash, 0, sizeof(hash));
4221 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4222 /* Hmac mode is unset. Remove the hmac and revert back to
4225 unsigned char hash[32];
4226 hmac = channel->hmac_name;
4228 /* Delete old hmac and allocate default one */
4229 silc_hmac_free(channel->hmac);
4230 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4231 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4232 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4236 silc_hmac_free(channel->hmac);
4237 channel->hmac = newhmac;
4239 /* Set the HMAC key out of current channel key. The client must do
4241 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4242 channel->key_len / 8,
4244 silc_hmac_set_key(channel->hmac, hash,
4245 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4246 memset(hash, 0, sizeof(hash));
4250 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4251 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4252 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4253 /* Set the founder authentication */
4254 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4256 silc_server_command_send_status_reply(
4257 cmd, SILC_COMMAND_CMODE,
4258 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4262 /* Verify the payload before setting the mode */
4263 if (!silc_auth_verify_data(tmp, tmp_len, SILC_AUTH_PUBLIC_KEY,
4264 idata->public_key, 0, server->sha1hash,
4265 client->id, SILC_ID_CLIENT)) {
4266 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4267 SILC_STATUS_ERR_AUTH_FAILED,
4272 /* Save the public key */
4273 channel->founder_key = silc_pkcs_public_key_copy(idata->public_key);
4274 if (!channel->founder_key) {
4275 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4276 SILC_STATUS_ERR_AUTH_FAILED,
4281 founder_key = channel->founder_key;
4282 fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
4284 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4285 SILC_STATUS_ERR_AUTH_FAILED,
4292 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4293 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4294 if (channel->founder_key)
4295 silc_pkcs_public_key_free(channel->founder_key);
4296 channel->founder_key = NULL;
4301 /* Finally, set the mode */
4302 channel->mode = mode_mask;
4304 /* Send CMODE_CHANGE notify. */
4305 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4306 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4307 SILC_NOTIFY_TYPE_CMODE_CHANGE, 6,
4308 cidp->data, cidp->len,
4310 cipher, cipher ? strlen(cipher) : 0,
4311 hmac, hmac ? strlen(hmac) : 0,
4312 passphrase, passphrase ?
4313 strlen(passphrase) : 0,
4316 /* Set CMODE notify type to network */
4317 silc_server_send_notify_cmode(server, SILC_PRIMARY_ROUTE(server),
4318 SILC_BROADCAST(server), channel,
4319 mode_mask, client->id, SILC_ID_CLIENT,
4320 cipher, hmac, passphrase, founder_key);
4322 /* Send command reply to sender */
4323 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4324 SILC_STATUS_OK, 0, ident, 2,
4325 2, tmp_id, tmp_len2,
4327 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4328 packet->data, packet->len, FALSE);
4330 silc_buffer_free(packet);
4331 silc_buffer_free(cidp);
4335 silc_free(channel_id);
4336 silc_server_command_free(cmd);
4339 /* Server side of CUMODE command. Changes client's mode on a channel. */
4341 SILC_SERVER_CMD_FUNC(cumode)
4343 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4344 SilcServer server = cmd->server;
4345 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4346 SilcIDListData idata = (SilcIDListData)client;
4347 SilcChannelID *channel_id;
4348 SilcClientID *client_id;
4349 SilcChannelEntry channel;
4350 SilcClientEntry target_client;
4351 SilcChannelClientEntry chl;
4352 SilcBuffer packet, idp;
4353 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4354 SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4356 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4357 SilcPublicKey founder_key = NULL;
4358 unsigned char *fkey = NULL;
4359 SilcUInt32 fkey_len = 0;
4361 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4363 /* Get Channel ID */
4364 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4366 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4367 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4370 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
4372 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4373 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4377 /* Get channel entry */
4378 channel = silc_idlist_find_channel_by_id(server->local_list,
4381 channel = silc_idlist_find_channel_by_id(server->global_list,
4384 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4385 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4391 /* Check whether sender is on the channel */
4392 if (!silc_server_client_on_channel(client, channel, &chl)) {
4393 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4394 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4397 sender_mask = chl->mode;
4399 /* Get the target client's channel mode mask */
4400 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4402 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4403 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4407 SILC_GET32_MSB(target_mask, tmp_mask);
4409 /* Get target Client ID */
4410 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4412 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4413 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4416 client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
4418 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4419 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4423 /* Get target client's entry */
4424 target_client = silc_idlist_find_client_by_id(server->local_list,
4425 client_id, TRUE, NULL);
4426 if (!target_client) {
4427 target_client = silc_idlist_find_client_by_id(server->global_list,
4428 client_id, TRUE, NULL);
4431 if (target_client != client &&
4432 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4433 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4434 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4435 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
4439 /* Check whether target client is on the channel */
4440 if (target_client != client) {
4441 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4442 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4443 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL, 0);
4452 /* If the target client is founder, no one else can change their mode
4454 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4455 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4456 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
4461 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4462 if (target_client != client) {
4463 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4464 SILC_STATUS_ERR_NOT_YOU, 0);
4468 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4469 /* The client tries to claim the founder rights. */
4470 unsigned char *tmp_auth;
4471 SilcUInt32 tmp_auth_len;
4472 SilcChannelClientEntry chl2;
4473 SilcHashTableList htl;
4475 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4476 !channel->founder_key || !idata->public_key ||
4477 !silc_pkcs_public_key_compare(channel->founder_key,
4478 idata->public_key)) {
4479 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4480 SILC_STATUS_ERR_AUTH_FAILED, 0);
4484 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4486 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4487 SILC_STATUS_ERR_AUTH_FAILED, 0);
4491 /* Verify the authentication payload */
4492 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len, SILC_AUTH_PUBLIC_KEY,
4493 channel->founder_key, 0, server->sha1hash,
4494 client->id, SILC_ID_CLIENT)) {
4495 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4496 SILC_STATUS_ERR_AUTH_FAILED, 0);
4501 founder_key = channel->founder_key;
4502 fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
4504 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4505 SILC_STATUS_ERR_AUTH_FAILED, 0);
4509 /* There cannot be anyone else as founder on the channel now. This
4510 client is definitely the founder due to this authentication */
4511 silc_hash_table_list(channel->user_list, &htl);
4512 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
4513 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
4514 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4515 silc_server_force_cumode_change(server, NULL, channel, chl2,
4519 silc_hash_table_list_reset(&htl);
4521 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4524 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4525 if (target_client == client) {
4526 /* Remove channel founder rights from itself */
4527 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4530 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4531 SILC_STATUS_ERR_NOT_YOU, 0);
4537 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4538 /* Promote to operator */
4539 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4540 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4541 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4542 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4543 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
4548 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4552 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4553 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4554 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4555 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4556 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
4561 /* Demote to normal user */
4562 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4567 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4568 if (target_client != client) {
4569 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4570 SILC_STATUS_ERR_NOT_YOU, 0);
4574 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
4575 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4579 if (chl->mode & 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 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4591 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4592 if (target_client != client) {
4593 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4594 SILC_STATUS_ERR_NOT_YOU, 0);
4598 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)) {
4599 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4603 if (chl->mode & 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 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4615 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4616 if (target_client != client) {
4617 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4618 SILC_STATUS_ERR_NOT_YOU, 0);
4622 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)) {
4623 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4627 if (chl->mode & 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 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4639 if (target_mask & SILC_CHANNEL_UMODE_QUIET) {
4640 if (!(chl->mode & SILC_CHANNEL_UMODE_QUIET)) {
4641 if (client == target_client) {
4642 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4643 SILC_STATUS_ERR_PERM_DENIED, 0);
4646 chl->mode |= SILC_CHANNEL_UMODE_QUIET;
4650 if (chl->mode & SILC_CHANNEL_UMODE_QUIET) {
4651 if (client == target_client) {
4652 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4653 SILC_STATUS_ERR_PERM_DENIED, 0);
4656 chl->mode &= ~SILC_CHANNEL_UMODE_QUIET;
4661 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4662 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4664 /* Send notify to channel, notify only if mode was actually changed. */
4666 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4667 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
4668 idp->data, idp->len,
4673 /* Set CUMODE notify type to network */
4674 silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
4675 SILC_BROADCAST(server), channel,
4676 target_mask, client->id, SILC_ID_CLIENT,
4677 target_client->id, founder_key);
4680 /* Send command reply to sender */
4681 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4682 SILC_STATUS_OK, 0, ident, 3,
4684 3, tmp_ch_id, tmp_ch_len,
4685 4, tmp_id, tmp_len);
4686 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4687 packet->data, packet->len, FALSE);
4689 silc_buffer_free(packet);
4690 silc_free(channel_id);
4691 silc_free(client_id);
4692 silc_buffer_free(idp);
4696 silc_server_command_free(cmd);
4699 /* Server side of KICK command. Kicks client out of channel. */
4701 SILC_SERVER_CMD_FUNC(kick)
4703 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4704 SilcServer server = cmd->server;
4705 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4706 SilcClientEntry target_client;
4707 SilcChannelID *channel_id;
4708 SilcClientID *client_id;
4709 SilcChannelEntry channel;
4710 SilcChannelClientEntry chl;
4712 SilcUInt32 tmp_len, target_idp_len;
4713 unsigned char *tmp, *comment, *target_idp;
4715 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4717 /* Get Channel ID */
4718 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4720 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4721 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4724 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4726 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4727 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4731 /* Get channel entry */
4732 channel = silc_idlist_find_channel_by_id(server->local_list,
4735 channel = silc_idlist_find_channel_by_id(server->local_list,
4738 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4739 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4745 /* Check whether sender is on the channel */
4746 if (!silc_server_client_on_channel(client, channel, &chl)) {
4747 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4748 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4752 /* Check that the kicker is channel operator or channel founder */
4753 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
4754 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4755 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4756 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
4760 /* Get target Client ID */
4761 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4763 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4764 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4767 client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
4769 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4770 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4774 /* Get target client's entry */
4775 target_client = silc_idlist_find_client_by_id(server->local_list,
4776 client_id, TRUE, NULL);
4777 if (!target_client) {
4778 target_client = silc_idlist_find_client_by_id(server->global_list,
4779 client_id, TRUE, NULL);
4782 /* Check whether target client is on the channel */
4783 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4784 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4785 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL,
4790 /* Check that the target client is not channel founder. Channel founder
4791 cannot be kicked from the channel. */
4792 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4793 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4794 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
4801 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4805 /* Send command reply to sender */
4806 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4809 /* Send KICKED notify to local clients on the channel */
4810 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4811 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4812 SILC_NOTIFY_TYPE_KICKED, 3,
4813 target_idp, target_idp_len,
4814 comment, comment ? strlen(comment) : 0,
4815 idp->data, idp->len);
4816 silc_buffer_free(idp);
4818 /* Remove the client from the channel. If the channel does not exist
4819 after removing the client then the client kicked itself off the channel
4820 and we don't have to send anything after that. */
4821 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4822 target_client, FALSE))
4825 /* Send KICKED notify to primary route */
4826 silc_server_send_notify_kicked(server, SILC_PRIMARY_ROUTE(server),
4827 SILC_BROADCAST(server), channel,
4828 target_client->id, client->id, comment);
4830 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4831 /* Re-generate channel key */
4832 if (!silc_server_create_channel_key(server, channel, 0))
4835 /* Send the channel key to the channel. The key of course is not sent
4836 to the client who was kicked off the channel. */
4837 silc_server_send_channel_key(server, target_client->connection, channel,
4838 server->server_type == SILC_ROUTER ?
4839 FALSE : !server->standalone);
4843 silc_server_command_free(cmd);
4846 /* Server side of OPER command. Client uses this comand to obtain server
4847 operator privileges to this server/router. */
4849 SILC_SERVER_CMD_FUNC(oper)
4851 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4852 SilcServer server = cmd->server;
4853 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4854 unsigned char *username, *auth;
4856 SilcServerConfigAdmin *admin;
4857 SilcIDListData idata = (SilcIDListData)client;
4858 bool result = FALSE;
4859 SilcPublicKey cached_key;
4861 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4863 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4866 /* Get the username */
4867 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4869 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4870 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4875 /* Get the admin configuration */
4876 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4877 username, client->nickname);
4879 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4880 username, client->nickname);
4882 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4883 SILC_STATUS_ERR_AUTH_FAILED,
4889 /* Get the authentication payload */
4890 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4892 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4893 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4898 /* Verify the authentication data. If both passphrase and public key
4899 is set then try both of them. */
4900 if (admin->passphrase)
4901 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4902 admin->passphrase, admin->passphrase_len,
4903 idata->hash, client->id, SILC_ID_CLIENT);
4904 if (!result && admin->publickeys) {
4905 cached_key = silc_server_get_public_key(server, admin->publickeys);
4908 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4909 cached_key, 0, idata->hash,
4910 client->id, SILC_ID_CLIENT);
4913 /* Authentication failed */
4914 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4915 SILC_STATUS_ERR_AUTH_FAILED,
4920 /* Client is now server operator */
4921 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4923 /* Update statistics */
4924 if (client->connection)
4925 server->stat.my_server_ops++;
4926 if (server->server_type == SILC_ROUTER)
4927 server->stat.server_ops++;
4929 /* Send UMODE change to primary router */
4930 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
4931 SILC_BROADCAST(server), client->id,
4934 /* Check if anyone is watching this nickname */
4935 if (server->server_type == SILC_ROUTER)
4936 silc_server_check_watcher_list(server, client, NULL,
4937 SILC_NOTIFY_TYPE_UMODE_CHANGE);
4939 /* Send reply to the sender */
4940 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4944 silc_server_command_free(cmd);
4947 SILC_TASK_CALLBACK(silc_server_command_detach_cb)
4949 QuitInternal q = (QuitInternal)context;
4950 SilcClientID *client_id = (SilcClientID *)q->sock;
4951 SilcClientEntry client;
4952 SilcSocketConnection sock;
4954 client = silc_idlist_find_client_by_id(q->server->local_list, client_id,
4956 if (client && client->connection) {
4957 sock = client->connection;
4959 /* If there is pending outgoing data for the client then purge it
4960 to the network before closing connection. */
4961 silc_server_packet_queue_purge(q->server, sock);
4963 /* Close the connection on our side */
4964 client->router = NULL;
4965 client->connection = NULL;
4966 sock->user_data = NULL;
4967 silc_server_close_connection(q->server, sock);
4970 silc_free(client_id);
4974 SILC_TASK_CALLBACK(silc_server_command_detach_timeout)
4976 QuitInternal q = (QuitInternal)context;
4977 SilcClientID *client_id = (SilcClientID *)q->sock;
4978 SilcClientEntry client;
4980 client = silc_idlist_find_client_by_id(q->server->local_list, client_id,
4982 if (client && client->mode & SILC_UMODE_DETACHED) {
4983 SILC_LOG_DEBUG(("Detach timeout"));
4984 silc_server_free_client_data(q->server, NULL, client, TRUE,
4988 silc_free(client_id);
4992 /* Server side of DETACH command. Detached the client from the network
4993 by closing the connection but preserving the session. */
4995 SILC_SERVER_CMD_FUNC(detach)
4997 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4998 SilcServer server = cmd->server;
4999 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5002 if (server->config->detach_disabled) {
5003 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
5004 SILC_STATUS_ERR_UNKNOWN_COMMAND, 0);
5008 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5011 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
5013 /* Send the user mode notify to notify that client is detached */
5014 client->mode |= SILC_UMODE_DETACHED;
5015 client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
5016 client->last_command = 0;
5017 client->fast_command = 0;
5018 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
5019 SILC_BROADCAST(server), client->id,
5021 server->stat.my_detached++;
5023 /* Check if anyone is watching this nickname */
5024 if (server->server_type == SILC_ROUTER)
5025 silc_server_check_watcher_list(server, client, NULL,
5026 SILC_NOTIFY_TYPE_UMODE_CHANGE);
5028 q = silc_calloc(1, sizeof(*q));
5030 q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
5031 silc_schedule_task_add(server->schedule, 0, silc_server_command_detach_cb,
5032 q, 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
5034 if (server->config->detach_timeout) {
5035 q = silc_calloc(1, sizeof(*q));
5037 q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
5038 silc_schedule_task_add(server->schedule, 0,
5039 silc_server_command_detach_timeout,
5040 q, server->config->detach_timeout * 60,
5041 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
5044 /* Send reply to the sender */
5045 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
5049 silc_server_command_free(cmd);
5052 /* Server side of WATCH command. */
5054 SILC_SERVER_CMD_FUNC(watch)
5056 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5057 SilcServer server = cmd->server;
5058 char *add_nick, *del_nick;
5059 SilcUInt32 add_nick_len, del_nick_len, tmp_len;
5061 unsigned char hash[16], *tmp;
5062 SilcClientEntry client;
5063 SilcClientID *client_id = NULL;
5065 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WATCH, cmd, 1, 3);
5067 if (server->server_type == SILC_SERVER && !server->standalone) {
5068 if (!cmd->pending) {
5069 /* Send the command to router */
5071 SilcUInt16 old_ident;
5073 old_ident = silc_command_get_ident(cmd->payload);
5074 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5075 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5077 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5078 SILC_PACKET_COMMAND, cmd->packet->flags,
5079 tmpbuf->data, tmpbuf->len, TRUE);
5081 /* Reprocess this packet after received reply from router */
5082 silc_server_command_pending(server, SILC_COMMAND_WATCH,
5083 silc_command_get_ident(cmd->payload),
5084 silc_server_command_watch,
5085 silc_server_command_dup(cmd));
5086 cmd->pending = TRUE;
5087 silc_command_set_ident(cmd->payload, old_ident);
5088 silc_buffer_free(tmpbuf);
5089 } else if (context2) {
5090 /* Received reply from router, just send same data to the client. */
5091 SilcServerCommandReplyContext reply = context2;
5093 silc_command_get_status(reply->payload, &status, NULL);
5094 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, status,
5101 /* We are router and keep the watch list for local cell */
5103 /* Get the client ID */
5104 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5106 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5107 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5111 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
5113 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5114 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5119 /* Get the client entry which must be in local list */
5120 client = silc_idlist_find_client_by_id(server->local_list,
5121 client_id, TRUE, NULL);
5123 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5124 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5130 add_nick = silc_argument_get_arg_type(cmd->args, 2, &add_nick_len);
5131 del_nick = silc_argument_get_arg_type(cmd->args, 3, &del_nick_len);
5132 if (!add_nick && !del_nick) {
5133 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5134 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5139 if (add_nick && add_nick_len > 128)
5140 add_nick[128] = '\0';
5141 if (del_nick && del_nick_len > 128)
5142 del_nick[128] = '\0';
5144 memset(nick, 0, sizeof(nick));
5146 /* Add new nickname to be watched in our cell */
5148 if (silc_server_name_bad_chars(add_nick, strlen(add_nick)) == TRUE) {
5149 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5150 SILC_STATUS_ERR_BAD_NICKNAME, 0);
5154 /* Hash the nick, we have the hash saved, not nicks because we can
5155 do one to one mapping to the nick from Client ID hash this way. */
5156 silc_to_lower(add_nick, nick, sizeof(nick) - 1);
5157 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
5159 /* Check whether this client is already watching this nickname */
5160 if (silc_hash_table_find_by_context(server->watcher_list, hash,
5162 /* Nickname is alredy being watched for this client */
5163 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5164 SILC_STATUS_ERR_NICKNAME_IN_USE,
5169 /* Get the nickname from the watcher list and use the same key in
5170 new entries as well. If key doesn't exist then create it. */
5171 if (!silc_hash_table_find(server->watcher_list, hash, (void **)&tmp, NULL))
5172 tmp = silc_memdup(hash, CLIENTID_HASH_LEN);
5174 /* Add the client to the watcher list with the specified nickname hash. */
5175 silc_hash_table_add(server->watcher_list, tmp, client);
5178 /* Delete nickname from watch list */
5180 if (silc_server_name_bad_chars(del_nick, strlen(del_nick)) == TRUE) {
5181 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5182 SILC_STATUS_ERR_BAD_NICKNAME, 0);
5186 /* Hash the nick, we have the hash saved, not nicks because we can
5187 do one to one mapping to the nick from Client ID hash this way. */
5188 silc_to_lower(del_nick, nick, sizeof(nick) - 1);
5189 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
5191 /* Check that this client is watching for this nickname */
5192 if (!silc_hash_table_find_by_context(server->watcher_list, hash,
5193 client, (void **)&tmp)) {
5194 /* Nickname is alredy being watched for this client */
5195 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5196 SILC_STATUS_ERR_NO_SUCH_NICK, 0);
5200 /* Delete the nickname from the watcher list. */
5201 silc_hash_table_del_by_context(server->watcher_list, hash, client);
5203 /* Now check whether there still exists entries with this key, if not
5204 then free the key to not leak memory. */
5205 if (!silc_hash_table_find(server->watcher_list, hash, NULL, NULL))
5209 /* Distribute the watch list to backup routers too */
5210 if (server->backup) {
5212 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5213 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5214 silc_server_backup_send(server, NULL, SILC_PACKET_COMMAND,
5215 cmd->packet->flags, tmpbuf->data, tmpbuf->len,
5217 silc_buffer_free(tmpbuf);
5220 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5224 silc_free(client_id);
5225 silc_server_command_free(cmd);
5228 /* Server side of SILCOPER command. Client uses this comand to obtain router
5229 operator privileges to this router. */
5231 SILC_SERVER_CMD_FUNC(silcoper)
5233 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5234 SilcServer server = cmd->server;
5235 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5236 unsigned char *username, *auth;
5238 SilcServerConfigAdmin *admin;
5239 SilcIDListData idata = (SilcIDListData)client;
5240 bool result = FALSE;
5241 SilcPublicKey cached_key;
5243 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
5245 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5248 if (server->server_type != SILC_ROUTER) {
5249 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5250 SILC_STATUS_ERR_AUTH_FAILED, 0);
5254 /* Get the username */
5255 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5257 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5258 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5263 /* Get the admin configuration */
5264 admin = silc_server_config_find_admin(server, cmd->sock->ip,
5265 username, client->nickname);
5267 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
5268 username, client->nickname);
5270 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5271 SILC_STATUS_ERR_AUTH_FAILED, 0);
5276 /* Get the authentication payload */
5277 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5279 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5280 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5285 /* Verify the authentication data. If both passphrase and public key
5286 is set then try both of them. */
5287 if (admin->passphrase)
5288 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
5289 admin->passphrase, admin->passphrase_len,
5290 idata->hash, client->id, SILC_ID_CLIENT);
5291 if (!result && admin->publickeys) {
5292 cached_key = silc_server_get_public_key(server, admin->publickeys);
5295 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
5296 cached_key, 0, idata->hash,
5297 client->id, SILC_ID_CLIENT);
5300 /* Authentication failed */
5301 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
5302 SILC_STATUS_ERR_AUTH_FAILED, 0);
5306 /* Client is now router operator */
5307 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
5309 /* Update statistics */
5310 if (client->connection)
5311 server->stat.my_router_ops++;
5312 if (server->server_type == SILC_ROUTER)
5313 server->stat.router_ops++;
5315 /* Send UMODE change to primary router */
5316 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
5317 SILC_BROADCAST(server), client->id,
5320 /* Check if anyone is watching this nickname */
5321 if (server->server_type == SILC_ROUTER)
5322 silc_server_check_watcher_list(server, client, NULL,
5323 SILC_NOTIFY_TYPE_UMODE_CHANGE);
5325 /* Send reply to the sender */
5326 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5330 silc_server_command_free(cmd);
5333 /* Server side of command BAN. This is used to manage the ban list of the
5334 channel. To add clients and remove clients from the ban list. */
5336 SILC_SERVER_CMD_FUNC(ban)
5338 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5339 SilcServer server = cmd->server;
5340 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5342 SilcChannelEntry channel;
5343 SilcChannelClientEntry chl;
5344 SilcChannelID *channel_id = NULL;
5345 unsigned char *id, *add, *del;
5346 SilcUInt32 id_len, tmp_len;
5347 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5349 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5352 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
5354 /* Get Channel ID */
5355 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
5357 channel_id = silc_id_payload_parse_id(id, id_len, NULL);
5359 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5360 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5365 /* Get channel entry. The server must know about the channel since the
5366 client is expected to be on the channel. */
5367 channel = silc_idlist_find_channel_by_id(server->local_list,
5370 channel = silc_idlist_find_channel_by_id(server->global_list,
5373 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5374 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5380 /* Check whether this client is on the channel */
5381 if (!silc_server_client_on_channel(client, channel, &chl)) {
5382 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5383 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5387 /* The client must be at least channel operator. */
5388 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
5389 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5390 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
5394 /* Get the new ban and add it to the ban list */
5395 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5397 if (!channel->ban_list)
5398 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
5400 channel->ban_list = silc_realloc(channel->ban_list,
5401 sizeof(*channel->ban_list) *
5403 strlen(channel->ban_list) + 2));
5404 if (add[tmp_len - 1] == ',')
5405 add[tmp_len - 1] = '\0';
5407 strncat(channel->ban_list, add, tmp_len);
5408 strncat(channel->ban_list, ",", 1);
5411 /* Get the ban to be removed and remove it from the list */
5412 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
5413 if (del && channel->ban_list) {
5414 char *start, *end, *n;
5416 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
5417 silc_free(channel->ban_list);
5418 channel->ban_list = NULL;
5420 start = strstr(channel->ban_list, del);
5421 if (start && strlen(start) >= tmp_len) {
5422 end = start + tmp_len;
5423 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
5424 strncat(n, channel->ban_list, start - channel->ban_list);
5425 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
5427 silc_free(channel->ban_list);
5428 channel->ban_list = n;
5433 /* Send the BAN notify type to our primary router. */
5435 silc_server_send_notify_ban(server, SILC_PRIMARY_ROUTE(server),
5436 SILC_BROADCAST(server), channel, add, del);
5438 /* Send the reply back to the client */
5440 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
5441 SILC_STATUS_OK, 0, ident, 2,
5443 3, channel->ban_list,
5445 strlen(channel->ban_list) -1 : 0);
5446 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5447 packet->data, packet->len, FALSE);
5449 silc_buffer_free(packet);
5452 silc_free(channel_id);
5453 silc_server_command_free(cmd);
5456 /* Server side command of LEAVE. Removes client from a channel. */
5458 SILC_SERVER_CMD_FUNC(leave)
5460 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5461 SilcServer server = cmd->server;
5462 SilcSocketConnection sock = cmd->sock;
5463 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
5464 SilcChannelID *id = NULL;
5465 SilcChannelEntry channel;
5469 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
5471 /* Get Channel ID */
5472 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
5474 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5475 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5478 id = silc_id_payload_parse_id(tmp, len, NULL);
5480 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5481 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5485 /* Get channel entry */
5486 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5488 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5490 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5491 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5497 /* Check whether this client is on the channel */
5498 if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
5499 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5500 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5504 /* Notify routers that they should remove this client from their list
5505 of clients on the channel. Send LEAVE notify type. */
5506 silc_server_send_notify_leave(server, SILC_PRIMARY_ROUTE(server),
5507 SILC_BROADCAST(server), channel, id_entry->id);
5509 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
5510 SILC_STATUS_OK, 0, 2, tmp, len);
5512 /* Remove client from channel */
5513 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5515 /* If the channel does not exist anymore we won't send anything */
5518 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5519 /* Re-generate channel key */
5520 if (!silc_server_create_channel_key(server, channel, 0))
5523 /* Send the channel key */
5524 silc_server_send_channel_key(server, NULL, channel,
5525 server->server_type == SILC_ROUTER ?
5526 FALSE : !server->standalone);
5531 silc_server_command_free(cmd);
5534 /* Server side of command USERS. Resolves clients and their USERS currently
5535 joined on the requested channel. The list of Client ID's and their modes
5536 on the channel is sent back. */
5538 SILC_SERVER_CMD_FUNC(users)
5540 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5541 SilcServer server = cmd->server;
5542 SilcChannelEntry channel;
5543 SilcChannelID *id = NULL;
5544 SilcBuffer packet, idp;
5545 unsigned char *channel_id;
5546 SilcUInt32 channel_id_len;
5547 SilcBuffer client_id_list;
5548 SilcBuffer client_mode_list;
5549 unsigned char lc[4];
5550 SilcUInt32 list_count = 0;
5551 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5554 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5556 /* Get Channel ID */
5557 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5559 /* Get channel name */
5560 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5562 if (!channel_id && !channel_name) {
5563 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5564 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5569 id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
5571 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5572 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5577 /* If we are server and we don't know about this channel we will send
5578 the command to our router. If we know about the channel then we also
5579 have the list of users already. */
5581 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5583 channel = silc_idlist_find_channel_by_name(server->local_list,
5584 channel_name, NULL);
5586 if (!channel || (!server->standalone && (channel->disabled ||
5587 !channel->users_resolved))) {
5588 if (server->server_type != SILC_ROUTER && !server->standalone &&
5592 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5593 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5595 /* Send USERS command */
5596 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5597 SILC_PACKET_COMMAND, cmd->packet->flags,
5598 tmpbuf->data, tmpbuf->len, TRUE);
5600 /* Reprocess this packet after received reply */
5601 silc_server_command_pending(server, SILC_COMMAND_USERS,
5602 silc_command_get_ident(cmd->payload),
5603 silc_server_command_users,
5604 silc_server_command_dup(cmd));
5605 cmd->pending = TRUE;
5606 silc_command_set_ident(cmd->payload, ident);
5607 silc_buffer_free(tmpbuf);
5612 /* Check the global list as well. */
5614 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5616 channel = silc_idlist_find_channel_by_name(server->global_list,
5617 channel_name, NULL);
5619 /* Channel really does not exist */
5620 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5621 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5627 /* If the channel is private or secret do not send anything, unless the
5628 user requesting this command is on the channel or is server */
5629 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5630 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5631 && !silc_server_client_on_channel(cmd->sock->user_data, channel,
5633 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5634 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5639 /* Get the users list */
5640 if (!silc_server_get_users_on_channel(server, channel, &client_id_list,
5641 &client_mode_list, &list_count)) {
5643 client_id_list = NULL;
5644 client_mode_list = NULL;
5648 SILC_PUT32_MSB(list_count, lc);
5651 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5652 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5653 SILC_STATUS_OK, 0, ident, 4,
5654 2, idp->data, idp->len,
5657 client_id_list->data : NULL,
5659 client_id_list->len : 0,
5660 5, client_mode_list ?
5661 client_mode_list->data : NULL,
5663 client_mode_list->len : 0);
5664 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5665 packet->data, packet->len, FALSE);
5667 silc_buffer_free(idp);
5668 silc_buffer_free(packet);
5670 silc_buffer_free(client_id_list);
5671 if (client_mode_list)
5672 silc_buffer_free(client_mode_list);
5676 silc_server_command_free(cmd);
5679 /* Server side of command GETKEY. This fetches the client's public key
5680 from the server where to the client is connected. */
5682 SILC_SERVER_CMD_FUNC(getkey)
5684 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5685 SilcServer server = cmd->server;
5687 SilcClientEntry client;
5688 SilcServerEntry server_entry;
5689 SilcClientID *client_id = NULL;
5690 SilcServerID *server_id = NULL;
5691 SilcIDPayload idp = NULL;
5692 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5693 unsigned char *tmp, *pkdata;
5694 SilcUInt32 tmp_len, pklen;
5695 SilcBuffer pk = NULL;
5697 SilcPublicKey public_key;
5699 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5701 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5702 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5706 idp = silc_id_payload_parse(tmp, tmp_len);
5708 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5709 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5714 id_type = silc_id_payload_get_type(idp);
5715 if (id_type == SILC_ID_CLIENT) {
5716 client_id = silc_id_payload_get_id(idp);
5718 /* If the client is not found from local list there is no chance it
5719 would be locally connected client so send the command further. */
5720 client = silc_idlist_find_client_by_id(server->local_list,
5721 client_id, TRUE, NULL);
5723 client = silc_idlist_find_client_by_id(server->global_list,
5724 client_id, TRUE, NULL);
5726 if ((!client && !cmd->pending && !server->standalone) ||
5727 (client && !client->connection && !cmd->pending &&
5728 !(client->mode & SILC_UMODE_DETACHED)) ||
5729 (client && !client->data.public_key && !cmd->pending)) {
5731 SilcUInt16 old_ident;
5732 SilcSocketConnection dest_sock;
5734 dest_sock = silc_server_get_client_route(server, NULL, 0,
5735 client_id, NULL, NULL);
5739 old_ident = silc_command_get_ident(cmd->payload);
5740 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5741 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5743 silc_server_packet_send(server, dest_sock,
5744 SILC_PACKET_COMMAND, cmd->packet->flags,
5745 tmpbuf->data, tmpbuf->len, TRUE);
5747 /* Reprocess this packet after received reply from router */
5748 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5749 silc_command_get_ident(cmd->payload),
5750 silc_server_command_getkey,
5751 silc_server_command_dup(cmd));
5752 cmd->pending = TRUE;
5753 silc_command_set_ident(cmd->payload, old_ident);
5754 silc_buffer_free(tmpbuf);
5759 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5760 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5765 /* The client is locally connected, just get the public key and
5766 send it back. If they key does not exist then do not send it,
5767 send just OK reply */
5768 public_key = client->data.public_key;
5773 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5774 pk = silc_buffer_alloc(4 + tmp_len);
5775 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5776 silc_buffer_format(pk,
5777 SILC_STR_UI_SHORT(tmp_len),
5778 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5779 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5785 } else if (id_type == SILC_ID_SERVER) {
5786 server_id = silc_id_payload_get_id(idp);
5788 /* If the server is not found from local list there is no chance it
5789 would be locally connected server so send the command further. */
5790 server_entry = silc_idlist_find_server_by_id(server->local_list,
5791 server_id, TRUE, NULL);
5793 server_entry = silc_idlist_find_server_by_id(server->global_list,
5794 server_id, TRUE, NULL);
5796 if (server_entry != server->id_entry &&
5797 ((!server_entry && !cmd->pending && !server->standalone) ||
5798 (server_entry && !server_entry->connection && !cmd->pending &&
5799 !server->standalone) ||
5800 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5801 !server->standalone))) {
5803 SilcUInt16 old_ident;
5805 old_ident = silc_command_get_ident(cmd->payload);
5806 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5807 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5809 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5810 SILC_PACKET_COMMAND, cmd->packet->flags,
5811 tmpbuf->data, tmpbuf->len, TRUE);
5813 /* Reprocess this packet after received reply from router */
5814 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5815 silc_command_get_ident(cmd->payload),
5816 silc_server_command_getkey,
5817 silc_server_command_dup(cmd));
5818 cmd->pending = TRUE;
5819 silc_command_set_ident(cmd->payload, old_ident);
5820 silc_buffer_free(tmpbuf);
5824 if (!server_entry) {
5825 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5826 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
5831 /* If they key does not exist then do not send it, send just OK reply */
5832 public_key = (!server_entry->data.public_key ?
5833 (server_entry == server->id_entry ? server->public_key :
5834 NULL) : server_entry->data.public_key);
5839 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5840 pk = silc_buffer_alloc(4 + tmp_len);
5841 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5842 silc_buffer_format(pk,
5843 SILC_STR_UI_SHORT(tmp_len),
5844 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5845 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5855 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5856 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5857 SILC_STATUS_OK, 0, ident,
5861 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5862 packet->data, packet->len, FALSE);
5863 silc_buffer_free(packet);
5866 silc_buffer_free(pk);
5870 silc_id_payload_free(idp);
5871 silc_free(client_id);
5872 silc_free(server_id);
5873 silc_server_command_free(cmd);
5877 /* Private range commands, specific to this implementation */
5879 /* Server side command of CONNECT. Connects us to the specified remote
5880 server or router. */
5882 SILC_SERVER_CMD_FUNC(connect)
5884 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5885 SilcServer server = cmd->server;
5886 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5887 unsigned char *tmp, *host;
5889 SilcUInt32 port = SILC_PORT;
5891 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
5893 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5896 /* Check whether client has the permissions. */
5897 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5898 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5899 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5900 SILC_STATUS_ERR_NO_SERVER_PRIV, 0);
5904 if (server->server_type == SILC_ROUTER &&
5905 client->mode & SILC_UMODE_SERVER_OPERATOR) {
5906 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5907 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
5911 /* Get the remote server */
5912 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5914 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5915 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5921 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5923 SILC_GET32_MSB(port, tmp);
5925 /* Create the connection. It is done with timeout and is async. */
5926 silc_server_create_connection(server, host, port);
5928 /* Send reply to the sender */
5929 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5933 silc_server_command_free(cmd);
5936 /* Server side command of CLOSE. Closes connection to a specified server. */
5938 SILC_SERVER_CMD_FUNC(close)
5940 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5941 SilcServer server = cmd->server;
5942 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5943 SilcServerEntry server_entry;
5944 SilcSocketConnection sock;
5947 unsigned char *name;
5948 SilcUInt32 port = SILC_PORT;
5950 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
5952 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5955 /* Check whether client has the permissions. */
5956 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5957 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5958 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5959 SILC_STATUS_ERR_NO_SERVER_PRIV,
5964 /* Get the remote server */
5965 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5967 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5968 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5974 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5976 SILC_GET32_MSB(port, tmp);
5978 server_entry = silc_idlist_find_server_by_conn(server->local_list,
5979 name, port, FALSE, NULL);
5981 server_entry = silc_idlist_find_server_by_conn(server->global_list,
5982 name, port, FALSE, NULL);
5983 if (!server_entry) {
5984 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5985 SILC_STATUS_ERR_NO_SERVER_ID, 0);
5989 /* Send reply to the sender */
5990 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5993 /* Close the connection to the server */
5994 sock = (SilcSocketConnection)server_entry->connection;
5996 /* If we shutdown primary router connection manually then don't trigger
5997 any reconnect or backup router connections, by setting the router
5999 if (server->router == server_entry) {
6000 server->id_entry->router = NULL;
6001 server->router = NULL;
6002 server->standalone = TRUE;
6004 silc_server_free_sock_user_data(server, sock, NULL);
6005 silc_server_close_connection(server, sock);
6008 silc_server_command_free(cmd);
6011 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
6012 active connections. */
6014 SILC_SERVER_CMD_FUNC(shutdown)
6016 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
6017 SilcServer server = cmd->server;
6018 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
6020 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
6022 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
6025 /* Check whether client has the permission. */
6026 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
6027 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
6028 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
6029 SILC_STATUS_ERR_NO_SERVER_PRIV,
6034 /* Send reply to the sender */
6035 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
6038 /* Then, gracefully, or not, bring the server down. */
6039 silc_server_stop(server);
6043 silc_server_command_free(cmd);