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 /* Set the topic for channel */
2444 silc_free(channel->topic);
2445 channel->topic = strdup(tmp);
2447 /* Send TOPIC_SET notify type to the network */
2448 silc_server_send_notify_topic_set(server, SILC_PRIMARY_ROUTE(server),
2449 SILC_BROADCAST(server), channel,
2450 client->id, SILC_ID_CLIENT,
2453 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2455 /* Send notify about topic change to all clients on the channel */
2456 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2457 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2458 idp->data, idp->len,
2459 channel->topic, strlen(channel->topic));
2460 silc_buffer_free(idp);
2463 /* Send the topic to client as reply packet */
2464 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2465 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2466 SILC_STATUS_OK, 0, ident, 2,
2467 2, idp->data, idp->len,
2470 strlen(channel->topic) : 0);
2471 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2472 0, packet->data, packet->len, FALSE);
2474 silc_buffer_free(packet);
2475 silc_buffer_free(idp);
2476 silc_free(channel_id);
2479 silc_server_command_free(cmd);
2482 /* Server side of INVITE command. Invites some client to join some channel.
2483 This command is also used to manage the invite list of the channel. */
2485 SILC_SERVER_CMD_FUNC(invite)
2487 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2488 SilcServer server = cmd->server;
2489 SilcSocketConnection sock = cmd->sock, dest_sock;
2490 SilcChannelClientEntry chl;
2491 SilcClientEntry sender, dest;
2492 SilcClientID *dest_id = NULL;
2493 SilcChannelEntry channel;
2494 SilcChannelID *channel_id = NULL;
2495 SilcIDListData idata;
2496 SilcBuffer idp, idp2, packet;
2497 unsigned char *tmp, *add, *del;
2499 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2501 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2503 /* Get Channel ID */
2504 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2506 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2507 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2510 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
2512 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2513 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2517 /* Get the channel entry */
2518 channel = silc_idlist_find_channel_by_id(server->local_list,
2521 channel = silc_idlist_find_channel_by_id(server->global_list,
2524 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2525 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
2531 /* Check whether the sender of this command is on the channel. */
2532 sender = (SilcClientEntry)sock->user_data;
2533 if (!silc_server_client_on_channel(sender, channel, &chl)) {
2534 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2535 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
2539 /* Check whether the channel is invite-only channel. If yes then the
2540 sender of this command must be at least channel operator. */
2541 if (channel->mode & SILC_CHANNEL_MODE_INVITE &&
2542 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
2543 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
2544 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2545 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
2550 /* Get destination client ID */
2551 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2556 dest_id = silc_id_payload_parse_id(tmp, len, NULL);
2558 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2559 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
2563 /* Get the client entry */
2564 dest = silc_server_get_client_resolve(server, dest_id, FALSE, &resolve);
2566 if (server->server_type != SILC_SERVER || !resolve) {
2567 silc_server_command_send_status_reply(
2568 cmd, SILC_COMMAND_INVITE,
2569 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0);
2573 /* The client info is being resolved. Reprocess this packet after
2574 receiving the reply to the query. */
2575 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2577 silc_server_command_invite,
2578 silc_server_command_dup(cmd));
2579 cmd->pending = TRUE;
2580 silc_free(channel_id);
2585 /* Check whether the requested client is already on the channel. */
2586 if (silc_server_client_on_channel(dest, channel, NULL)) {
2587 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2588 SILC_STATUS_ERR_USER_ON_CHANNEL,
2593 /* Get route to the client */
2594 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id,
2597 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2598 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2603 memset(invite, 0, sizeof(invite));
2604 strncat(invite, dest->nickname, strlen(dest->nickname));
2605 strncat(invite, "!", 1);
2606 strncat(invite, dest->username, strlen(dest->username));
2607 if (!strchr(dest->username, '@')) {
2608 strncat(invite, "@", 1);
2609 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2612 len = strlen(invite);
2613 if (!channel->invite_list)
2614 channel->invite_list = silc_calloc(len + 2,
2615 sizeof(*channel->invite_list));
2617 channel->invite_list = silc_realloc(channel->invite_list,
2618 sizeof(*channel->invite_list) *
2620 strlen(channel->invite_list) + 2));
2621 strncat(channel->invite_list, invite, len);
2622 strncat(channel->invite_list, ",", 1);
2624 if (!(dest->mode & SILC_UMODE_BLOCK_INVITE)) {
2625 /* Send notify to the client that is invited to the channel */
2626 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2627 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2628 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2630 SILC_NOTIFY_TYPE_INVITE, 3,
2631 idp->data, idp->len,
2632 channel->channel_name,
2633 strlen(channel->channel_name),
2634 idp2->data, idp2->len);
2635 silc_buffer_free(idp);
2636 silc_buffer_free(idp2);
2640 /* Add the client to the invite list of the channel */
2641 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2643 if (!channel->invite_list)
2644 channel->invite_list = silc_calloc(len + 2,
2645 sizeof(*channel->invite_list));
2647 channel->invite_list = silc_realloc(channel->invite_list,
2648 sizeof(*channel->invite_list) *
2650 strlen(channel->invite_list) + 2));
2651 if (add[len - 1] == ',')
2652 add[len - 1] = '\0';
2654 strncat(channel->invite_list, add, len);
2655 strncat(channel->invite_list, ",", 1);
2658 /* Get the invite to be removed and remove it from the list */
2659 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2660 if (del && channel->invite_list) {
2661 char *start, *end, *n;
2663 if (!strncmp(channel->invite_list, del,
2664 strlen(channel->invite_list) - 1)) {
2665 silc_free(channel->invite_list);
2666 channel->invite_list = NULL;
2668 start = strstr(channel->invite_list, del);
2669 if (start && strlen(start) >= len) {
2671 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2672 strncat(n, channel->invite_list, start - channel->invite_list);
2673 strncat(n, end + 1, ((channel->invite_list +
2674 strlen(channel->invite_list)) - end) - 1);
2675 silc_free(channel->invite_list);
2676 channel->invite_list = n;
2681 /* Send notify to the primary router */
2682 silc_server_send_notify_invite(server, SILC_PRIMARY_ROUTE(server),
2683 SILC_BROADCAST(server), channel,
2684 sender->id, add, del);
2686 /* Send command reply */
2687 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2691 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2692 SILC_STATUS_OK, 0, ident, 2,
2694 3, channel->invite_list,
2695 channel->invite_list ?
2696 strlen(channel->invite_list) : 0);
2699 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2700 SILC_STATUS_OK, 0, ident, 1,
2702 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2703 packet->data, packet->len, FALSE);
2704 silc_buffer_free(packet);
2708 silc_free(channel_id);
2709 silc_server_command_free(cmd);
2714 SilcSocketConnection sock;
2718 /* Quits connection to client. This gets called if client won't
2719 close the connection even when it has issued QUIT command. */
2721 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2723 QuitInternal q = (QuitInternal)context;
2725 /* Free all client specific data, such as client entry and entires
2726 on channels this client may be on. */
2727 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2729 q->sock->user_data = NULL;
2731 /* Close the connection on our side */
2732 silc_server_close_connection(q->server, q->sock);
2734 silc_free(q->signoff);
2738 /* Quits SILC session. This is the normal way to disconnect client. */
2740 SILC_SERVER_CMD_FUNC(quit)
2742 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2743 SilcServer server = cmd->server;
2744 SilcSocketConnection sock = cmd->sock;
2746 unsigned char *tmp = NULL;
2749 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2751 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2755 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2759 q = silc_calloc(1, sizeof(*q));
2762 q->signoff = tmp ? strdup(tmp) : NULL;
2764 /* We quit the connection with little timeout */
2765 silc_schedule_task_add(server->schedule, sock->sock,
2766 silc_server_command_quit_cb, (void *)q,
2767 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2770 silc_server_command_free(cmd);
2773 /* Server side of command KILL. This command is used by router operator
2774 to remove an client from the SILC Network temporarily. */
2776 SILC_SERVER_CMD_FUNC(kill)
2778 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2779 SilcServer server = cmd->server;
2780 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2781 SilcClientEntry remote_client;
2782 SilcClientID *client_id;
2783 unsigned char *tmp, *comment;
2784 SilcUInt32 tmp_len, tmp_len2;
2787 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2789 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2792 /* KILL command works only on router */
2793 if (server->server_type != SILC_ROUTER) {
2794 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2795 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
2799 /* Check whether client has the permissions. */
2800 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2801 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2802 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
2806 /* Get the client ID */
2807 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2809 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2810 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2814 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2816 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2817 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2822 /* Get the client entry */
2823 remote_client = silc_idlist_find_client_by_id(server->local_list,
2824 client_id, TRUE, NULL);
2826 if (!remote_client) {
2827 remote_client = silc_idlist_find_client_by_id(server->global_list,
2828 client_id, TRUE, NULL);
2830 if (!remote_client) {
2831 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2832 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2839 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2843 /* Send reply to the sender */
2844 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2847 /* Check if anyone is watching this nickname */
2848 if (server->server_type == SILC_ROUTER)
2849 silc_server_check_watcher_list(server, client, NULL,
2850 SILC_NOTIFY_TYPE_KILLED);
2852 /* Now do the killing */
2853 silc_server_kill_client(server, remote_client, comment, client->id,
2857 silc_server_command_free(cmd);
2860 /* Server side of command INFO. This sends information about us to
2861 the client. If client requested specific server we will send the
2862 command to that server. */
2864 SILC_SERVER_CMD_FUNC(info)
2866 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2867 SilcServer server = cmd->server;
2868 SilcBuffer packet, idp;
2871 char *dest_server, *server_info = NULL, *server_name;
2872 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2873 SilcServerEntry entry = NULL;
2874 SilcServerID *server_id = NULL;
2876 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2878 /* Get server name */
2879 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2882 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2884 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2886 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2887 SILC_STATUS_ERR_NO_SERVER_ID, 0);
2893 /* Check whether we have this server cached */
2894 entry = silc_idlist_find_server_by_id(server->local_list,
2895 server_id, TRUE, NULL);
2897 entry = silc_idlist_find_server_by_id(server->global_list,
2898 server_id, TRUE, NULL);
2899 if (!entry && server->server_type != SILC_SERVER) {
2900 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2901 SILC_STATUS_ERR_NO_SUCH_SERVER,
2908 /* Some buggy servers has sent request to router about themselves. */
2909 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2912 if ((!dest_server && !server_id && !entry) || (entry &&
2913 entry == server->id_entry) ||
2914 (dest_server && !cmd->pending &&
2915 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2916 /* Send our reply */
2917 char info_string[256];
2919 memset(info_string, 0, sizeof(info_string));
2920 snprintf(info_string, sizeof(info_string),
2921 "location: %s server: %s admin: %s <%s>",
2922 server->config->server_info->location,
2923 server->config->server_info->server_type,
2924 server->config->server_info->admin,
2925 server->config->server_info->email);
2927 server_info = info_string;
2928 entry = server->id_entry;
2930 /* Check whether we have this server cached */
2931 if (!entry && dest_server) {
2932 entry = silc_idlist_find_server_by_name(server->global_list,
2933 dest_server, TRUE, NULL);
2935 entry = silc_idlist_find_server_by_name(server->local_list,
2936 dest_server, TRUE, NULL);
2940 if (!cmd->pending &&
2941 server->server_type != SILC_SERVER && entry && !entry->server_info) {
2942 /* Send to the server */
2944 SilcUInt16 old_ident;
2946 old_ident = silc_command_get_ident(cmd->payload);
2947 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2948 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2950 silc_server_packet_send(server, entry->connection,
2951 SILC_PACKET_COMMAND, cmd->packet->flags,
2952 tmpbuf->data, tmpbuf->len, TRUE);
2954 /* Reprocess this packet after received reply from router */
2955 silc_server_command_pending(server, SILC_COMMAND_INFO,
2956 silc_command_get_ident(cmd->payload),
2957 silc_server_command_info,
2958 silc_server_command_dup(cmd));
2959 cmd->pending = TRUE;
2960 silc_command_set_ident(cmd->payload, old_ident);
2961 silc_buffer_free(tmpbuf);
2965 if (!entry && !cmd->pending && !server->standalone) {
2966 /* Send to the primary router */
2968 SilcUInt16 old_ident;
2970 old_ident = silc_command_get_ident(cmd->payload);
2971 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2972 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2974 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
2975 SILC_PACKET_COMMAND, cmd->packet->flags,
2976 tmpbuf->data, tmpbuf->len, TRUE);
2978 /* Reprocess this packet after received reply from router */
2979 silc_server_command_pending(server, SILC_COMMAND_INFO,
2980 silc_command_get_ident(cmd->payload),
2981 silc_server_command_info,
2982 silc_server_command_dup(cmd));
2983 cmd->pending = TRUE;
2984 silc_command_set_ident(cmd->payload, old_ident);
2985 silc_buffer_free(tmpbuf);
2990 silc_free(server_id);
2993 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2994 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
2998 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
3000 server_info = entry->server_info;
3001 server_name = entry->server_name;
3003 /* Send the reply */
3004 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
3005 SILC_STATUS_OK, 0, ident, 3,
3006 2, idp->data, idp->len,
3008 strlen(server_name),
3011 strlen(server_info) : 0);
3012 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3013 packet->data, packet->len, FALSE);
3015 silc_buffer_free(packet);
3016 silc_buffer_free(idp);
3019 silc_server_command_free(cmd);
3022 /* Server side of command PING. This just replies to the ping. */
3024 SILC_SERVER_CMD_FUNC(ping)
3026 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3027 SilcServer server = cmd->server;
3032 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
3035 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
3037 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3038 SILC_STATUS_ERR_NO_SERVER_ID, 0);
3041 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
3045 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
3046 /* Send our reply */
3047 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3050 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3051 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3058 silc_server_command_free(cmd);
3061 /* Server side of command STATS. */
3063 SILC_SERVER_CMD_FUNC(stats)
3065 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3066 SilcServer server = cmd->server;
3067 SilcServerID *server_id;
3070 SilcBuffer packet, stats;
3071 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3074 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1);
3077 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3079 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3080 SILC_STATUS_ERR_NO_SERVER_ID, 0);
3083 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3087 /* The ID must be ours */
3088 if (!SILC_ID_SERVER_COMPARE(server->id, server_id)) {
3089 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3090 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3091 silc_free(server_id);
3094 silc_free(server_id);
3096 /* If we are router then just send everything we got. If we are normal
3097 server then we'll send this to our router to get all the latest
3098 statistical information. */
3099 if (!cmd->pending && server->server_type != SILC_ROUTER &&
3100 !server->standalone) {
3101 /* Send request to our router */
3102 SilcBuffer idp = silc_id_payload_encode(server->router->id,
3104 packet = silc_command_payload_encode_va(SILC_COMMAND_STATS,
3105 ++server->cmd_ident, 1,
3106 1, idp->data, idp->len);
3107 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
3108 SILC_PACKET_COMMAND, 0, packet->data,
3109 packet->len, FALSE);
3111 /* Reprocess this packet after received reply from router */
3112 silc_server_command_pending(server, SILC_COMMAND_STATS,
3114 silc_server_command_stats,
3115 silc_server_command_dup(cmd));
3116 cmd->pending = TRUE;
3117 silc_buffer_free(packet);
3118 silc_buffer_free(idp);
3122 /* Send our reply to sender */
3123 uptime = time(NULL) - server->starttime;
3125 stats = silc_buffer_alloc_size(60);
3126 silc_buffer_format(stats,
3127 SILC_STR_UI_INT(server->starttime),
3128 SILC_STR_UI_INT(uptime),
3129 SILC_STR_UI_INT(server->stat.my_clients),
3130 SILC_STR_UI_INT(server->stat.my_channels),
3131 SILC_STR_UI_INT(server->stat.my_server_ops),
3132 SILC_STR_UI_INT(server->stat.my_router_ops),
3133 SILC_STR_UI_INT(server->stat.cell_clients),
3134 SILC_STR_UI_INT(server->stat.cell_channels),
3135 SILC_STR_UI_INT(server->stat.cell_servers),
3136 SILC_STR_UI_INT(server->stat.clients),
3137 SILC_STR_UI_INT(server->stat.channels),
3138 SILC_STR_UI_INT(server->stat.servers),
3139 SILC_STR_UI_INT(server->stat.routers),
3140 SILC_STR_UI_INT(server->stat.server_ops),
3141 SILC_STR_UI_INT(server->stat.router_ops),
3144 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_STATS,
3145 SILC_STATUS_OK, 0, ident, 2,
3147 3, stats->data, stats->len);
3148 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
3149 0, packet->data, packet->len, FALSE);
3150 silc_buffer_free(packet);
3151 silc_buffer_free(stats);
3154 silc_server_command_free(cmd);
3157 /* Internal routine to join channel. The channel sent to this function
3158 has been either created or resolved from ID lists. This joins the sent
3159 client to the channel. */
3161 static void silc_server_command_join_channel(SilcServer server,
3162 SilcServerCommandContext cmd,
3163 SilcChannelEntry channel,
3164 SilcClientID *client_id,
3168 const unsigned char *auth,
3169 SilcUInt32 auth_len)
3171 SilcSocketConnection sock = cmd->sock;
3173 SilcUInt32 tmp_len, user_count;
3174 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
3175 SilcClientEntry client;
3176 SilcChannelClientEntry chl;
3177 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
3178 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3179 char check[512], check2[512];
3180 bool founder = FALSE;
3182 unsigned char *fkey = NULL;
3183 SilcUInt32 fkey_len = 0;
3185 SILC_LOG_DEBUG(("Joining client to channel"));
3190 /* Get the client entry */
3191 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3192 client = (SilcClientEntry)sock->user_data;
3194 client = silc_server_get_client_resolve(server, client_id, FALSE,
3201 silc_server_command_send_status_reply(
3202 cmd, SILC_COMMAND_JOIN,
3203 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3207 /* The client info is being resolved. Reprocess this packet after
3208 receiving the reply to the query. */
3209 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
3211 silc_server_command_join,
3212 silc_server_command_dup(cmd));
3213 cmd->pending = TRUE;
3217 cmd->pending = FALSE;
3221 * Check founder auth payload if provided. If client can gain founder
3222 * privileges it can override various conditions on joining the channel,
3223 * and can have directly the founder mode set on the channel.
3225 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3226 SilcIDListData idata = (SilcIDListData)client;
3227 SilcChannelClientEntry chl2;
3228 SilcHashTableList htl;
3230 if (channel->founder_key && idata->public_key &&
3231 silc_pkcs_public_key_compare(channel->founder_key,
3232 idata->public_key)) {
3233 /* Check whether the client is to become founder */
3234 if (silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
3235 channel->founder_key, 0, server->sha1hash,
3236 client->id, SILC_ID_CLIENT)) {
3238 /* There cannot be anyone else as founder on the channel now. This
3239 client is definitely the founder due to this authentication */
3240 silc_hash_table_list(channel->user_list, &htl);
3241 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
3242 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
3243 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3244 silc_server_force_cumode_change(server, NULL, channel, chl2,
3248 silc_hash_table_list_reset(&htl);
3250 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3257 * Check channel modes
3261 memset(check, 0, sizeof(check));
3262 memset(check2, 0, sizeof(check2));
3263 strncat(check, client->nickname, strlen(client->nickname));
3264 strncat(check, "!", 1);
3265 strncat(check, client->username, strlen(client->username));
3266 if (!strchr(client->username, '@')) {
3267 strncat(check, "@", 1);
3268 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3271 strncat(check2, client->nickname, strlen(client->nickname));
3272 if (!strchr(client->nickname, '@')) {
3273 strncat(check2, "@", 1);
3274 strncat(check2, server->server_name, strlen(server->server_name));
3276 strncat(check2, "!", 1);
3277 strncat(check2, client->username, strlen(client->username));
3278 if (!strchr(client->username, '@')) {
3279 strncat(check2, "@", 1);
3280 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3283 /* Check invite list if channel is invite-only channel */
3284 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3285 if (!channel->invite_list ||
3286 (!silc_string_match(channel->invite_list, check) &&
3287 !silc_string_match(channel->invite_list, check2))) {
3288 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3289 SILC_STATUS_ERR_NOT_INVITED, 0);
3294 /* Check ban list if it exists. If the client's nickname, server,
3295 username and/or hostname is in the ban list the access to the
3296 channel is denied. */
3297 if (channel->ban_list) {
3298 if (silc_string_match(channel->ban_list, check) ||
3299 silc_string_match(channel->ban_list, check2)) {
3300 silc_server_command_send_status_reply(
3301 cmd, SILC_COMMAND_JOIN,
3302 SILC_STATUS_ERR_BANNED_FROM_CHANNEL, 0);
3307 /* Check user count limit if set. */
3308 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3309 if (silc_hash_table_count(channel->user_list) + 1 >
3310 channel->user_limit) {
3311 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3312 SILC_STATUS_ERR_CHANNEL_IS_FULL,
3319 /* Check the channel passphrase if set. */
3320 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3321 /* Get passphrase */
3322 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3324 passphrase = silc_memdup(tmp, tmp_len);
3326 if (!passphrase || !channel->passphrase ||
3327 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3328 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3329 SILC_STATUS_ERR_BAD_PASSWORD, 0);
3335 * Client is allowed to join to the channel. Make it happen.
3338 /* Check whether the client already is on the channel */
3339 if (silc_server_client_on_channel(client, channel, NULL)) {
3340 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3341 SILC_STATUS_ERR_USER_ON_CHANNEL, 0);
3345 /* Generate new channel key as protocol dictates */
3347 if (!silc_server_create_channel_key(server, channel, 0))
3350 /* Send the channel key. This is broadcasted to the channel but is not
3351 sent to the client who is joining to the channel. */
3352 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3353 silc_server_send_channel_key(server, NULL, channel,
3354 server->server_type == SILC_ROUTER ?
3355 FALSE : !server->standalone);
3358 /* Join the client to the channel by adding it to channel's user list.
3359 Add also the channel to client entry's channels list for fast cross-
3361 chl = silc_calloc(1, sizeof(*chl));
3363 chl->client = client;
3364 chl->channel = channel;
3365 silc_hash_table_add(channel->user_list, client, chl);
3366 silc_hash_table_add(client->channels, channel, chl);
3367 channel->user_count++;
3368 channel->disabled = FALSE;
3370 /* Get users on the channel */
3371 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3374 /* Encode Client ID Payload of the original client who wants to join */
3375 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3377 /* Encode command reply packet */
3378 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3379 SILC_PUT32_MSB(channel->mode, mode);
3380 SILC_PUT32_MSB(created, tmp2);
3381 SILC_PUT32_MSB(user_count, tmp3);
3383 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3384 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3385 keyp = silc_channel_key_payload_encode(silc_id_get_len(channel->id,
3388 strlen(channel->channel_key->
3390 channel->channel_key->cipher->name,
3391 channel->key_len / 8, channel->key);
3395 if (channel->founder_key)
3396 fkey = silc_pkcs_public_key_encode(channel->founder_key, &fkey_len);
3399 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3400 SILC_STATUS_OK, 0, ident, 14,
3401 2, channel->channel_name,
3402 strlen(channel->channel_name),
3403 3, chidp->data, chidp->len,
3404 4, clidp->data, clidp->len,
3407 7, keyp ? keyp->data : NULL,
3408 keyp ? keyp->len : 0,
3409 8, channel->ban_list,
3411 strlen(channel->ban_list) : 0,
3412 9, channel->invite_list,
3413 channel->invite_list ?
3414 strlen(channel->invite_list) : 0,
3417 strlen(channel->topic) : 0,
3418 11, silc_hmac_get_name(channel->hmac),
3419 strlen(silc_hmac_get_name(channel->
3422 13, user_list->data, user_list->len,
3423 14, mode_list->data,
3425 15, fkey, fkey_len);
3427 /* Send command reply */
3428 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3429 reply->data, reply->len, FALSE);
3431 /* Send JOIN notify to locally connected clients on the channel. If
3432 we are normal server then router will send or have sent JOIN notify
3433 already. However since we've added the client already to our channel
3434 we'll ignore it (in packet_receive.c) so we must send it here. If
3435 we are router then this will send it to local clients and local
3437 SILC_LOG_DEBUG(("Send JOIN notify to channel"));
3438 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3439 SILC_NOTIFY_TYPE_JOIN, 2,
3440 clidp->data, clidp->len,
3441 chidp->data, chidp->len);
3443 /* Update statistics */
3444 server->stat.my_chanclients++;
3445 if (server->server_type == SILC_ROUTER) {
3446 server->stat.cell_chanclients++;
3447 server->stat.chanclients++;
3450 if (!cmd->pending) {
3451 /* Send JOIN notify packet to our primary router */
3452 silc_server_send_notify_join(server, SILC_PRIMARY_ROUTE(server),
3453 SILC_BROADCAST(server), channel, client->id);
3456 /* Distribute the channel key to all backup routers. */
3457 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3458 keyp->data, keyp->len, FALSE, TRUE);
3460 /* If client became founder by providing correct founder auth data
3461 notify the mode change to the channel. */
3463 SILC_PUT32_MSB(chl->mode, mode);
3464 SILC_LOG_DEBUG(("Send CUMODE_CHANGE notify to channel"));
3465 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3466 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
3467 clidp->data, clidp->len,
3468 mode, 4, clidp->data, clidp->len,
3473 /* Set CUMODE notify type to network */
3475 silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
3476 SILC_BROADCAST(server), channel,
3477 chl->mode, client->id, SILC_ID_CLIENT,
3478 client->id, channel->founder_key);
3480 silc_buffer_free(reply);
3481 silc_buffer_free(clidp);
3482 silc_buffer_free(chidp);
3483 silc_buffer_free(keyp);
3484 silc_buffer_free(user_list);
3485 silc_buffer_free(mode_list);
3489 silc_free(passphrase);
3492 /* Server side of command JOIN. Joins client into requested channel. If
3493 the channel does not exist it will be created. */
3495 SILC_SERVER_CMD_FUNC(join)
3497 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3498 SilcServer server = cmd->server;
3499 unsigned char *auth;
3500 SilcUInt32 tmp_len, auth_len;
3501 char *tmp, *channel_name = NULL, *cipher, *hmac;
3502 SilcChannelEntry channel;
3503 SilcUInt32 umode = 0;
3504 bool created = FALSE, create_key = TRUE;
3505 SilcClientID *client_id;
3507 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3509 /* Get channel name */
3510 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3512 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3513 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3520 channel_name[255] = '\0';
3522 if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
3523 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3524 SILC_STATUS_ERR_BAD_CHANNEL, 0);
3528 /* Get Client ID of the client who is joining to the channel */
3529 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3531 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3532 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3536 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3538 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3539 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3544 /* Get cipher, hmac name and auth payload */
3545 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3546 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3547 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3549 /* See if the channel exists */
3550 channel = silc_idlist_find_channel_by_name(server->local_list,
3551 channel_name, NULL);
3553 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3554 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3555 silc_free(client_id);
3556 client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
3559 (channel->disabled && server->server_type != SILC_ROUTER)) {
3560 /* Channel not found */
3562 /* If we are standalone server we don't have a router, we just create
3563 the channel by ourselves. */
3564 if (server->standalone) {
3565 channel = silc_server_create_new_channel(server, server->id, cipher,
3566 hmac, channel_name, TRUE);
3568 silc_server_command_send_status_reply(
3569 cmd, SILC_COMMAND_JOIN,
3570 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
3572 silc_free(client_id);
3576 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3582 /* The channel does not exist on our server. If we are normal server
3583 we will send JOIN command to our router which will handle the
3584 joining procedure (either creates the channel if it doesn't exist
3585 or joins the client to it). */
3586 if (server->server_type != SILC_ROUTER) {
3588 SilcUInt16 old_ident;
3590 /* If this is pending command callback then we've resolved
3591 it and it didn't work, return since we've notified the
3592 client already in the command reply callback. */
3594 silc_free(client_id);
3598 old_ident = silc_command_get_ident(cmd->payload);
3599 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3600 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3602 /* Send JOIN command to our router */
3603 silc_server_packet_send(server, (SilcSocketConnection)
3604 SILC_PRIMARY_ROUTE(server),
3605 SILC_PACKET_COMMAND, cmd->packet->flags,
3606 tmpbuf->data, tmpbuf->len, TRUE);
3608 /* Reprocess this packet after received reply from router */
3609 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3610 silc_command_get_ident(cmd->payload),
3611 silc_server_command_join,
3612 silc_server_command_dup(cmd));
3613 cmd->pending = TRUE;
3614 silc_command_set_ident(cmd->payload, old_ident);
3615 silc_buffer_free(tmpbuf);
3616 silc_free(client_id);
3620 /* We are router and the channel does not seem exist so we will check
3621 our global list as well for the channel. */
3622 channel = silc_idlist_find_channel_by_name(server->global_list,
3623 channel_name, NULL);
3625 /* Channel really does not exist, create it */
3626 channel = silc_server_create_new_channel(server, server->id, cipher,
3627 hmac, channel_name, TRUE);
3629 silc_server_command_send_status_reply(
3630 cmd, SILC_COMMAND_JOIN,
3631 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
3632 silc_free(client_id);
3636 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3644 /* Channel not found */
3646 /* If the command came from router and we are normal server then
3647 something went wrong with the joining as the channel was not found.
3648 We can't do anything else but ignore this. */
3649 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3650 server->server_type != SILC_ROUTER) {
3651 silc_free(client_id);
3655 /* We are router and the channel does not seem exist so we will check
3656 our global list as well for the channel. */
3657 channel = silc_idlist_find_channel_by_name(server->global_list,
3658 channel_name, NULL);
3660 /* Channel really does not exist, create it */
3661 channel = silc_server_create_new_channel(server, server->id, cipher,
3662 hmac, channel_name, TRUE);
3664 silc_server_command_send_status_reply(
3665 cmd, SILC_COMMAND_JOIN,
3666 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
3667 silc_free(client_id);
3671 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3678 /* Check whether the channel was created by our router */
3679 if (cmd->pending && context2) {
3680 SilcServerCommandReplyContext reply = context2;
3682 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3683 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3684 SILC_GET32_MSB(created, tmp);
3685 if (silc_argument_get_arg_type(reply->args, 7, NULL))
3686 create_key = FALSE; /* Router returned the key already */
3688 if (silc_command_get_status(reply->payload, NULL, NULL) &&
3689 channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3690 /* Save channel passphrase, if user provided it successfully */
3693 pa = silc_argument_get_arg_type(reply->args, 3, &pa_len);
3695 silc_free(channel->passphrase);
3696 channel->passphrase = silc_memdup(pa, pa_len);
3701 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
3702 !channel->disabled && !silc_hash_table_count(channel->user_list))
3706 /* If the channel does not have global users and is also empty the client
3707 will be the channel founder and operator. */
3708 if (!channel->disabled &&
3709 !channel->global_users && !silc_hash_table_count(channel->user_list))
3710 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3712 /* Join to the channel */
3713 silc_server_command_join_channel(server, cmd, channel, client_id,
3714 created, create_key, umode,
3717 silc_free(client_id);
3720 silc_server_command_free(cmd);
3723 /* Server side of command MOTD. Sends server's current "message of the
3724 day" to the client. */
3726 SILC_SERVER_CMD_FUNC(motd)
3728 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3729 SilcServer server = cmd->server;
3730 SilcBuffer packet, idp;
3731 char *motd, *dest_server;
3732 SilcUInt32 motd_len;
3733 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3735 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3737 /* Get server name */
3738 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3740 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3741 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3745 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3748 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3750 if (server->config && server->config->server_info &&
3751 server->config->server_info->motd_file) {
3753 motd = silc_file_readfile(server->config->server_info->motd_file,
3759 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3766 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3772 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3773 packet->data, packet->len, FALSE);
3774 silc_buffer_free(packet);
3775 silc_buffer_free(idp);
3777 SilcServerEntry entry;
3779 /* Check whether we have this server cached */
3780 entry = silc_idlist_find_server_by_name(server->global_list,
3781 dest_server, TRUE, NULL);
3783 entry = silc_idlist_find_server_by_name(server->local_list,
3784 dest_server, TRUE, NULL);
3787 if (server->server_type != SILC_SERVER && !cmd->pending &&
3788 entry && !entry->motd) {
3789 /* Send to the server */
3791 SilcUInt16 old_ident;
3793 old_ident = silc_command_get_ident(cmd->payload);
3794 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3795 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3797 silc_server_packet_send(server, entry->connection,
3798 SILC_PACKET_COMMAND, cmd->packet->flags,
3799 tmpbuf->data, tmpbuf->len, TRUE);
3801 /* Reprocess this packet after received reply from router */
3802 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3803 silc_command_get_ident(cmd->payload),
3804 silc_server_command_motd,
3805 silc_server_command_dup(cmd));
3806 cmd->pending = TRUE;
3807 silc_command_set_ident(cmd->payload, old_ident);
3808 silc_buffer_free(tmpbuf);
3812 if (!entry && !cmd->pending && !server->standalone) {
3813 /* Send to the primary router */
3815 SilcUInt16 old_ident;
3817 old_ident = silc_command_get_ident(cmd->payload);
3818 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3819 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3821 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
3822 SILC_PACKET_COMMAND, cmd->packet->flags,
3823 tmpbuf->data, tmpbuf->len, TRUE);
3825 /* Reprocess this packet after received reply from router */
3826 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3827 silc_command_get_ident(cmd->payload),
3828 silc_server_command_motd,
3829 silc_server_command_dup(cmd));
3830 cmd->pending = TRUE;
3831 silc_command_set_ident(cmd->payload, old_ident);
3832 silc_buffer_free(tmpbuf);
3837 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3838 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3842 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3843 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3844 SILC_STATUS_OK, 0, ident, 2,
3848 strlen(entry->motd) : 0);
3849 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3850 packet->data, packet->len, FALSE);
3851 silc_buffer_free(packet);
3852 silc_buffer_free(idp);
3856 silc_server_command_free(cmd);
3859 /* Server side of command UMODE. Client can use this command to set/unset
3860 user mode. Client actually cannot set itself to be as server/router
3861 operator so this can be used only to unset the modes. */
3863 SILC_SERVER_CMD_FUNC(umode)
3865 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3866 SilcServer server = cmd->server;
3867 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3869 unsigned char *tmp_mask, m[4];
3870 SilcUInt32 mask = 0;
3871 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3872 bool set_mask = FALSE;
3874 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3877 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2);
3879 /* Get the client's mode mask */
3880 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3882 SILC_GET32_MSB(mask, tmp_mask);
3887 /* Check that mode changing is allowed. */
3888 if (!silc_server_check_umode_rights(server, client, mask)) {
3889 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3890 SILC_STATUS_ERR_PERM_DENIED, 0);
3894 /* Anonymous mode cannot be set by client */
3895 if (mask & SILC_UMODE_ANONYMOUS) {
3896 if (!(client->mode & SILC_UMODE_ANONYMOUS)) {
3897 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3898 SILC_STATUS_ERR_PERM_DENIED, 0);
3902 if (client->mode & SILC_UMODE_ANONYMOUS) {
3903 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3904 SILC_STATUS_ERR_PERM_DENIED, 0);
3909 /* Update statistics */
3910 if (mask & SILC_UMODE_GONE) {
3911 if (!(client->mode & SILC_UMODE_GONE))
3912 server->stat.my_aways++;
3914 if (client->mode & SILC_UMODE_GONE)
3915 server->stat.my_aways--;
3918 /* Change the mode */
3919 client->mode = mask;
3921 /* Send UMODE change to primary router */
3922 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
3923 SILC_BROADCAST(server), client->id,
3926 /* Check if anyone is watching this nickname */
3927 if (server->server_type == SILC_ROUTER)
3928 silc_server_check_watcher_list(server, client, NULL,
3929 SILC_NOTIFY_TYPE_UMODE_CHANGE);
3932 /* Send command reply to sender */
3933 SILC_PUT32_MSB(client->mode, m);
3934 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3935 SILC_STATUS_OK, 0, ident, 1,
3937 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3938 packet->data, packet->len, FALSE);
3939 silc_buffer_free(packet);
3942 silc_server_command_free(cmd);
3945 /* Server side command of CMODE. Changes channel mode */
3947 SILC_SERVER_CMD_FUNC(cmode)
3949 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3950 SilcServer server = cmd->server;
3951 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3952 SilcIDListData idata = (SilcIDListData)client;
3953 SilcChannelID *channel_id = NULL;
3954 SilcChannelEntry channel;
3955 SilcChannelClientEntry chl;
3956 SilcBuffer packet, cidp;
3957 unsigned char *tmp, *tmp_id, *tmp_mask;
3958 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3959 SilcUInt32 mode_mask = 0, tmp_len, tmp_len2;
3960 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3961 bool set_mask = FALSE;
3962 SilcPublicKey founder_key = NULL;
3963 unsigned char *fkey = NULL;
3964 SilcUInt32 fkey_len = 0;
3966 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 7);
3968 /* Get Channel ID */
3969 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3971 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3972 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3975 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
3977 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3978 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3982 /* Get the channel mode mask */
3983 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3985 SILC_GET32_MSB(mode_mask, tmp_mask);
3989 /* Get channel entry */
3990 channel = silc_idlist_find_channel_by_id(server->local_list,
3993 channel = silc_idlist_find_channel_by_id(server->global_list,
3996 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3997 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4003 /* Check whether this client is on the channel */
4004 if (!silc_server_client_on_channel(client, channel, &chl)) {
4005 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4006 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4010 /* Check that client has rights to change any requested channel modes */
4011 if (set_mask && !silc_server_check_cmode_rights(server, channel, chl,
4013 silc_server_command_send_status_reply(
4014 cmd, SILC_COMMAND_CMODE,
4015 (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) ?
4016 SILC_STATUS_ERR_NO_CHANNEL_PRIV :
4017 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV), 0);
4021 /* If mode mask was not sent as argument then merely return the current
4022 mode mask to the sender. */
4025 SILC_PUT32_MSB(channel->mode, m);
4026 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4027 SILC_STATUS_OK, 0, ident, 2,
4028 2, tmp_id, tmp_len2,
4030 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4031 packet->data, packet->len, FALSE);
4032 silc_buffer_free(packet);
4037 * Check the modes. Modes that requires nothing special operation are
4041 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
4042 /* Channel uses private keys to protect traffic. Client(s) has set the
4043 key locally they want to use, server does not know that key. */
4044 /* Nothing interesting to do here */
4046 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
4047 /* The mode is removed and we need to generate and distribute
4048 new channel key. Clients are not using private channel keys
4049 anymore after this. */
4051 /* Re-generate channel key */
4052 if (!silc_server_create_channel_key(server, channel, 0))
4055 /* Send the channel key. This sends it to our local clients and if
4056 we are normal server to our router as well. */
4057 silc_server_send_channel_key(server, NULL, channel,
4058 server->server_type == SILC_ROUTER ?
4059 FALSE : !server->standalone);
4061 cipher = channel->channel_key->cipher->name;
4062 hmac = (char *)silc_hmac_get_name(channel->hmac);
4066 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
4067 /* User limit is set on channel */
4068 SilcUInt32 user_limit;
4070 /* Get user limit */
4071 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
4073 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
4074 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4075 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4079 SILC_GET32_MSB(user_limit, tmp);
4080 channel->user_limit = user_limit;
4083 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
4084 /* User limit mode is unset. Remove user limit */
4085 channel->user_limit = 0;
4088 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
4089 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
4090 /* Passphrase has been set to channel */
4092 /* Get the passphrase */
4093 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
4095 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4096 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4100 /* Save the passphrase */
4101 passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
4104 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
4105 /* Passphrase mode is unset. remove the passphrase */
4106 silc_free(channel->passphrase);
4107 channel->passphrase = NULL;
4111 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
4112 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
4113 /* Cipher to use protect the traffic */
4114 SilcCipher newkey, oldkey;
4117 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
4119 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4120 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4124 /* Delete old cipher and allocate the new one */
4125 if (!silc_cipher_alloc(cipher, &newkey)) {
4126 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4127 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4131 oldkey = channel->channel_key;
4132 channel->channel_key = newkey;
4134 /* Re-generate channel key */
4135 if (!silc_server_create_channel_key(server, channel, 0)) {
4136 /* We don't have new key, revert to old one */
4137 channel->channel_key = oldkey;
4141 /* Remove old channel key for good */
4142 silc_cipher_free(oldkey);
4144 /* Send the channel key. This sends it to our local clients and if
4145 we are normal server to our router as well. */
4146 silc_server_send_channel_key(server, NULL, channel,
4147 server->server_type == SILC_ROUTER ?
4148 FALSE : !server->standalone);
4151 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
4152 /* Cipher mode is unset. Remove the cipher and revert back to
4154 SilcCipher newkey, oldkey;
4155 cipher = channel->cipher;
4157 /* Delete old cipher and allocate default one */
4158 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
4159 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4160 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4164 oldkey = channel->channel_key;
4165 channel->channel_key = newkey;
4167 /* Re-generate channel key */
4168 if (!silc_server_create_channel_key(server, channel, 0)) {
4169 /* We don't have new key, revert to old one */
4170 channel->channel_key = oldkey;
4174 /* Remove old channel key for good */
4175 silc_cipher_free(oldkey);
4177 /* Send the channel key. This sends it to our local clients and if
4178 we are normal server to our router as well. */
4179 silc_server_send_channel_key(server, NULL, channel,
4180 server->server_type == SILC_ROUTER ?
4181 FALSE : !server->standalone);
4185 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
4186 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
4187 /* HMAC to use protect the traffic */
4188 unsigned char hash[32];
4192 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4194 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4195 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4199 /* Delete old hmac and allocate the new one */
4200 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4201 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4202 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4206 silc_hmac_free(channel->hmac);
4207 channel->hmac = newhmac;
4209 /* Set the HMAC key out of current channel key. The client must do
4211 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4212 channel->key_len / 8, hash);
4213 silc_hmac_set_key(channel->hmac, hash,
4214 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4215 memset(hash, 0, sizeof(hash));
4218 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4219 /* Hmac mode is unset. Remove the hmac and revert back to
4222 unsigned char hash[32];
4223 hmac = channel->hmac_name;
4225 /* Delete old hmac and allocate default one */
4226 silc_hmac_free(channel->hmac);
4227 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4228 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4229 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4233 silc_hmac_free(channel->hmac);
4234 channel->hmac = newhmac;
4236 /* Set the HMAC key out of current channel key. The client must do
4238 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4239 channel->key_len / 8,
4241 silc_hmac_set_key(channel->hmac, hash,
4242 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4243 memset(hash, 0, sizeof(hash));
4247 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4248 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4249 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4250 /* Set the founder authentication */
4251 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4253 silc_server_command_send_status_reply(
4254 cmd, SILC_COMMAND_CMODE,
4255 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4259 /* Verify the payload before setting the mode */
4260 if (!silc_auth_verify_data(tmp, tmp_len, SILC_AUTH_PUBLIC_KEY,
4261 idata->public_key, 0, server->sha1hash,
4262 client->id, SILC_ID_CLIENT)) {
4263 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4264 SILC_STATUS_ERR_AUTH_FAILED,
4269 /* Save the public key */
4270 channel->founder_key = silc_pkcs_public_key_copy(idata->public_key);
4271 if (!channel->founder_key) {
4272 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4273 SILC_STATUS_ERR_AUTH_FAILED,
4278 founder_key = channel->founder_key;
4279 fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
4281 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4282 SILC_STATUS_ERR_AUTH_FAILED,
4289 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4290 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4291 if (channel->founder_key)
4292 silc_pkcs_public_key_free(channel->founder_key);
4293 channel->founder_key = NULL;
4298 /* Finally, set the mode */
4299 channel->mode = mode_mask;
4301 /* Send CMODE_CHANGE notify. */
4302 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4303 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4304 SILC_NOTIFY_TYPE_CMODE_CHANGE, 6,
4305 cidp->data, cidp->len,
4307 cipher, cipher ? strlen(cipher) : 0,
4308 hmac, hmac ? strlen(hmac) : 0,
4309 passphrase, passphrase ?
4310 strlen(passphrase) : 0,
4313 /* Set CMODE notify type to network */
4314 silc_server_send_notify_cmode(server, SILC_PRIMARY_ROUTE(server),
4315 SILC_BROADCAST(server), channel,
4316 mode_mask, client->id, SILC_ID_CLIENT,
4317 cipher, hmac, passphrase, founder_key);
4319 /* Send command reply to sender */
4320 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4321 SILC_STATUS_OK, 0, ident, 2,
4322 2, tmp_id, tmp_len2,
4324 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4325 packet->data, packet->len, FALSE);
4327 silc_buffer_free(packet);
4328 silc_buffer_free(cidp);
4332 silc_free(channel_id);
4333 silc_server_command_free(cmd);
4336 /* Server side of CUMODE command. Changes client's mode on a channel. */
4338 SILC_SERVER_CMD_FUNC(cumode)
4340 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4341 SilcServer server = cmd->server;
4342 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4343 SilcIDListData idata = (SilcIDListData)client;
4344 SilcChannelID *channel_id;
4345 SilcClientID *client_id;
4346 SilcChannelEntry channel;
4347 SilcClientEntry target_client;
4348 SilcChannelClientEntry chl;
4349 SilcBuffer packet, idp;
4350 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4351 SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4353 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4354 SilcPublicKey founder_key = NULL;
4355 unsigned char *fkey = NULL;
4356 SilcUInt32 fkey_len = 0;
4358 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4360 /* Get Channel ID */
4361 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4363 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4364 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4367 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
4369 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4370 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4374 /* Get channel entry */
4375 channel = silc_idlist_find_channel_by_id(server->local_list,
4378 channel = silc_idlist_find_channel_by_id(server->global_list,
4381 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4382 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4388 /* Check whether sender is on the channel */
4389 if (!silc_server_client_on_channel(client, channel, &chl)) {
4390 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4391 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4394 sender_mask = chl->mode;
4396 /* Get the target client's channel mode mask */
4397 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4399 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4400 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4404 SILC_GET32_MSB(target_mask, tmp_mask);
4406 /* Get target Client ID */
4407 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4409 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4410 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4413 client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
4415 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4416 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4420 /* Get target client's entry */
4421 target_client = silc_idlist_find_client_by_id(server->local_list,
4422 client_id, TRUE, NULL);
4423 if (!target_client) {
4424 target_client = silc_idlist_find_client_by_id(server->global_list,
4425 client_id, TRUE, NULL);
4428 if (target_client != client &&
4429 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4430 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4431 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4432 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
4436 /* Check whether target client is on the channel */
4437 if (target_client != client) {
4438 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4439 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4440 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL, 0);
4449 /* If the target client is founder, no one else can change their mode
4451 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4452 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4453 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
4458 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4459 if (target_client != client) {
4460 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4461 SILC_STATUS_ERR_NOT_YOU, 0);
4465 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4466 /* The client tries to claim the founder rights. */
4467 unsigned char *tmp_auth;
4468 SilcUInt32 tmp_auth_len;
4469 SilcChannelClientEntry chl2;
4470 SilcHashTableList htl;
4472 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4473 !channel->founder_key || !idata->public_key ||
4474 !silc_pkcs_public_key_compare(channel->founder_key,
4475 idata->public_key)) {
4476 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4477 SILC_STATUS_ERR_AUTH_FAILED, 0);
4481 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4483 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4484 SILC_STATUS_ERR_AUTH_FAILED, 0);
4488 /* Verify the authentication payload */
4489 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len, SILC_AUTH_PUBLIC_KEY,
4490 channel->founder_key, 0, server->sha1hash,
4491 client->id, SILC_ID_CLIENT)) {
4492 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4493 SILC_STATUS_ERR_AUTH_FAILED, 0);
4498 founder_key = channel->founder_key;
4499 fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
4501 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4502 SILC_STATUS_ERR_AUTH_FAILED, 0);
4506 /* There cannot be anyone else as founder on the channel now. This
4507 client is definitely the founder due to this authentication */
4508 silc_hash_table_list(channel->user_list, &htl);
4509 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
4510 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
4511 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4512 silc_server_force_cumode_change(server, NULL, channel, chl2,
4516 silc_hash_table_list_reset(&htl);
4518 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4521 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4522 if (target_client == client) {
4523 /* Remove channel founder rights from itself */
4524 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4527 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4528 SILC_STATUS_ERR_NOT_YOU, 0);
4534 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4535 /* Promote to operator */
4536 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4537 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4538 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4539 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4540 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
4545 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4549 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4550 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4551 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4552 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4553 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
4558 /* Demote to normal user */
4559 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4564 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4565 if (target_client != client) {
4566 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4567 SILC_STATUS_ERR_NOT_YOU, 0);
4571 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
4572 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4576 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4577 if (target_client != client) {
4578 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4579 SILC_STATUS_ERR_NOT_YOU, 0);
4583 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4588 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4589 if (target_client != client) {
4590 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4591 SILC_STATUS_ERR_NOT_YOU, 0);
4595 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)) {
4596 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4600 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4601 if (target_client != client) {
4602 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4603 SILC_STATUS_ERR_NOT_YOU, 0);
4607 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4612 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4613 if (target_client != client) {
4614 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4615 SILC_STATUS_ERR_NOT_YOU, 0);
4619 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)) {
4620 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4624 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4625 if (target_client != client) {
4626 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4627 SILC_STATUS_ERR_NOT_YOU, 0);
4631 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4636 if (target_mask & SILC_CHANNEL_UMODE_QUIET) {
4637 if (!(chl->mode & SILC_CHANNEL_UMODE_QUIET)) {
4638 if (client == target_client) {
4639 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4640 SILC_STATUS_ERR_PERM_DENIED, 0);
4643 chl->mode |= SILC_CHANNEL_UMODE_QUIET;
4647 if (chl->mode & SILC_CHANNEL_UMODE_QUIET) {
4648 if (client == target_client) {
4649 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4650 SILC_STATUS_ERR_PERM_DENIED, 0);
4653 chl->mode &= ~SILC_CHANNEL_UMODE_QUIET;
4658 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4659 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4661 /* Send notify to channel, notify only if mode was actually changed. */
4663 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4664 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
4665 idp->data, idp->len,
4670 /* Set CUMODE notify type to network */
4671 silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
4672 SILC_BROADCAST(server), channel,
4673 target_mask, client->id, SILC_ID_CLIENT,
4674 target_client->id, founder_key);
4677 /* Send command reply to sender */
4678 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4679 SILC_STATUS_OK, 0, ident, 3,
4681 3, tmp_ch_id, tmp_ch_len,
4682 4, tmp_id, tmp_len);
4683 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4684 packet->data, packet->len, FALSE);
4686 silc_buffer_free(packet);
4687 silc_free(channel_id);
4688 silc_free(client_id);
4689 silc_buffer_free(idp);
4693 silc_server_command_free(cmd);
4696 /* Server side of KICK command. Kicks client out of channel. */
4698 SILC_SERVER_CMD_FUNC(kick)
4700 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4701 SilcServer server = cmd->server;
4702 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4703 SilcClientEntry target_client;
4704 SilcChannelID *channel_id;
4705 SilcClientID *client_id;
4706 SilcChannelEntry channel;
4707 SilcChannelClientEntry chl;
4709 SilcUInt32 tmp_len, target_idp_len;
4710 unsigned char *tmp, *comment, *target_idp;
4712 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4714 /* Get Channel ID */
4715 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4717 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4718 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4721 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4723 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4724 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4728 /* Get channel entry */
4729 channel = silc_idlist_find_channel_by_id(server->local_list,
4732 channel = silc_idlist_find_channel_by_id(server->local_list,
4735 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4736 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4742 /* Check whether sender is on the channel */
4743 if (!silc_server_client_on_channel(client, channel, &chl)) {
4744 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4745 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4749 /* Check that the kicker is channel operator or channel founder */
4750 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
4751 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4752 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4753 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
4757 /* Get target Client ID */
4758 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4760 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4761 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4764 client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
4766 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4767 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4771 /* Get target client's entry */
4772 target_client = silc_idlist_find_client_by_id(server->local_list,
4773 client_id, TRUE, NULL);
4774 if (!target_client) {
4775 target_client = silc_idlist_find_client_by_id(server->global_list,
4776 client_id, TRUE, NULL);
4779 /* Check whether target client is on the channel */
4780 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4781 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4782 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL,
4787 /* Check that the target client is not channel founder. Channel founder
4788 cannot be kicked from the channel. */
4789 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4790 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4791 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
4798 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4802 /* Send command reply to sender */
4803 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4806 /* Send KICKED notify to local clients on the channel */
4807 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4808 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4809 SILC_NOTIFY_TYPE_KICKED, 3,
4810 target_idp, target_idp_len,
4811 comment, comment ? strlen(comment) : 0,
4812 idp->data, idp->len);
4813 silc_buffer_free(idp);
4815 /* Remove the client from the channel. If the channel does not exist
4816 after removing the client then the client kicked itself off the channel
4817 and we don't have to send anything after that. */
4818 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4819 target_client, FALSE))
4822 /* Send KICKED notify to primary route */
4823 silc_server_send_notify_kicked(server, SILC_PRIMARY_ROUTE(server),
4824 SILC_BROADCAST(server), channel,
4825 target_client->id, client->id, comment);
4827 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4828 /* Re-generate channel key */
4829 if (!silc_server_create_channel_key(server, channel, 0))
4832 /* Send the channel key to the channel. The key of course is not sent
4833 to the client who was kicked off the channel. */
4834 silc_server_send_channel_key(server, target_client->connection, channel,
4835 server->server_type == SILC_ROUTER ?
4836 FALSE : !server->standalone);
4840 silc_server_command_free(cmd);
4843 /* Server side of OPER command. Client uses this comand to obtain server
4844 operator privileges to this server/router. */
4846 SILC_SERVER_CMD_FUNC(oper)
4848 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4849 SilcServer server = cmd->server;
4850 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4851 unsigned char *username, *auth;
4853 SilcServerConfigAdmin *admin;
4854 SilcIDListData idata = (SilcIDListData)client;
4855 bool result = FALSE;
4856 SilcPublicKey cached_key;
4858 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4860 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4863 /* Get the username */
4864 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4866 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4867 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4872 /* Get the admin configuration */
4873 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4874 username, client->nickname);
4876 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4877 username, client->nickname);
4879 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4880 SILC_STATUS_ERR_AUTH_FAILED,
4886 /* Get the authentication payload */
4887 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4889 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4890 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4895 /* Verify the authentication data. If both passphrase and public key
4896 is set then try both of them. */
4897 if (admin->passphrase)
4898 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4899 admin->passphrase, admin->passphrase_len,
4900 idata->hash, client->id, SILC_ID_CLIENT);
4901 if (!result && admin->publickeys) {
4902 cached_key = silc_server_get_public_key(server, admin->publickeys);
4905 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4906 cached_key, 0, idata->hash,
4907 client->id, SILC_ID_CLIENT);
4910 /* Authentication failed */
4911 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4912 SILC_STATUS_ERR_AUTH_FAILED,
4917 /* Client is now server operator */
4918 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4920 /* Update statistics */
4921 if (client->connection)
4922 server->stat.my_server_ops++;
4923 if (server->server_type == SILC_ROUTER)
4924 server->stat.server_ops++;
4926 /* Send UMODE change to primary router */
4927 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
4928 SILC_BROADCAST(server), client->id,
4931 /* Check if anyone is watching this nickname */
4932 if (server->server_type == SILC_ROUTER)
4933 silc_server_check_watcher_list(server, client, NULL,
4934 SILC_NOTIFY_TYPE_UMODE_CHANGE);
4936 /* Send reply to the sender */
4937 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4941 silc_server_command_free(cmd);
4944 SILC_TASK_CALLBACK(silc_server_command_detach_cb)
4946 QuitInternal q = (QuitInternal)context;
4947 SilcClientID *client_id = (SilcClientID *)q->sock;
4948 SilcClientEntry client;
4949 SilcSocketConnection sock;
4951 client = silc_idlist_find_client_by_id(q->server->local_list, client_id,
4953 if (client && client->connection) {
4954 sock = client->connection;
4956 /* If there is pending outgoing data for the client then purge it
4957 to the network before closing connection. */
4958 silc_server_packet_queue_purge(q->server, sock);
4960 /* Close the connection on our side */
4961 client->router = NULL;
4962 client->connection = NULL;
4963 sock->user_data = NULL;
4964 silc_server_close_connection(q->server, sock);
4967 silc_free(client_id);
4971 SILC_TASK_CALLBACK(silc_server_command_detach_timeout)
4973 QuitInternal q = (QuitInternal)context;
4974 SilcClientID *client_id = (SilcClientID *)q->sock;
4975 SilcClientEntry client;
4977 client = silc_idlist_find_client_by_id(q->server->local_list, client_id,
4979 if (client && client->mode & SILC_UMODE_DETACHED) {
4980 SILC_LOG_DEBUG(("Detach timeout"));
4981 silc_server_free_client_data(q->server, NULL, client, TRUE,
4985 silc_free(client_id);
4989 /* Server side of DETACH command. Detached the client from the network
4990 by closing the connection but preserving the session. */
4992 SILC_SERVER_CMD_FUNC(detach)
4994 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4995 SilcServer server = cmd->server;
4996 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4999 if (server->config->detach_disabled) {
5000 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
5001 SILC_STATUS_ERR_UNKNOWN_COMMAND, 0);
5005 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5008 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
5010 /* Send the user mode notify to notify that client is detached */
5011 client->mode |= SILC_UMODE_DETACHED;
5012 client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
5013 client->last_command = 0;
5014 client->fast_command = 0;
5015 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
5016 SILC_BROADCAST(server), client->id,
5018 server->stat.my_detached++;
5020 /* Check if anyone is watching this nickname */
5021 if (server->server_type == SILC_ROUTER)
5022 silc_server_check_watcher_list(server, client, NULL,
5023 SILC_NOTIFY_TYPE_UMODE_CHANGE);
5025 q = silc_calloc(1, sizeof(*q));
5027 q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
5028 silc_schedule_task_add(server->schedule, 0, silc_server_command_detach_cb,
5029 q, 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
5031 if (server->config->detach_timeout) {
5032 q = silc_calloc(1, sizeof(*q));
5034 q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
5035 silc_schedule_task_add(server->schedule, 0,
5036 silc_server_command_detach_timeout,
5037 q, server->config->detach_timeout * 60,
5038 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
5041 /* Send reply to the sender */
5042 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
5046 silc_server_command_free(cmd);
5049 /* Server side of WATCH command. */
5051 SILC_SERVER_CMD_FUNC(watch)
5053 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5054 SilcServer server = cmd->server;
5055 char *add_nick, *del_nick;
5056 SilcUInt32 add_nick_len, del_nick_len, tmp_len;
5058 unsigned char hash[16], *tmp;
5059 SilcClientEntry client;
5060 SilcClientID *client_id = NULL;
5062 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WATCH, cmd, 1, 3);
5064 if (server->server_type == SILC_SERVER && !server->standalone) {
5065 if (!cmd->pending) {
5066 /* Send the command to router */
5068 SilcUInt16 old_ident;
5070 old_ident = silc_command_get_ident(cmd->payload);
5071 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5072 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5074 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5075 SILC_PACKET_COMMAND, cmd->packet->flags,
5076 tmpbuf->data, tmpbuf->len, TRUE);
5078 /* Reprocess this packet after received reply from router */
5079 silc_server_command_pending(server, SILC_COMMAND_WATCH,
5080 silc_command_get_ident(cmd->payload),
5081 silc_server_command_watch,
5082 silc_server_command_dup(cmd));
5083 cmd->pending = TRUE;
5084 silc_command_set_ident(cmd->payload, old_ident);
5085 silc_buffer_free(tmpbuf);
5086 } else if (context2) {
5087 /* Received reply from router, just send same data to the client. */
5088 SilcServerCommandReplyContext reply = context2;
5090 silc_command_get_status(reply->payload, &status, NULL);
5091 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, status,
5098 /* We are router and keep the watch list for local cell */
5100 /* Get the client ID */
5101 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5103 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5104 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5108 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
5110 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5111 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5116 /* Get the client entry which must be in local list */
5117 client = silc_idlist_find_client_by_id(server->local_list,
5118 client_id, TRUE, NULL);
5120 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5121 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5127 add_nick = silc_argument_get_arg_type(cmd->args, 2, &add_nick_len);
5128 del_nick = silc_argument_get_arg_type(cmd->args, 3, &del_nick_len);
5129 if (!add_nick && !del_nick) {
5130 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5131 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5136 if (add_nick && add_nick_len > 128)
5137 add_nick[128] = '\0';
5138 if (del_nick && del_nick_len > 128)
5139 del_nick[128] = '\0';
5141 memset(nick, 0, sizeof(nick));
5143 /* Add new nickname to be watched in our cell */
5145 if (silc_server_name_bad_chars(add_nick, strlen(add_nick)) == TRUE) {
5146 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5147 SILC_STATUS_ERR_BAD_NICKNAME, 0);
5151 /* Hash the nick, we have the hash saved, not nicks because we can
5152 do one to one mapping to the nick from Client ID hash this way. */
5153 silc_to_lower(add_nick, nick, sizeof(nick) - 1);
5154 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
5156 /* Check whether this client is already watching this nickname */
5157 if (silc_hash_table_find_by_context(server->watcher_list, hash,
5159 /* Nickname is alredy being watched for this client */
5160 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5161 SILC_STATUS_ERR_NICKNAME_IN_USE,
5166 /* Get the nickname from the watcher list and use the same key in
5167 new entries as well. If key doesn't exist then create it. */
5168 if (!silc_hash_table_find(server->watcher_list, hash, (void **)&tmp, NULL))
5169 tmp = silc_memdup(hash, CLIENTID_HASH_LEN);
5171 /* Add the client to the watcher list with the specified nickname hash. */
5172 silc_hash_table_add(server->watcher_list, tmp, client);
5175 /* Delete nickname from watch list */
5177 if (silc_server_name_bad_chars(del_nick, strlen(del_nick)) == TRUE) {
5178 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5179 SILC_STATUS_ERR_BAD_NICKNAME, 0);
5183 /* Hash the nick, we have the hash saved, not nicks because we can
5184 do one to one mapping to the nick from Client ID hash this way. */
5185 silc_to_lower(del_nick, nick, sizeof(nick) - 1);
5186 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
5188 /* Check that this client is watching for this nickname */
5189 if (!silc_hash_table_find_by_context(server->watcher_list, hash,
5190 client, (void **)&tmp)) {
5191 /* Nickname is alredy being watched for this client */
5192 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5193 SILC_STATUS_ERR_NO_SUCH_NICK, 0);
5197 /* Delete the nickname from the watcher list. */
5198 silc_hash_table_del_by_context(server->watcher_list, hash, client);
5200 /* Now check whether there still exists entries with this key, if not
5201 then free the key to not leak memory. */
5202 if (!silc_hash_table_find(server->watcher_list, hash, NULL, NULL))
5206 /* Distribute the watch list to backup routers too */
5207 if (server->backup) {
5209 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5210 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5211 silc_server_backup_send(server, NULL, SILC_PACKET_COMMAND,
5212 cmd->packet->flags, tmpbuf->data, tmpbuf->len,
5214 silc_buffer_free(tmpbuf);
5217 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5221 silc_free(client_id);
5222 silc_server_command_free(cmd);
5225 /* Server side of SILCOPER command. Client uses this comand to obtain router
5226 operator privileges to this router. */
5228 SILC_SERVER_CMD_FUNC(silcoper)
5230 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5231 SilcServer server = cmd->server;
5232 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5233 unsigned char *username, *auth;
5235 SilcServerConfigAdmin *admin;
5236 SilcIDListData idata = (SilcIDListData)client;
5237 bool result = FALSE;
5238 SilcPublicKey cached_key;
5240 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
5242 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5245 if (server->server_type != SILC_ROUTER) {
5246 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5247 SILC_STATUS_ERR_AUTH_FAILED, 0);
5251 /* Get the username */
5252 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5254 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5255 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5260 /* Get the admin configuration */
5261 admin = silc_server_config_find_admin(server, cmd->sock->ip,
5262 username, client->nickname);
5264 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
5265 username, client->nickname);
5267 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5268 SILC_STATUS_ERR_AUTH_FAILED, 0);
5273 /* Get the authentication payload */
5274 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5276 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5277 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5282 /* Verify the authentication data. If both passphrase and public key
5283 is set then try both of them. */
5284 if (admin->passphrase)
5285 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
5286 admin->passphrase, admin->passphrase_len,
5287 idata->hash, client->id, SILC_ID_CLIENT);
5288 if (!result && admin->publickeys) {
5289 cached_key = silc_server_get_public_key(server, admin->publickeys);
5292 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
5293 cached_key, 0, idata->hash,
5294 client->id, SILC_ID_CLIENT);
5297 /* Authentication failed */
5298 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
5299 SILC_STATUS_ERR_AUTH_FAILED, 0);
5303 /* Client is now router operator */
5304 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
5306 /* Update statistics */
5307 if (client->connection)
5308 server->stat.my_router_ops++;
5309 if (server->server_type == SILC_ROUTER)
5310 server->stat.router_ops++;
5312 /* Send UMODE change to primary router */
5313 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
5314 SILC_BROADCAST(server), client->id,
5317 /* Check if anyone is watching this nickname */
5318 if (server->server_type == SILC_ROUTER)
5319 silc_server_check_watcher_list(server, client, NULL,
5320 SILC_NOTIFY_TYPE_UMODE_CHANGE);
5322 /* Send reply to the sender */
5323 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5327 silc_server_command_free(cmd);
5330 /* Server side of command BAN. This is used to manage the ban list of the
5331 channel. To add clients and remove clients from the ban list. */
5333 SILC_SERVER_CMD_FUNC(ban)
5335 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5336 SilcServer server = cmd->server;
5337 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5339 SilcChannelEntry channel;
5340 SilcChannelClientEntry chl;
5341 SilcChannelID *channel_id = NULL;
5342 unsigned char *id, *add, *del;
5343 SilcUInt32 id_len, tmp_len;
5344 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5346 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5349 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
5351 /* Get Channel ID */
5352 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
5354 channel_id = silc_id_payload_parse_id(id, id_len, NULL);
5356 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5357 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5362 /* Get channel entry. The server must know about the channel since the
5363 client is expected to be on the channel. */
5364 channel = silc_idlist_find_channel_by_id(server->local_list,
5367 channel = silc_idlist_find_channel_by_id(server->global_list,
5370 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5371 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5377 /* Check whether this client is on the channel */
5378 if (!silc_server_client_on_channel(client, channel, &chl)) {
5379 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5380 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5384 /* The client must be at least channel operator. */
5385 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
5386 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5387 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
5391 /* Get the new ban and add it to the ban list */
5392 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5394 if (!channel->ban_list)
5395 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
5397 channel->ban_list = silc_realloc(channel->ban_list,
5398 sizeof(*channel->ban_list) *
5400 strlen(channel->ban_list) + 2));
5401 if (add[tmp_len - 1] == ',')
5402 add[tmp_len - 1] = '\0';
5404 strncat(channel->ban_list, add, tmp_len);
5405 strncat(channel->ban_list, ",", 1);
5408 /* Get the ban to be removed and remove it from the list */
5409 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
5410 if (del && channel->ban_list) {
5411 char *start, *end, *n;
5413 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
5414 silc_free(channel->ban_list);
5415 channel->ban_list = NULL;
5417 start = strstr(channel->ban_list, del);
5418 if (start && strlen(start) >= tmp_len) {
5419 end = start + tmp_len;
5420 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
5421 strncat(n, channel->ban_list, start - channel->ban_list);
5422 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
5424 silc_free(channel->ban_list);
5425 channel->ban_list = n;
5430 /* Send the BAN notify type to our primary router. */
5432 silc_server_send_notify_ban(server, SILC_PRIMARY_ROUTE(server),
5433 SILC_BROADCAST(server), channel, add, del);
5435 /* Send the reply back to the client */
5437 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
5438 SILC_STATUS_OK, 0, ident, 2,
5440 3, channel->ban_list,
5442 strlen(channel->ban_list) -1 : 0);
5443 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5444 packet->data, packet->len, FALSE);
5446 silc_buffer_free(packet);
5449 silc_free(channel_id);
5450 silc_server_command_free(cmd);
5453 /* Server side command of LEAVE. Removes client from a channel. */
5455 SILC_SERVER_CMD_FUNC(leave)
5457 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5458 SilcServer server = cmd->server;
5459 SilcSocketConnection sock = cmd->sock;
5460 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
5461 SilcChannelID *id = NULL;
5462 SilcChannelEntry channel;
5466 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
5468 /* Get Channel ID */
5469 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
5471 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5472 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5475 id = silc_id_payload_parse_id(tmp, len, NULL);
5477 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5478 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5482 /* Get channel entry */
5483 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5485 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5487 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5488 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5494 /* Check whether this client is on the channel */
5495 if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
5496 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5497 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5501 /* Notify routers that they should remove this client from their list
5502 of clients on the channel. Send LEAVE notify type. */
5503 silc_server_send_notify_leave(server, SILC_PRIMARY_ROUTE(server),
5504 SILC_BROADCAST(server), channel, id_entry->id);
5506 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
5507 SILC_STATUS_OK, 0, 2, tmp, len);
5509 /* Remove client from channel */
5510 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5512 /* If the channel does not exist anymore we won't send anything */
5515 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5516 /* Re-generate channel key */
5517 if (!silc_server_create_channel_key(server, channel, 0))
5520 /* Send the channel key */
5521 silc_server_send_channel_key(server, NULL, channel,
5522 server->server_type == SILC_ROUTER ?
5523 FALSE : !server->standalone);
5528 silc_server_command_free(cmd);
5531 /* Server side of command USERS. Resolves clients and their USERS currently
5532 joined on the requested channel. The list of Client ID's and their modes
5533 on the channel is sent back. */
5535 SILC_SERVER_CMD_FUNC(users)
5537 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5538 SilcServer server = cmd->server;
5539 SilcChannelEntry channel;
5540 SilcChannelID *id = NULL;
5541 SilcBuffer packet, idp;
5542 unsigned char *channel_id;
5543 SilcUInt32 channel_id_len;
5544 SilcBuffer client_id_list;
5545 SilcBuffer client_mode_list;
5546 unsigned char lc[4];
5547 SilcUInt32 list_count = 0;
5548 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5551 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5553 /* Get Channel ID */
5554 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5556 /* Get channel name */
5557 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5559 if (!channel_id && !channel_name) {
5560 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5561 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5566 id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
5568 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5569 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5574 /* If we are server and we don't know about this channel we will send
5575 the command to our router. If we know about the channel then we also
5576 have the list of users already. */
5578 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5580 channel = silc_idlist_find_channel_by_name(server->local_list,
5581 channel_name, NULL);
5583 if (!channel || (!server->standalone && (channel->disabled ||
5584 !channel->users_resolved))) {
5585 if (server->server_type != SILC_ROUTER && !server->standalone &&
5589 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5590 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5592 /* Send USERS command */
5593 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5594 SILC_PACKET_COMMAND, cmd->packet->flags,
5595 tmpbuf->data, tmpbuf->len, TRUE);
5597 /* Reprocess this packet after received reply */
5598 silc_server_command_pending(server, SILC_COMMAND_USERS,
5599 silc_command_get_ident(cmd->payload),
5600 silc_server_command_users,
5601 silc_server_command_dup(cmd));
5602 cmd->pending = TRUE;
5603 silc_command_set_ident(cmd->payload, ident);
5604 silc_buffer_free(tmpbuf);
5609 /* Check the global list as well. */
5611 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5613 channel = silc_idlist_find_channel_by_name(server->global_list,
5614 channel_name, NULL);
5616 /* Channel really does not exist */
5617 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5618 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5624 /* If the channel is private or secret do not send anything, unless the
5625 user requesting this command is on the channel or is server */
5626 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5627 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5628 && !silc_server_client_on_channel(cmd->sock->user_data, channel,
5630 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5631 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5636 /* Get the users list */
5637 if (!silc_server_get_users_on_channel(server, channel, &client_id_list,
5638 &client_mode_list, &list_count)) {
5640 client_id_list = NULL;
5641 client_mode_list = NULL;
5645 SILC_PUT32_MSB(list_count, lc);
5648 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5649 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5650 SILC_STATUS_OK, 0, ident, 4,
5651 2, idp->data, idp->len,
5654 client_id_list->data : NULL,
5656 client_id_list->len : 0,
5657 5, client_mode_list ?
5658 client_mode_list->data : NULL,
5660 client_mode_list->len : 0);
5661 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5662 packet->data, packet->len, FALSE);
5664 silc_buffer_free(idp);
5665 silc_buffer_free(packet);
5667 silc_buffer_free(client_id_list);
5668 if (client_mode_list)
5669 silc_buffer_free(client_mode_list);
5673 silc_server_command_free(cmd);
5676 /* Server side of command GETKEY. This fetches the client's public key
5677 from the server where to the client is connected. */
5679 SILC_SERVER_CMD_FUNC(getkey)
5681 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5682 SilcServer server = cmd->server;
5684 SilcClientEntry client;
5685 SilcServerEntry server_entry;
5686 SilcClientID *client_id = NULL;
5687 SilcServerID *server_id = NULL;
5688 SilcIDPayload idp = NULL;
5689 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5690 unsigned char *tmp, *pkdata;
5691 SilcUInt32 tmp_len, pklen;
5692 SilcBuffer pk = NULL;
5694 SilcPublicKey public_key;
5696 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5698 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5699 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5703 idp = silc_id_payload_parse(tmp, tmp_len);
5705 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5706 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5711 id_type = silc_id_payload_get_type(idp);
5712 if (id_type == SILC_ID_CLIENT) {
5713 client_id = silc_id_payload_get_id(idp);
5715 /* If the client is not found from local list there is no chance it
5716 would be locally connected client so send the command further. */
5717 client = silc_idlist_find_client_by_id(server->local_list,
5718 client_id, TRUE, NULL);
5720 client = silc_idlist_find_client_by_id(server->global_list,
5721 client_id, TRUE, NULL);
5723 if ((!client && !cmd->pending && !server->standalone) ||
5724 (client && !client->connection && !cmd->pending &&
5725 !(client->mode & SILC_UMODE_DETACHED)) ||
5726 (client && !client->data.public_key && !cmd->pending)) {
5728 SilcUInt16 old_ident;
5729 SilcSocketConnection dest_sock;
5731 dest_sock = silc_server_get_client_route(server, NULL, 0,
5732 client_id, NULL, NULL);
5736 old_ident = silc_command_get_ident(cmd->payload);
5737 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5738 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5740 silc_server_packet_send(server, dest_sock,
5741 SILC_PACKET_COMMAND, cmd->packet->flags,
5742 tmpbuf->data, tmpbuf->len, TRUE);
5744 /* Reprocess this packet after received reply from router */
5745 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5746 silc_command_get_ident(cmd->payload),
5747 silc_server_command_getkey,
5748 silc_server_command_dup(cmd));
5749 cmd->pending = TRUE;
5750 silc_command_set_ident(cmd->payload, old_ident);
5751 silc_buffer_free(tmpbuf);
5756 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5757 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5762 /* The client is locally connected, just get the public key and
5763 send it back. If they key does not exist then do not send it,
5764 send just OK reply */
5765 public_key = client->data.public_key;
5770 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5771 pk = silc_buffer_alloc(4 + tmp_len);
5772 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5773 silc_buffer_format(pk,
5774 SILC_STR_UI_SHORT(tmp_len),
5775 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5776 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5782 } else if (id_type == SILC_ID_SERVER) {
5783 server_id = silc_id_payload_get_id(idp);
5785 /* If the server is not found from local list there is no chance it
5786 would be locally connected server so send the command further. */
5787 server_entry = silc_idlist_find_server_by_id(server->local_list,
5788 server_id, TRUE, NULL);
5790 server_entry = silc_idlist_find_server_by_id(server->global_list,
5791 server_id, TRUE, NULL);
5793 if (server_entry != server->id_entry &&
5794 ((!server_entry && !cmd->pending && !server->standalone) ||
5795 (server_entry && !server_entry->connection && !cmd->pending &&
5796 !server->standalone) ||
5797 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5798 !server->standalone))) {
5800 SilcUInt16 old_ident;
5802 old_ident = silc_command_get_ident(cmd->payload);
5803 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5804 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5806 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5807 SILC_PACKET_COMMAND, cmd->packet->flags,
5808 tmpbuf->data, tmpbuf->len, TRUE);
5810 /* Reprocess this packet after received reply from router */
5811 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5812 silc_command_get_ident(cmd->payload),
5813 silc_server_command_getkey,
5814 silc_server_command_dup(cmd));
5815 cmd->pending = TRUE;
5816 silc_command_set_ident(cmd->payload, old_ident);
5817 silc_buffer_free(tmpbuf);
5821 if (!server_entry) {
5822 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5823 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
5828 /* If they key does not exist then do not send it, send just OK reply */
5829 public_key = (!server_entry->data.public_key ?
5830 (server_entry == server->id_entry ? server->public_key :
5831 NULL) : server_entry->data.public_key);
5836 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5837 pk = silc_buffer_alloc(4 + tmp_len);
5838 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5839 silc_buffer_format(pk,
5840 SILC_STR_UI_SHORT(tmp_len),
5841 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5842 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5852 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5853 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5854 SILC_STATUS_OK, 0, ident,
5858 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5859 packet->data, packet->len, FALSE);
5860 silc_buffer_free(packet);
5863 silc_buffer_free(pk);
5867 silc_id_payload_free(idp);
5868 silc_free(client_id);
5869 silc_free(server_id);
5870 silc_server_command_free(cmd);
5874 /* Private range commands, specific to this implementation */
5876 /* Server side command of CONNECT. Connects us to the specified remote
5877 server or router. */
5879 SILC_SERVER_CMD_FUNC(connect)
5881 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5882 SilcServer server = cmd->server;
5883 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5884 unsigned char *tmp, *host;
5886 SilcUInt32 port = SILC_PORT;
5888 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
5890 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5893 /* Check whether client has the permissions. */
5894 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5895 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5896 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5897 SILC_STATUS_ERR_NO_SERVER_PRIV, 0);
5901 if (server->server_type == SILC_ROUTER &&
5902 client->mode & SILC_UMODE_SERVER_OPERATOR) {
5903 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5904 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
5908 /* Get the remote server */
5909 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5911 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5912 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5918 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5920 SILC_GET32_MSB(port, tmp);
5922 /* Create the connection. It is done with timeout and is async. */
5923 silc_server_create_connection(server, host, port);
5925 /* Send reply to the sender */
5926 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5930 silc_server_command_free(cmd);
5933 /* Server side command of CLOSE. Closes connection to a specified server. */
5935 SILC_SERVER_CMD_FUNC(close)
5937 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5938 SilcServer server = cmd->server;
5939 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5940 SilcServerEntry server_entry;
5941 SilcSocketConnection sock;
5944 unsigned char *name;
5945 SilcUInt32 port = SILC_PORT;
5947 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
5949 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5952 /* Check whether client has the permissions. */
5953 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5954 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5955 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5956 SILC_STATUS_ERR_NO_SERVER_PRIV,
5961 /* Get the remote server */
5962 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5964 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5965 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5971 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5973 SILC_GET32_MSB(port, tmp);
5975 server_entry = silc_idlist_find_server_by_conn(server->local_list,
5976 name, port, FALSE, NULL);
5978 server_entry = silc_idlist_find_server_by_conn(server->global_list,
5979 name, port, FALSE, NULL);
5980 if (!server_entry) {
5981 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5982 SILC_STATUS_ERR_NO_SERVER_ID, 0);
5986 /* Send reply to the sender */
5987 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5990 /* Close the connection to the server */
5991 sock = (SilcSocketConnection)server_entry->connection;
5993 /* If we shutdown primary router connection manually then don't trigger
5994 any reconnect or backup router connections, by setting the router
5996 if (server->router == server_entry) {
5997 server->id_entry->router = NULL;
5998 server->router = NULL;
5999 server->standalone = TRUE;
6001 silc_server_free_sock_user_data(server, sock, NULL);
6002 silc_server_close_connection(server, sock);
6005 silc_server_command_free(cmd);
6008 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
6009 active connections. */
6011 SILC_SERVER_CMD_FUNC(shutdown)
6013 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
6014 SilcServer server = cmd->server;
6015 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
6017 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
6019 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
6022 /* Check whether client has the permission. */
6023 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
6024 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
6025 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
6026 SILC_STATUS_ERR_NO_SERVER_PRIV,
6031 /* Send reply to the sender */
6032 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
6035 /* Then, gracefully, or not, bring the server down. */
6036 silc_server_stop(server);
6040 silc_server_command_free(cmd);