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 server->router->connection,
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, (SilcSocketConnection)
1270 server->router->connection,
1271 SILC_PACKET_COMMAND, cmd->packet->flags,
1272 tmpbuf->data, tmpbuf->len, TRUE);
1274 /* Reprocess this packet after received reply from router */
1275 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1276 silc_command_get_ident(cmd->payload),
1277 silc_server_command_whowas,
1278 silc_server_command_dup(cmd));
1279 cmd->pending = TRUE;
1280 silc_command_set_ident(cmd->payload, old_ident);
1282 silc_buffer_free(tmpbuf);
1287 /* We are ready to process the command request. Let's search for the
1288 requested client and send reply to the requesting client. */
1290 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1291 check_global = TRUE;
1292 else if (server->server_type != SILC_SERVER)
1293 check_global = TRUE;
1295 /* Parse the whowas request */
1296 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1299 /* Get all clients matching that nickname from local list */
1300 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1302 &clients, &clients_count))
1303 silc_idlist_get_clients_by_hash(server->local_list,
1304 nick, server->md5hash,
1305 &clients, &clients_count);
1307 /* Check global list as well */
1309 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1311 &clients, &clients_count))
1312 silc_idlist_get_clients_by_hash(server->global_list,
1313 nick, server->md5hash,
1314 &clients, &clients_count);
1318 /* Such a client really does not exist in the SILC network. */
1319 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1320 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1321 3, nick, strlen(nick));
1325 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1330 /* Send the command reply to the client */
1331 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1336 silc_free(server_name);
1340 /* Server side of command WHOWAS. */
1342 SILC_SERVER_CMD_FUNC(whowas)
1344 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1347 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1349 ret = silc_server_command_whowas_process(cmd);
1350 silc_server_command_free(cmd);
1353 /******************************************************************************
1357 ******************************************************************************/
1360 silc_server_command_identify_send_router(SilcServerCommandContext cmd)
1362 SilcServer server = cmd->server;
1364 SilcUInt16 old_ident;
1366 old_ident = silc_command_get_ident(cmd->payload);
1367 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1368 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1370 /* Send IDENTIFY command to our router */
1371 silc_server_packet_send(server, (SilcSocketConnection)
1372 server->router->connection,
1373 SILC_PACKET_COMMAND, cmd->packet->flags,
1374 tmpbuf->data, tmpbuf->len, TRUE);
1376 /* Reprocess this packet after received reply from router */
1377 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1378 silc_command_get_ident(cmd->payload),
1379 silc_server_command_identify,
1380 silc_server_command_dup(cmd));
1381 cmd->pending = TRUE;
1382 silc_command_set_ident(cmd->payload, old_ident);
1383 silc_buffer_free(tmpbuf);
1387 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1388 SilcClientEntry **clients,
1389 SilcUInt32 *clients_count,
1390 SilcServerEntry **servers,
1391 SilcUInt32 *servers_count,
1392 SilcChannelEntry **channels,
1393 SilcUInt32 *channels_count,
1395 ResolveError *error_id,
1396 SilcUInt32 *error_id_count)
1398 SilcServer server = cmd->server;
1401 SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
1403 bool check_global = FALSE;
1407 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1408 check_global = TRUE;
1409 else if (server->server_type != SILC_SERVER)
1410 check_global = TRUE;
1412 /* If ID Payload is in the command it must be used instead of names */
1413 tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1415 /* No ID, get the names. */
1417 /* If we are normal server and have not resolved information from
1418 router yet, do so now. */
1419 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1420 server->server_type == SILC_SERVER && !cmd->pending &&
1421 !server->standalone) {
1422 silc_server_command_identify_send_router(cmd);
1426 /* Try to get nickname@server. */
1427 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1430 char *nick_server = NULL;
1432 silc_parse_userfqdn(tmp, &nick, &nick_server);
1434 if (!silc_idlist_get_clients_by_hash(server->local_list,
1435 nick, server->md5hash,
1436 clients, clients_count))
1437 silc_idlist_get_clients_by_nickname(server->local_list,
1439 clients, clients_count);
1441 if (!silc_idlist_get_clients_by_hash(server->global_list,
1442 nick, server->md5hash,
1443 clients, clients_count))
1444 silc_idlist_get_clients_by_nickname(server->global_list,
1446 clients, clients_count);
1450 silc_free(nick_server);
1453 /* the nickname does not exist, send error reply */
1454 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1455 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1456 3, tmp, strlen(tmp));
1461 /* Try to get server name */
1462 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1464 entry = silc_idlist_find_server_by_name(server->local_list,
1466 if (!entry && check_global)
1467 entry = silc_idlist_find_server_by_name(server->global_list,
1470 *servers = silc_realloc(*servers, sizeof(**servers) *
1471 (*servers_count + 1));
1472 (*servers)[(*servers_count)++] = entry;
1476 /* the server does not exist, send error reply */
1477 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1478 SILC_STATUS_ERR_NO_SUCH_SERVER,
1479 0, 3, tmp, strlen(tmp));
1484 /* Try to get channel name */
1485 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1487 entry = silc_idlist_find_channel_by_name(server->local_list,
1489 if (!entry && check_global)
1490 entry = silc_idlist_find_channel_by_name(server->global_list,
1493 *channels = silc_realloc(*channels, sizeof(**channels) *
1494 (*channels_count + 1));
1495 (*channels)[(*channels_count)++] = entry;
1499 /* The channel does not exist, send error reply */
1500 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1501 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1502 0, 3, tmp, strlen(tmp));
1507 if (!(*clients) && !(*servers) && !(*channels)) {
1508 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1509 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1514 /* Command includes ID, we must use that. Also check whether the command
1515 has more than one ID set - take them all. */
1517 /* Take all ID's from the command packet */
1518 for (i = 0; i < argc; i++) {
1521 tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
1525 idp = silc_id_payload_parse(tmp, len);
1527 ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1528 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1530 id = silc_id_payload_get_id(idp);
1531 switch (silc_id_payload_get_type(idp)) {
1533 case SILC_ID_CLIENT:
1534 entry = silc_idlist_find_client_by_id(server->local_list,
1536 if (!entry && check_global)
1537 entry = silc_idlist_find_client_by_id(server->global_list,
1540 *clients = silc_realloc(*clients, sizeof(**clients) *
1541 (*clients_count + 1));
1542 (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
1544 /* If we are normal server and have not resolved information from
1545 router yet, do so now. */
1546 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1547 server->server_type == SILC_SERVER && !cmd->pending &&
1548 !server->standalone) {
1549 silc_server_command_identify_send_router(cmd);
1550 silc_free(*clients);
1551 silc_free(*servers);
1552 silc_free(*channels);
1553 silc_free(*error_id);
1557 ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1558 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
1563 case SILC_ID_SERVER:
1564 entry = silc_idlist_find_server_by_id(server->local_list,
1566 if (!entry && check_global)
1567 entry = silc_idlist_find_server_by_id(server->global_list,
1570 *servers = silc_realloc(*servers, sizeof(**servers) *
1571 (*servers_count + 1));
1572 (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
1574 /* If we are normal server and have not resolved information from
1575 router yet, do so now. */
1576 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1577 server->server_type == SILC_SERVER && !cmd->pending &&
1578 !server->standalone) {
1579 silc_server_command_identify_send_router(cmd);
1580 silc_free(*clients);
1581 silc_free(*servers);
1582 silc_free(*channels);
1583 silc_free(*error_id);
1587 ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1588 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
1592 case SILC_ID_CHANNEL:
1593 entry = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
1594 if (!entry && check_global)
1595 entry = silc_idlist_find_channel_by_id(server->global_list, id,
1598 *channels = silc_realloc(*channels, sizeof(**channels) *
1599 (*channels_count + 1));
1600 (*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
1602 /* If we are normal server and have not resolved information from
1603 router yet, do so now. */
1604 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1605 server->server_type == SILC_SERVER && !cmd->pending &&
1606 !server->standalone) {
1607 silc_server_command_identify_send_router(cmd);
1608 silc_free(*clients);
1609 silc_free(*servers);
1610 silc_free(*channels);
1611 silc_free(*error_id);
1615 ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1616 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID);
1625 /* Get the max count of reply messages allowed */
1626 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1628 SILC_GET32_MSB(*count, tmp);
1635 /* Checks that all mandatory fields in client entry are present. If not
1636 then send WHOIS request to the server who owns the client. We use
1637 WHOIS because we want to get as much information as possible at once. */
1640 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1641 SilcClientEntry *clients,
1642 SilcUInt32 clients_count)
1644 SilcServer server = cmd->server;
1645 SilcClientEntry entry;
1646 SilcServerResolveContext resolve = NULL, r = NULL;
1647 SilcUInt32 resolve_count = 0;
1651 for (i = 0; i < clients_count; i++) {
1656 if (entry->nickname ||
1657 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1661 /* If we are normal server, and we've not resolved this client from
1662 router and it is global client, we'll check whether it is on some
1663 channel. If not then we cannot be sure about its validity, and
1664 we'll resolve it from router. */
1665 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
1666 entry->connection || silc_hash_table_count(entry->channels))
1670 /* We need to resolve this entry since it is not complete */
1672 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1673 /* The entry is being resolved (and we are not the resolver) so attach
1674 to the command reply and we're done with this one. */
1675 silc_server_command_pending(server, SILC_COMMAND_NONE,
1676 entry->resolve_cmd_ident,
1677 silc_server_command_identify,
1678 silc_server_command_dup(cmd));
1681 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1682 /* We've resolved this and it still is not ready. We'll return
1683 and are that this will be handled again after it is resolved. */
1684 for (i = 0; i < resolve_count; i++) {
1685 for (k = 0; k < r->res_argc; k++)
1686 silc_free(r->res_argv[k]);
1687 silc_free(r->res_argv);
1688 silc_free(r->res_argv_lens);
1689 silc_free(r->res_argv_types);
1694 /* We'll resolve this client */
1698 for (k = 0; k < resolve_count; k++) {
1699 if (resolve[k].router == entry->router) {
1706 resolve = silc_realloc(resolve, sizeof(*resolve) *
1707 (resolve_count + 1));
1708 r = &resolve[resolve_count];
1709 memset(r, 0, sizeof(*r));
1710 r->router = entry->router;
1711 r->ident = ++server->cmd_ident;
1715 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1717 r->res_argv_lens = silc_realloc(r->res_argv_lens,
1718 sizeof(*r->res_argv_lens) *
1720 r->res_argv_types = silc_realloc(r->res_argv_types,
1721 sizeof(*r->res_argv_types) *
1723 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1724 r->res_argv[r->res_argc] = silc_calloc(idp->len,
1725 sizeof(**r->res_argv));
1726 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1727 r->res_argv_lens[r->res_argc] = idp->len;
1728 r->res_argv_types[r->res_argc] = r->res_argc + 4;
1730 silc_buffer_free(idp);
1732 entry->resolve_cmd_ident = r->ident;
1733 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1734 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1739 /* Do the resolving */
1740 for (i = 0; i < resolve_count; i++) {
1745 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1746 now anyway so make it a good one. */
1747 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1748 r->res_argc, r->res_argv,
1752 silc_server_packet_send(server, r->router->connection,
1753 SILC_PACKET_COMMAND, cmd->packet->flags,
1754 res_cmd->data, res_cmd->len, FALSE);
1756 /* Reprocess this packet after received reply */
1757 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1759 silc_server_command_identify,
1760 silc_server_command_dup(cmd));
1761 cmd->pending = TRUE;
1763 silc_buffer_free(res_cmd);
1764 for (k = 0; k < r->res_argc; k++)
1765 silc_free(r->res_argv[k]);
1766 silc_free(r->res_argv);
1767 silc_free(r->res_argv_lens);
1768 silc_free(r->res_argv_types);
1777 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1778 SilcClientEntry *clients,
1779 SilcUInt32 clients_count,
1780 SilcServerEntry *servers,
1781 SilcUInt32 servers_count,
1782 SilcChannelEntry *channels,
1783 SilcUInt32 channels_count,
1784 ResolveError errors,
1785 SilcUInt32 errors_count,
1788 SilcServer server = cmd->server;
1789 int i, k, valid_count;
1791 SilcBuffer packet, idp;
1793 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1794 char nh[256], uh[256];
1795 SilcSocketConnection hsock;
1798 status = SILC_STATUS_OK;
1801 SilcClientEntry entry;
1802 valid_count = clients_count;
1804 if (silc_argument_get_arg_type(cmd->args, 1, NULL)) {
1805 /* Process only valid clients and ignore those that are not registered.
1806 This is checked with nickname only because when resolved client IDs
1807 we check that they are registered earlier. */
1809 for (i = 0; i < clients_count; i++) {
1810 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1817 /* No valid entries found at all, just send error */
1818 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1819 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1820 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1821 3, tmp, tmp ? strlen(tmp) : 0);
1826 /* Process all valid client entries and send command replies */
1828 if (valid_count > 1)
1829 status = SILC_STATUS_LIST_START;
1831 for (i = 0, k = 0; i < clients_count; i++) {
1837 status = SILC_STATUS_LIST_ITEM;
1838 if (valid_count > 1 && k == valid_count - 1
1839 && !servers_count && !channels_count && !errors_count)
1840 status = SILC_STATUS_LIST_END;
1841 if (count && k - 1 == count)
1842 status = SILC_STATUS_LIST_END;
1844 /* Send IDENTIFY reply */
1846 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1847 memset(uh, 0, sizeof(uh));
1848 memset(nh, 0, sizeof(nh));
1849 strncat(nh, entry->nickname, strlen(entry->nickname));
1850 if (!strchr(entry->nickname, '@')) {
1851 strncat(nh, "@", 1);
1852 if (entry->servername) {
1853 strncat(nh, entry->servername, strlen(entry->servername));
1855 len = entry->router ? strlen(entry->router->server_name) :
1856 strlen(server->server_name);
1857 strncat(nh, entry->router ? entry->router->server_name :
1858 server->server_name, len);
1862 if (!entry->username) {
1863 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1864 status, 0, ident, 2,
1865 2, idp->data, idp->len,
1868 strncat(uh, entry->username, strlen(entry->username));
1869 if (!strchr(entry->username, '@') && entry->connection) {
1870 strncat(uh, "@", 1);
1871 hsock = (SilcSocketConnection)entry->connection;
1872 len = strlen(hsock->hostname);
1873 strncat(uh, hsock->hostname, len);
1876 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1877 status, 0, ident, 3,
1878 2, idp->data, idp->len,
1883 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1884 0, packet->data, packet->len, FALSE);
1886 silc_buffer_free(packet);
1887 silc_buffer_free(idp);
1889 if (status == SILC_STATUS_LIST_END)
1896 SilcServerEntry entry;
1898 if (status == SILC_STATUS_OK && servers_count > 1)
1899 status = SILC_STATUS_LIST_START;
1901 for (i = 0, k = 0; i < servers_count; i++) {
1905 status = SILC_STATUS_LIST_ITEM;
1906 if (servers_count > 1 && k == servers_count - 1 && !channels_count &&
1908 status = SILC_STATUS_LIST_END;
1909 if (count && k - 1 == count)
1910 status = SILC_STATUS_LIST_END;
1912 /* Send IDENTIFY reply */
1913 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1915 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1916 status, 0, ident, 2,
1917 2, idp->data, idp->len,
1918 3, entry->server_name,
1919 entry->server_name ?
1920 strlen(entry->server_name) : 0);
1921 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1922 0, packet->data, packet->len, FALSE);
1924 silc_buffer_free(packet);
1925 silc_buffer_free(idp);
1927 if (status == SILC_STATUS_LIST_END)
1934 SilcChannelEntry entry;
1936 if (status == SILC_STATUS_OK && channels_count > 1)
1937 status = SILC_STATUS_LIST_START;
1939 for (i = 0, k = 0; i < channels_count; i++) {
1940 entry = channels[i];
1943 status = SILC_STATUS_LIST_ITEM;
1944 if (channels_count > 1 && k == channels_count - 1 && !errors_count)
1945 status = SILC_STATUS_LIST_END;
1946 if (count && k - 1 == count)
1947 status = SILC_STATUS_LIST_END;
1949 /* Send IDENTIFY reply */
1950 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1952 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1953 status, 0, ident, 2,
1954 2, idp->data, idp->len,
1955 3, entry->channel_name,
1956 entry->channel_name ?
1957 strlen(entry->channel_name): 0);
1958 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1959 0, packet->data, packet->len, FALSE);
1961 silc_buffer_free(packet);
1962 silc_buffer_free(idp);
1964 if (status == SILC_STATUS_LIST_END)
1970 /* Send error replies */
1972 if (status == SILC_STATUS_OK && errors_count > 1)
1973 status = SILC_STATUS_LIST_START;
1976 for (i = 0, k = 0; i < errors_count; i++) {
1978 idp = silc_id_payload_encode(errors[i].id, SILC_ID_CLIENT);
1982 tmp = silc_argument_get_arg_type(cmd->args, errors[i].index, &len);
1986 status = SILC_STATUS_LIST_ITEM;
1987 if (errors_count > 1 && k == errors_count - 1)
1988 status = SILC_STATUS_LIST_END;
1989 if (count && k - 1 == count)
1990 status = SILC_STATUS_LIST_END;
1993 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1994 (status == SILC_STATUS_OK ?
1995 errors[i].error : status),
1996 (status == SILC_STATUS_OK ?
1997 0 : errors[i].error),
1999 silc_buffer_free(idp);
2002 if (status == SILC_STATUS_LIST_END)
2010 silc_server_command_identify_process(SilcServerCommandContext cmd)
2012 SilcUInt32 count = 0;
2014 SilcClientEntry *clients = NULL;
2015 SilcServerEntry *servers = NULL;
2016 SilcChannelEntry *channels = NULL;
2017 SilcUInt32 clients_count = 0, servers_count = 0, channels_count = 0;
2018 SilcUInt32 errors_count = 0;
2019 ResolveError errors = NULL;
2021 /* Parse the IDENTIFY request */
2022 ret = silc_server_command_identify_parse(cmd,
2023 &clients, &clients_count,
2024 &servers, &servers_count,
2025 &channels, &channels_count,
2026 &count, &errors, &errors_count);
2031 /* Check that all mandatory fields are present and request those data
2032 from the server who owns the client if necessary. */
2033 if (!silc_server_command_identify_check_client(cmd, clients,
2039 /* Send the command reply to the client */
2040 silc_server_command_identify_send_reply(cmd,
2041 clients, clients_count,
2042 servers, servers_count,
2043 channels, channels_count,
2044 errors, errors_count,
2050 silc_free(channels);
2055 SILC_SERVER_CMD_FUNC(identify)
2057 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2060 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
2062 ret = silc_server_command_identify_process(cmd);
2063 silc_server_command_free(cmd);
2066 /* Server side of command NICK. Sets nickname for user. Setting
2067 nickname causes generation of a new client ID for the client. The
2068 new client ID is sent to the client after changing the nickname. */
2070 SILC_SERVER_CMD_FUNC(nick)
2072 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2073 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2074 SilcServer server = cmd->server;
2075 SilcBuffer packet, nidp, oidp = NULL;
2076 SilcClientID *new_id;
2077 SilcUInt32 nick_len;
2079 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2082 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2085 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
2087 /* Check nickname */
2088 nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
2091 if (silc_server_name_bad_chars(nick, nick_len) == TRUE) {
2092 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2093 SILC_STATUS_ERR_BAD_NICKNAME, 0);
2097 /* Check for same nickname */
2098 if (!strcmp(client->nickname, nick)) {
2099 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2103 /* Create new Client ID */
2104 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
2106 cmd->server->md5hash, nick,
2110 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2111 SILC_STATUS_ERR_BAD_NICKNAME, 0);
2114 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2117 /* Send notify about nickname change to our router. We send the new
2118 ID and ask to replace it with the old one. If we are router the
2119 packet is broadcasted. Send NICK_CHANGE notify. */
2120 if (!server->standalone)
2121 silc_server_send_notify_nick_change(server, server->router->connection,
2122 server->server_type == SILC_SERVER ?
2123 FALSE : TRUE, client->id,
2126 /* Check if anyone is watching the old nickname */
2127 if (server->server_type == SILC_ROUTER)
2128 silc_server_check_watcher_list(server, client, nick,
2129 SILC_NOTIFY_TYPE_NICK_CHANGE);
2131 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2133 /* Remove old cache entry */
2134 silc_idcache_del_by_context(server->local_list->clients, client);
2136 silc_free(client->id);
2137 client->id = new_id;
2139 silc_free(client->nickname);
2140 client->nickname = strdup(nick);
2142 /* Update client cache */
2143 silc_idcache_add(server->local_list->clients, client->nickname,
2144 client->id, (void *)client, 0, NULL);
2146 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2148 /* Send NICK_CHANGE notify to the client's channels */
2149 silc_server_send_notify_on_channels(server, NULL, client,
2150 SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
2151 oidp->data, oidp->len,
2152 nidp->data, nidp->len,
2154 strlen(client->nickname));
2156 /* Check if anyone is watching the new nickname */
2157 if (server->server_type == SILC_ROUTER)
2158 silc_server_check_watcher_list(server, client, NULL,
2159 SILC_NOTIFY_TYPE_NICK_CHANGE);
2162 /* Send the new Client ID as reply command back to client */
2163 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
2164 SILC_STATUS_OK, 0, ident, 2,
2165 2, nidp->data, nidp->len,
2166 3, nick, strlen(nick));
2167 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2168 0, packet->data, packet->len, FALSE);
2170 silc_buffer_free(packet);
2171 silc_buffer_free(nidp);
2173 silc_buffer_free(oidp);
2176 silc_server_command_free(cmd);
2179 /* Sends the LIST command reply */
2182 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2183 SilcChannelEntry *lch,
2184 SilcUInt32 lch_count,
2185 SilcChannelEntry *gch,
2186 SilcUInt32 gch_count)
2189 SilcBuffer packet, idp;
2190 SilcChannelEntry entry;
2192 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2194 unsigned char usercount[4];
2196 int valid_lcount = 0, valid_rcount = 0;
2198 for (i = 0; i < lch_count; i++) {
2199 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2204 for (i = 0; i < gch_count; i++) {
2205 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2211 status = SILC_STATUS_OK;
2212 if ((lch_count + gch_count) > 1)
2213 status = SILC_STATUS_LIST_START;
2216 for (i = 0, k = 0; i < lch_count; i++) {
2222 status = SILC_STATUS_LIST_ITEM;
2223 if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
2224 status = SILC_STATUS_LIST_END;
2226 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2228 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2229 topic = "*private*";
2230 memset(usercount, 0, sizeof(usercount));
2232 topic = entry->topic;
2233 users = silc_hash_table_count(entry->user_list);
2234 SILC_PUT32_MSB(users, usercount);
2237 /* Send the reply */
2239 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2240 status, 0, ident, 4,
2241 2, idp->data, idp->len,
2242 3, entry->channel_name,
2243 strlen(entry->channel_name),
2244 4, topic, topic ? strlen(topic) : 0,
2246 silc_server_packet_send(cmd->server, cmd->sock,
2247 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2248 packet->len, FALSE);
2249 silc_buffer_free(packet);
2250 silc_buffer_free(idp);
2255 for (i = 0, k = 0; i < gch_count; i++) {
2261 status = SILC_STATUS_LIST_ITEM;
2262 if (valid_rcount > 1 && k == valid_rcount - 1)
2263 status = SILC_STATUS_LIST_END;
2265 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2267 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2268 topic = "*private*";
2269 memset(usercount, 0, sizeof(usercount));
2271 topic = entry->topic;
2272 users = entry->user_count;
2273 SILC_PUT32_MSB(users, usercount);
2276 /* Send the reply */
2278 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2279 status, 0, ident, 4,
2280 2, idp->data, idp->len,
2281 3, entry->channel_name,
2282 strlen(entry->channel_name),
2283 4, topic, topic ? strlen(topic) : 0,
2285 silc_server_packet_send(cmd->server, cmd->sock,
2286 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2287 packet->len, FALSE);
2288 silc_buffer_free(packet);
2289 silc_buffer_free(idp);
2294 /* Server side of LIST command. This lists the channel of the requested
2295 server. Secret channels are not listed. */
2297 SILC_SERVER_CMD_FUNC(list)
2299 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2300 SilcServer server = cmd->server;
2301 SilcChannelID *channel_id = NULL;
2304 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2305 SilcUInt32 lch_count = 0, gch_count = 0;
2307 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2309 /* If we are normal server, send the command to router, since we
2310 want to know all channels in the network. */
2311 if (!cmd->pending && server->server_type == SILC_SERVER &&
2312 !server->standalone) {
2314 SilcUInt16 old_ident;
2316 old_ident = silc_command_get_ident(cmd->payload);
2317 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2318 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2319 silc_server_packet_send(server, server->router->connection,
2320 SILC_PACKET_COMMAND, cmd->packet->flags,
2321 tmpbuf->data, tmpbuf->len, TRUE);
2323 /* Reprocess this packet after received reply from router */
2324 silc_server_command_pending(server, SILC_COMMAND_LIST,
2325 silc_command_get_ident(cmd->payload),
2326 silc_server_command_list,
2327 silc_server_command_dup(cmd));
2328 cmd->pending = TRUE;
2329 silc_command_set_ident(cmd->payload, old_ident);
2330 silc_buffer_free(tmpbuf);
2334 /* Get Channel ID */
2335 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2337 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2339 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2340 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2345 /* Get the channels from local list */
2346 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2349 /* Get the channels from global list */
2350 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2353 /* Send the reply */
2354 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2355 gchannels, gch_count);
2357 silc_free(lchannels);
2358 silc_free(gchannels);
2361 silc_server_command_free(cmd);
2364 /* Server side of TOPIC command. Sets topic for channel and/or returns
2365 current topic to client. */
2367 SILC_SERVER_CMD_FUNC(topic)
2369 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2370 SilcServer server = cmd->server;
2371 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2372 SilcChannelID *channel_id;
2373 SilcChannelEntry channel;
2374 SilcChannelClientEntry chl;
2375 SilcBuffer packet, idp;
2377 SilcUInt32 argc, tmp_len;
2378 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2380 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2382 argc = silc_argument_get_arg_num(cmd->args);
2384 /* Get Channel ID */
2385 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2387 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2388 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2391 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2393 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2394 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2398 /* Check whether the channel exists */
2399 channel = silc_idlist_find_channel_by_id(server->local_list,
2402 channel = silc_idlist_find_channel_by_id(server->global_list,
2405 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2406 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
2414 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2416 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2417 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2422 if (strlen(tmp) > 256) {
2423 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2424 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2429 /* See whether the client is on channel and has rights to change topic */
2430 if (!silc_server_client_on_channel(client, channel, &chl)) {
2431 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2432 SILC_STATUS_ERR_NOT_ON_CHANNEL,
2437 if (channel->mode & SILC_CHANNEL_MODE_TOPIC &&
2438 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
2439 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
2440 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2441 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
2446 /* Set the topic for channel */
2447 silc_free(channel->topic);
2448 channel->topic = strdup(tmp);
2450 /* Send TOPIC_SET notify type to the network */
2451 if (!server->standalone)
2452 silc_server_send_notify_topic_set(server, server->router->connection,
2453 server->server_type == SILC_ROUTER ?
2454 TRUE : FALSE, channel,
2455 client->id, SILC_ID_CLIENT,
2458 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2460 /* Send notify about topic change to all clients on the channel */
2461 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2462 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2463 idp->data, idp->len,
2464 channel->topic, strlen(channel->topic));
2465 silc_buffer_free(idp);
2468 /* Send the topic to client as reply packet */
2469 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2470 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2471 SILC_STATUS_OK, 0, ident, 2,
2472 2, idp->data, idp->len,
2475 strlen(channel->topic) : 0);
2476 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2477 0, packet->data, packet->len, FALSE);
2479 silc_buffer_free(packet);
2480 silc_buffer_free(idp);
2481 silc_free(channel_id);
2484 silc_server_command_free(cmd);
2487 /* Server side of INVITE command. Invites some client to join some channel.
2488 This command is also used to manage the invite list of the channel. */
2490 SILC_SERVER_CMD_FUNC(invite)
2492 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2493 SilcServer server = cmd->server;
2494 SilcSocketConnection sock = cmd->sock, dest_sock;
2495 SilcChannelClientEntry chl;
2496 SilcClientEntry sender, dest;
2497 SilcClientID *dest_id = NULL;
2498 SilcChannelEntry channel;
2499 SilcChannelID *channel_id = NULL;
2500 SilcIDListData idata;
2501 SilcBuffer idp, idp2, packet;
2502 unsigned char *tmp, *add, *del;
2504 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2506 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2508 /* Get Channel ID */
2509 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2511 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2512 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2515 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
2517 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2518 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2522 /* Get the channel entry */
2523 channel = silc_idlist_find_channel_by_id(server->local_list,
2526 channel = silc_idlist_find_channel_by_id(server->global_list,
2529 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2530 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
2536 /* Check whether the sender of this command is on the channel. */
2537 sender = (SilcClientEntry)sock->user_data;
2538 if (!silc_server_client_on_channel(sender, channel, &chl)) {
2539 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2540 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
2544 /* Check whether the channel is invite-only channel. If yes then the
2545 sender of this command must be at least channel operator. */
2546 if (channel->mode & SILC_CHANNEL_MODE_INVITE &&
2547 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
2548 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
2549 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2550 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
2555 /* Get destination client ID */
2556 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2561 dest_id = silc_id_payload_parse_id(tmp, len, NULL);
2563 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2564 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
2568 /* Get the client entry */
2569 dest = silc_server_get_client_resolve(server, dest_id, FALSE, &resolve);
2571 if (server->server_type != SILC_SERVER || !resolve) {
2572 silc_server_command_send_status_reply(
2573 cmd, SILC_COMMAND_INVITE,
2574 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0);
2578 /* The client info is being resolved. Reprocess this packet after
2579 receiving the reply to the query. */
2580 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2582 silc_server_command_invite,
2583 silc_server_command_dup(cmd));
2584 cmd->pending = TRUE;
2585 silc_free(channel_id);
2590 /* Check whether the requested client is already on the channel. */
2591 if (silc_server_client_on_channel(dest, channel, NULL)) {
2592 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2593 SILC_STATUS_ERR_USER_ON_CHANNEL,
2598 /* Get route to the client */
2599 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id,
2602 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2603 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2608 memset(invite, 0, sizeof(invite));
2609 strncat(invite, dest->nickname, strlen(dest->nickname));
2610 strncat(invite, "!", 1);
2611 strncat(invite, dest->username, strlen(dest->username));
2612 if (!strchr(dest->username, '@')) {
2613 strncat(invite, "@", 1);
2614 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2617 len = strlen(invite);
2618 if (!channel->invite_list)
2619 channel->invite_list = silc_calloc(len + 2,
2620 sizeof(*channel->invite_list));
2622 channel->invite_list = silc_realloc(channel->invite_list,
2623 sizeof(*channel->invite_list) *
2625 strlen(channel->invite_list) + 2));
2626 strncat(channel->invite_list, invite, len);
2627 strncat(channel->invite_list, ",", 1);
2629 if (!(dest->mode & SILC_UMODE_BLOCK_INVITE)) {
2630 /* Send notify to the client that is invited to the channel */
2631 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2632 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2633 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2635 SILC_NOTIFY_TYPE_INVITE, 3,
2636 idp->data, idp->len,
2637 channel->channel_name,
2638 strlen(channel->channel_name),
2639 idp2->data, idp2->len);
2640 silc_buffer_free(idp);
2641 silc_buffer_free(idp2);
2645 /* Add the client to the invite list of the channel */
2646 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2648 if (!channel->invite_list)
2649 channel->invite_list = silc_calloc(len + 2,
2650 sizeof(*channel->invite_list));
2652 channel->invite_list = silc_realloc(channel->invite_list,
2653 sizeof(*channel->invite_list) *
2655 strlen(channel->invite_list) + 2));
2656 if (add[len - 1] == ',')
2657 add[len - 1] = '\0';
2659 strncat(channel->invite_list, add, len);
2660 strncat(channel->invite_list, ",", 1);
2663 /* Get the invite to be removed and remove it from the list */
2664 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2665 if (del && channel->invite_list) {
2666 char *start, *end, *n;
2668 if (!strncmp(channel->invite_list, del,
2669 strlen(channel->invite_list) - 1)) {
2670 silc_free(channel->invite_list);
2671 channel->invite_list = NULL;
2673 start = strstr(channel->invite_list, del);
2674 if (start && strlen(start) >= len) {
2676 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2677 strncat(n, channel->invite_list, start - channel->invite_list);
2678 strncat(n, end + 1, ((channel->invite_list +
2679 strlen(channel->invite_list)) - end) - 1);
2680 silc_free(channel->invite_list);
2681 channel->invite_list = n;
2686 /* Send notify to the primary router */
2687 if (!server->standalone)
2688 silc_server_send_notify_invite(server, server->router->connection,
2689 server->server_type == SILC_ROUTER ?
2690 TRUE : FALSE, channel,
2691 sender->id, add, del);
2693 /* Send command reply */
2694 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2698 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2699 SILC_STATUS_OK, 0, ident, 2,
2701 3, channel->invite_list,
2702 channel->invite_list ?
2703 strlen(channel->invite_list) : 0);
2706 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2707 SILC_STATUS_OK, 0, ident, 1,
2709 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2710 packet->data, packet->len, FALSE);
2711 silc_buffer_free(packet);
2715 silc_free(channel_id);
2716 silc_server_command_free(cmd);
2721 SilcSocketConnection sock;
2725 /* Quits connection to client. This gets called if client won't
2726 close the connection even when it has issued QUIT command. */
2728 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2730 QuitInternal q = (QuitInternal)context;
2732 /* Free all client specific data, such as client entry and entires
2733 on channels this client may be on. */
2734 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2736 q->sock->user_data = NULL;
2738 /* Close the connection on our side */
2739 silc_server_close_connection(q->server, q->sock);
2741 silc_free(q->signoff);
2745 /* Quits SILC session. This is the normal way to disconnect client. */
2747 SILC_SERVER_CMD_FUNC(quit)
2749 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2750 SilcServer server = cmd->server;
2751 SilcSocketConnection sock = cmd->sock;
2753 unsigned char *tmp = NULL;
2756 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2758 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2762 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2766 q = silc_calloc(1, sizeof(*q));
2769 q->signoff = tmp ? strdup(tmp) : NULL;
2771 /* We quit the connection with little timeout */
2772 silc_schedule_task_add(server->schedule, sock->sock,
2773 silc_server_command_quit_cb, (void *)q,
2774 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2777 silc_server_command_free(cmd);
2780 /* Server side of command KILL. This command is used by router operator
2781 to remove an client from the SILC Network temporarily. */
2783 SILC_SERVER_CMD_FUNC(kill)
2785 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2786 SilcServer server = cmd->server;
2787 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2788 SilcClientEntry remote_client;
2789 SilcClientID *client_id;
2790 unsigned char *tmp, *comment;
2791 SilcUInt32 tmp_len, tmp_len2;
2794 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2796 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2799 /* KILL command works only on router */
2800 if (server->server_type != SILC_ROUTER) {
2801 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2802 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
2806 /* Check whether client has the permissions. */
2807 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2808 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2809 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
2813 /* Get the client ID */
2814 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2816 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2817 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2821 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2823 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2824 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2829 /* Get the client entry */
2830 remote_client = silc_idlist_find_client_by_id(server->local_list,
2831 client_id, TRUE, NULL);
2833 if (!remote_client) {
2834 remote_client = silc_idlist_find_client_by_id(server->global_list,
2835 client_id, TRUE, NULL);
2837 if (!remote_client) {
2838 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2839 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2846 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2850 /* Send reply to the sender */
2851 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2854 /* Check if anyone is watching this nickname */
2855 if (server->server_type == SILC_ROUTER)
2856 silc_server_check_watcher_list(server, client, NULL,
2857 SILC_NOTIFY_TYPE_KILLED);
2859 /* Now do the killing */
2860 silc_server_kill_client(server, remote_client, comment, client->id,
2864 silc_server_command_free(cmd);
2867 /* Server side of command INFO. This sends information about us to
2868 the client. If client requested specific server we will send the
2869 command to that server. */
2871 SILC_SERVER_CMD_FUNC(info)
2873 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2874 SilcServer server = cmd->server;
2875 SilcBuffer packet, idp;
2878 char *dest_server, *server_info = NULL, *server_name;
2879 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2880 SilcServerEntry entry = NULL;
2881 SilcServerID *server_id = NULL;
2883 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2885 /* Get server name */
2886 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2889 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2891 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2893 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2894 SILC_STATUS_ERR_NO_SERVER_ID, 0);
2900 /* Check whether we have this server cached */
2901 entry = silc_idlist_find_server_by_id(server->local_list,
2902 server_id, TRUE, NULL);
2904 entry = silc_idlist_find_server_by_id(server->global_list,
2905 server_id, TRUE, NULL);
2906 if (!entry && server->server_type != SILC_SERVER) {
2907 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2908 SILC_STATUS_ERR_NO_SUCH_SERVER,
2915 /* Some buggy servers has sent request to router about themselves. */
2916 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2919 if ((!dest_server && !server_id && !entry) || (entry &&
2920 entry == server->id_entry) ||
2921 (dest_server && !cmd->pending &&
2922 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2923 /* Send our reply */
2924 char info_string[256];
2926 memset(info_string, 0, sizeof(info_string));
2927 snprintf(info_string, sizeof(info_string),
2928 "location: %s server: %s admin: %s <%s>",
2929 server->config->server_info->location,
2930 server->config->server_info->server_type,
2931 server->config->server_info->admin,
2932 server->config->server_info->email);
2934 server_info = info_string;
2935 entry = server->id_entry;
2937 /* Check whether we have this server cached */
2938 if (!entry && dest_server) {
2939 entry = silc_idlist_find_server_by_name(server->global_list,
2940 dest_server, TRUE, NULL);
2942 entry = silc_idlist_find_server_by_name(server->local_list,
2943 dest_server, TRUE, NULL);
2947 if (!cmd->pending &&
2948 server->server_type != SILC_SERVER && entry && !entry->server_info) {
2949 /* Send to the server */
2951 SilcUInt16 old_ident;
2953 old_ident = silc_command_get_ident(cmd->payload);
2954 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2955 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2957 silc_server_packet_send(server, entry->connection,
2958 SILC_PACKET_COMMAND, cmd->packet->flags,
2959 tmpbuf->data, tmpbuf->len, TRUE);
2961 /* Reprocess this packet after received reply from router */
2962 silc_server_command_pending(server, SILC_COMMAND_INFO,
2963 silc_command_get_ident(cmd->payload),
2964 silc_server_command_info,
2965 silc_server_command_dup(cmd));
2966 cmd->pending = TRUE;
2967 silc_command_set_ident(cmd->payload, old_ident);
2968 silc_buffer_free(tmpbuf);
2972 if (!entry && !cmd->pending && !server->standalone) {
2973 /* Send to the primary router */
2975 SilcUInt16 old_ident;
2977 old_ident = silc_command_get_ident(cmd->payload);
2978 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2979 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2981 silc_server_packet_send(server, server->router->connection,
2982 SILC_PACKET_COMMAND, cmd->packet->flags,
2983 tmpbuf->data, tmpbuf->len, TRUE);
2985 /* Reprocess this packet after received reply from router */
2986 silc_server_command_pending(server, SILC_COMMAND_INFO,
2987 silc_command_get_ident(cmd->payload),
2988 silc_server_command_info,
2989 silc_server_command_dup(cmd));
2990 cmd->pending = TRUE;
2991 silc_command_set_ident(cmd->payload, old_ident);
2992 silc_buffer_free(tmpbuf);
2997 silc_free(server_id);
3000 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3001 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3005 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
3007 server_info = entry->server_info;
3008 server_name = entry->server_name;
3010 /* Send the reply */
3011 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
3012 SILC_STATUS_OK, 0, ident, 3,
3013 2, idp->data, idp->len,
3015 strlen(server_name),
3018 strlen(server_info) : 0);
3019 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3020 packet->data, packet->len, FALSE);
3022 silc_buffer_free(packet);
3023 silc_buffer_free(idp);
3026 silc_server_command_free(cmd);
3029 /* Server side of command PING. This just replies to the ping. */
3031 SILC_SERVER_CMD_FUNC(ping)
3033 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3034 SilcServer server = cmd->server;
3039 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
3042 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
3044 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3045 SILC_STATUS_ERR_NO_SERVER_ID, 0);
3048 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
3052 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
3053 /* Send our reply */
3054 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3057 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3058 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3065 silc_server_command_free(cmd);
3068 /* Server side of command STATS. */
3070 SILC_SERVER_CMD_FUNC(stats)
3072 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3073 SilcServer server = cmd->server;
3074 SilcServerID *server_id;
3077 SilcBuffer packet, stats;
3078 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3081 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1);
3084 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3086 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3087 SILC_STATUS_ERR_NO_SERVER_ID, 0);
3090 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3094 /* The ID must be ours */
3095 if (!SILC_ID_SERVER_COMPARE(server->id, server_id)) {
3096 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3097 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3098 silc_free(server_id);
3101 silc_free(server_id);
3103 /* If we are router then just send everything we got. If we are normal
3104 server then we'll send this to our router to get all the latest
3105 statistical information. */
3106 if (!cmd->pending && server->server_type != SILC_ROUTER &&
3107 !server->standalone) {
3108 /* Send request to our router */
3109 SilcBuffer idp = silc_id_payload_encode(server->router->id,
3111 packet = silc_command_payload_encode_va(SILC_COMMAND_STATS,
3112 ++server->cmd_ident, 1,
3113 1, idp->data, idp->len);
3114 silc_server_packet_send(server, server->router->connection,
3115 SILC_PACKET_COMMAND, 0, packet->data,
3116 packet->len, FALSE);
3118 /* Reprocess this packet after received reply from router */
3119 silc_server_command_pending(server, SILC_COMMAND_STATS,
3121 silc_server_command_stats,
3122 silc_server_command_dup(cmd));
3123 cmd->pending = TRUE;
3124 silc_buffer_free(packet);
3125 silc_buffer_free(idp);
3129 /* Send our reply to sender */
3130 uptime = time(NULL) - server->starttime;
3132 stats = silc_buffer_alloc_size(60);
3133 silc_buffer_format(stats,
3134 SILC_STR_UI_INT(server->starttime),
3135 SILC_STR_UI_INT(uptime),
3136 SILC_STR_UI_INT(server->stat.my_clients),
3137 SILC_STR_UI_INT(server->stat.my_channels),
3138 SILC_STR_UI_INT(server->stat.my_server_ops),
3139 SILC_STR_UI_INT(server->stat.my_router_ops),
3140 SILC_STR_UI_INT(server->stat.cell_clients),
3141 SILC_STR_UI_INT(server->stat.cell_channels),
3142 SILC_STR_UI_INT(server->stat.cell_servers),
3143 SILC_STR_UI_INT(server->stat.clients),
3144 SILC_STR_UI_INT(server->stat.channels),
3145 SILC_STR_UI_INT(server->stat.servers),
3146 SILC_STR_UI_INT(server->stat.routers),
3147 SILC_STR_UI_INT(server->stat.server_ops),
3148 SILC_STR_UI_INT(server->stat.router_ops),
3151 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_STATS,
3152 SILC_STATUS_OK, 0, ident, 2,
3154 3, stats->data, stats->len);
3155 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
3156 0, packet->data, packet->len, FALSE);
3157 silc_buffer_free(packet);
3158 silc_buffer_free(stats);
3161 silc_server_command_free(cmd);
3164 /* Internal routine to join channel. The channel sent to this function
3165 has been either created or resolved from ID lists. This joins the sent
3166 client to the channel. */
3168 static void silc_server_command_join_channel(SilcServer server,
3169 SilcServerCommandContext cmd,
3170 SilcChannelEntry channel,
3171 SilcClientID *client_id,
3175 const unsigned char *auth,
3176 SilcUInt32 auth_len)
3178 SilcSocketConnection sock = cmd->sock;
3180 SilcUInt32 tmp_len, user_count;
3181 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
3182 SilcClientEntry client;
3183 SilcChannelClientEntry chl;
3184 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
3185 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3186 char check[512], check2[512];
3187 bool founder = FALSE;
3189 unsigned char *fkey = NULL;
3190 SilcUInt32 fkey_len = 0;
3192 SILC_LOG_DEBUG(("Joining client to channel"));
3197 /* Get the client entry */
3198 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3199 client = (SilcClientEntry)sock->user_data;
3201 client = silc_server_get_client_resolve(server, client_id, FALSE,
3208 silc_server_command_send_status_reply(
3209 cmd, SILC_COMMAND_JOIN,
3210 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3214 /* The client info is being resolved. Reprocess this packet after
3215 receiving the reply to the query. */
3216 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
3218 silc_server_command_join,
3219 silc_server_command_dup(cmd));
3220 cmd->pending = TRUE;
3224 cmd->pending = FALSE;
3228 * Check founder auth payload if provided. If client can gain founder
3229 * privileges it can override various conditions on joining the channel,
3230 * and can have directly the founder mode set on the channel.
3232 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3233 SilcIDListData idata = (SilcIDListData)client;
3234 SilcChannelClientEntry chl2;
3235 SilcHashTableList htl;
3237 if (channel->founder_key && idata->public_key &&
3238 silc_pkcs_public_key_compare(channel->founder_key,
3239 idata->public_key)) {
3240 /* Check whether the client is to become founder */
3241 if (silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
3242 channel->founder_key, 0, server->sha1hash,
3243 client->id, SILC_ID_CLIENT)) {
3245 /* There cannot be anyone else as founder on the channel now. This
3246 client is definitely the founder due to this authentication */
3247 silc_hash_table_list(channel->user_list, &htl);
3248 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
3249 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
3250 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3251 silc_server_force_cumode_change(server, NULL, channel, chl2,
3255 silc_hash_table_list_reset(&htl);
3257 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3264 * Check channel modes
3268 memset(check, 0, sizeof(check));
3269 memset(check2, 0, sizeof(check2));
3270 strncat(check, client->nickname, strlen(client->nickname));
3271 strncat(check, "!", 1);
3272 strncat(check, client->username, strlen(client->username));
3273 if (!strchr(client->username, '@')) {
3274 strncat(check, "@", 1);
3275 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3278 strncat(check2, client->nickname, strlen(client->nickname));
3279 if (!strchr(client->nickname, '@')) {
3280 strncat(check2, "@", 1);
3281 strncat(check2, server->server_name, strlen(server->server_name));
3283 strncat(check2, "!", 1);
3284 strncat(check2, client->username, strlen(client->username));
3285 if (!strchr(client->username, '@')) {
3286 strncat(check2, "@", 1);
3287 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3290 /* Check invite list if channel is invite-only channel */
3291 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3292 if (!channel->invite_list ||
3293 (!silc_string_match(channel->invite_list, check) &&
3294 !silc_string_match(channel->invite_list, check2))) {
3295 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3296 SILC_STATUS_ERR_NOT_INVITED, 0);
3301 /* Check ban list if it exists. If the client's nickname, server,
3302 username and/or hostname is in the ban list the access to the
3303 channel is denied. */
3304 if (channel->ban_list) {
3305 if (silc_string_match(channel->ban_list, check) ||
3306 silc_string_match(channel->ban_list, check2)) {
3307 silc_server_command_send_status_reply(
3308 cmd, SILC_COMMAND_JOIN,
3309 SILC_STATUS_ERR_BANNED_FROM_CHANNEL, 0);
3314 /* Check user count limit if set. */
3315 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3316 if (silc_hash_table_count(channel->user_list) + 1 >
3317 channel->user_limit) {
3318 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3319 SILC_STATUS_ERR_CHANNEL_IS_FULL,
3326 /* Check the channel passphrase if set. */
3327 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3328 /* Get passphrase */
3329 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3331 passphrase = silc_memdup(tmp, tmp_len);
3333 if (!passphrase || !channel->passphrase ||
3334 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3335 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3336 SILC_STATUS_ERR_BAD_PASSWORD, 0);
3342 * Client is allowed to join to the channel. Make it happen.
3345 /* Check whether the client already is on the channel */
3346 if (silc_server_client_on_channel(client, channel, NULL)) {
3347 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3348 SILC_STATUS_ERR_USER_ON_CHANNEL, 0);
3352 /* Generate new channel key as protocol dictates */
3354 if (!silc_server_create_channel_key(server, channel, 0))
3357 /* Send the channel key. This is broadcasted to the channel but is not
3358 sent to the client who is joining to the channel. */
3359 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3360 silc_server_send_channel_key(server, NULL, channel,
3361 server->server_type == SILC_ROUTER ?
3362 FALSE : !server->standalone);
3365 /* Join the client to the channel by adding it to channel's user list.
3366 Add also the channel to client entry's channels list for fast cross-
3368 chl = silc_calloc(1, sizeof(*chl));
3370 chl->client = client;
3371 chl->channel = channel;
3372 silc_hash_table_add(channel->user_list, client, chl);
3373 silc_hash_table_add(client->channels, channel, chl);
3374 channel->user_count++;
3375 channel->disabled = FALSE;
3377 /* Get users on the channel */
3378 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3381 /* Encode Client ID Payload of the original client who wants to join */
3382 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3384 /* Encode command reply packet */
3385 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3386 SILC_PUT32_MSB(channel->mode, mode);
3387 SILC_PUT32_MSB(created, tmp2);
3388 SILC_PUT32_MSB(user_count, tmp3);
3390 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3391 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3392 keyp = silc_channel_key_payload_encode(silc_id_get_len(channel->id,
3395 strlen(channel->channel_key->
3397 channel->channel_key->cipher->name,
3398 channel->key_len / 8, channel->key);
3402 if (channel->founder_key)
3403 fkey = silc_pkcs_public_key_encode(channel->founder_key, &fkey_len);
3406 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3407 SILC_STATUS_OK, 0, ident, 14,
3408 2, channel->channel_name,
3409 strlen(channel->channel_name),
3410 3, chidp->data, chidp->len,
3411 4, clidp->data, clidp->len,
3414 7, keyp ? keyp->data : NULL,
3415 keyp ? keyp->len : 0,
3416 8, channel->ban_list,
3418 strlen(channel->ban_list) : 0,
3419 9, channel->invite_list,
3420 channel->invite_list ?
3421 strlen(channel->invite_list) : 0,
3424 strlen(channel->topic) : 0,
3425 11, silc_hmac_get_name(channel->hmac),
3426 strlen(silc_hmac_get_name(channel->
3429 13, user_list->data, user_list->len,
3430 14, mode_list->data,
3432 15, fkey, fkey_len);
3434 /* Send command reply */
3435 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3436 reply->data, reply->len, FALSE);
3438 /* Send JOIN notify to locally connected clients on the channel. If
3439 we are normal server then router will send or have sent JOIN notify
3440 already. However since we've added the client already to our channel
3441 we'll ignore it (in packet_receive.c) so we must send it here. If
3442 we are router then this will send it to local clients and local
3444 SILC_LOG_DEBUG(("Send JOIN notify to channel"));
3445 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3446 SILC_NOTIFY_TYPE_JOIN, 2,
3447 clidp->data, clidp->len,
3448 chidp->data, chidp->len);
3450 /* Update statistics */
3451 server->stat.my_chanclients++;
3452 if (server->server_type == SILC_ROUTER) {
3453 server->stat.cell_chanclients++;
3454 server->stat.chanclients++;
3457 if (!cmd->pending) {
3458 /* Send JOIN notify packet to our primary router */
3459 if (!server->standalone)
3460 silc_server_send_notify_join(server, server->router->connection,
3461 server->server_type == SILC_ROUTER ?
3462 TRUE : FALSE, channel, client->id);
3465 /* Distribute the channel key to all backup routers. */
3466 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3467 keyp->data, keyp->len, FALSE, TRUE);
3469 /* If client became founder by providing correct founder auth data
3470 notify the mode change to the channel. */
3472 SILC_PUT32_MSB(chl->mode, mode);
3473 SILC_LOG_DEBUG(("Send CUMODE_CHANGE notify to channel"));
3474 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3475 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
3476 clidp->data, clidp->len,
3477 mode, 4, clidp->data, clidp->len,
3482 /* Set CUMODE notify type to network */
3483 if (founder && !server->standalone)
3484 silc_server_send_notify_cumode(server, server->router->connection,
3485 server->server_type == SILC_ROUTER ?
3486 TRUE : FALSE, channel,
3487 chl->mode, client->id, SILC_ID_CLIENT,
3488 client->id, channel->founder_key);
3490 silc_buffer_free(reply);
3491 silc_buffer_free(clidp);
3492 silc_buffer_free(chidp);
3493 silc_buffer_free(keyp);
3494 silc_buffer_free(user_list);
3495 silc_buffer_free(mode_list);
3499 silc_free(passphrase);
3502 /* Server side of command JOIN. Joins client into requested channel. If
3503 the channel does not exist it will be created. */
3505 SILC_SERVER_CMD_FUNC(join)
3507 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3508 SilcServer server = cmd->server;
3509 unsigned char *auth;
3510 SilcUInt32 tmp_len, auth_len;
3511 char *tmp, *channel_name = NULL, *cipher, *hmac;
3512 SilcChannelEntry channel;
3513 SilcUInt32 umode = 0;
3514 bool created = FALSE, create_key = TRUE;
3515 SilcClientID *client_id;
3517 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3519 /* Get channel name */
3520 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3522 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3523 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3530 channel_name[255] = '\0';
3532 if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
3533 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3534 SILC_STATUS_ERR_BAD_CHANNEL, 0);
3538 /* Get Client ID of the client who is joining to the channel */
3539 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3541 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3542 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3546 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3548 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3549 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3554 /* Get cipher, hmac name and auth payload */
3555 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3556 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3557 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3559 /* See if the channel exists */
3560 channel = silc_idlist_find_channel_by_name(server->local_list,
3561 channel_name, NULL);
3563 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3564 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3565 silc_free(client_id);
3566 client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
3569 (channel->disabled && server->server_type != SILC_ROUTER)) {
3570 /* Channel not found */
3572 /* If we are standalone server we don't have a router, we just create
3573 the channel by ourselves. */
3574 if (server->standalone) {
3575 channel = silc_server_create_new_channel(server, server->id, cipher,
3576 hmac, channel_name, TRUE);
3578 silc_server_command_send_status_reply(
3579 cmd, SILC_COMMAND_JOIN,
3580 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
3582 silc_free(client_id);
3586 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3592 /* The channel does not exist on our server. If we are normal server
3593 we will send JOIN command to our router which will handle the
3594 joining procedure (either creates the channel if it doesn't exist
3595 or joins the client to it). */
3596 if (server->server_type != SILC_ROUTER) {
3598 SilcUInt16 old_ident;
3600 /* If this is pending command callback then we've resolved
3601 it and it didn't work, return since we've notified the
3602 client already in the command reply callback. */
3604 silc_free(client_id);
3608 old_ident = silc_command_get_ident(cmd->payload);
3609 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3610 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3612 /* Send JOIN command to our router */
3613 silc_server_packet_send(server, (SilcSocketConnection)
3614 server->router->connection,
3615 SILC_PACKET_COMMAND, cmd->packet->flags,
3616 tmpbuf->data, tmpbuf->len, TRUE);
3618 /* Reprocess this packet after received reply from router */
3619 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3620 silc_command_get_ident(cmd->payload),
3621 silc_server_command_join,
3622 silc_server_command_dup(cmd));
3623 cmd->pending = TRUE;
3624 silc_command_set_ident(cmd->payload, old_ident);
3625 silc_buffer_free(tmpbuf);
3626 silc_free(client_id);
3630 /* We are router and the channel does not seem exist so we will check
3631 our global list as well for the channel. */
3632 channel = silc_idlist_find_channel_by_name(server->global_list,
3633 channel_name, NULL);
3635 /* Channel really does not exist, create it */
3636 channel = silc_server_create_new_channel(server, server->id, cipher,
3637 hmac, channel_name, TRUE);
3639 silc_server_command_send_status_reply(
3640 cmd, SILC_COMMAND_JOIN,
3641 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
3642 silc_free(client_id);
3646 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3654 /* Channel not found */
3656 /* If the command came from router and we are normal server then
3657 something went wrong with the joining as the channel was not found.
3658 We can't do anything else but ignore this. */
3659 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3660 server->server_type != SILC_ROUTER) {
3661 silc_free(client_id);
3665 /* We are router and the channel does not seem exist so we will check
3666 our global list as well for the channel. */
3667 channel = silc_idlist_find_channel_by_name(server->global_list,
3668 channel_name, NULL);
3670 /* Channel really does not exist, create it */
3671 channel = silc_server_create_new_channel(server, server->id, cipher,
3672 hmac, channel_name, TRUE);
3674 silc_server_command_send_status_reply(
3675 cmd, SILC_COMMAND_JOIN,
3676 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
3677 silc_free(client_id);
3681 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3688 /* Check whether the channel was created by our router */
3689 if (cmd->pending && context2) {
3690 SilcServerCommandReplyContext reply = context2;
3692 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3693 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3694 SILC_GET32_MSB(created, tmp);
3695 if (silc_argument_get_arg_type(reply->args, 7, NULL))
3696 create_key = FALSE; /* Router returned the key already */
3698 if (silc_command_get_status(reply->payload, NULL, NULL) &&
3699 channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3700 /* Save channel passphrase, if user provided it successfully */
3703 pa = silc_argument_get_arg_type(reply->args, 3, &pa_len);
3705 silc_free(channel->passphrase);
3706 channel->passphrase = silc_memdup(pa, pa_len);
3711 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
3712 !channel->disabled && !silc_hash_table_count(channel->user_list))
3716 /* If the channel does not have global users and is also empty the client
3717 will be the channel founder and operator. */
3718 if (!channel->disabled &&
3719 !channel->global_users && !silc_hash_table_count(channel->user_list))
3720 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3722 /* Join to the channel */
3723 silc_server_command_join_channel(server, cmd, channel, client_id,
3724 created, create_key, umode,
3727 silc_free(client_id);
3730 silc_server_command_free(cmd);
3733 /* Server side of command MOTD. Sends server's current "message of the
3734 day" to the client. */
3736 SILC_SERVER_CMD_FUNC(motd)
3738 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3739 SilcServer server = cmd->server;
3740 SilcBuffer packet, idp;
3741 char *motd, *dest_server;
3742 SilcUInt32 motd_len;
3743 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3745 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3747 /* Get server name */
3748 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3750 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3751 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3755 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3758 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3760 if (server->config && server->config->server_info &&
3761 server->config->server_info->motd_file) {
3763 motd = silc_file_readfile(server->config->server_info->motd_file,
3769 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3776 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3782 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3783 packet->data, packet->len, FALSE);
3784 silc_buffer_free(packet);
3785 silc_buffer_free(idp);
3787 SilcServerEntry entry;
3789 /* Check whether we have this server cached */
3790 entry = silc_idlist_find_server_by_name(server->global_list,
3791 dest_server, TRUE, NULL);
3793 entry = silc_idlist_find_server_by_name(server->local_list,
3794 dest_server, TRUE, NULL);
3797 if (server->server_type != SILC_SERVER && !cmd->pending &&
3798 entry && !entry->motd) {
3799 /* Send to the server */
3801 SilcUInt16 old_ident;
3803 old_ident = silc_command_get_ident(cmd->payload);
3804 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3805 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3807 silc_server_packet_send(server, entry->connection,
3808 SILC_PACKET_COMMAND, cmd->packet->flags,
3809 tmpbuf->data, tmpbuf->len, TRUE);
3811 /* Reprocess this packet after received reply from router */
3812 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3813 silc_command_get_ident(cmd->payload),
3814 silc_server_command_motd,
3815 silc_server_command_dup(cmd));
3816 cmd->pending = TRUE;
3817 silc_command_set_ident(cmd->payload, old_ident);
3818 silc_buffer_free(tmpbuf);
3822 if (!entry && !cmd->pending && !server->standalone) {
3823 /* Send to the primary router */
3825 SilcUInt16 old_ident;
3827 old_ident = silc_command_get_ident(cmd->payload);
3828 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3829 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3831 silc_server_packet_send(server, server->router->connection,
3832 SILC_PACKET_COMMAND, cmd->packet->flags,
3833 tmpbuf->data, tmpbuf->len, TRUE);
3835 /* Reprocess this packet after received reply from router */
3836 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3837 silc_command_get_ident(cmd->payload),
3838 silc_server_command_motd,
3839 silc_server_command_dup(cmd));
3840 cmd->pending = TRUE;
3841 silc_command_set_ident(cmd->payload, old_ident);
3842 silc_buffer_free(tmpbuf);
3847 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3848 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3852 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3853 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3854 SILC_STATUS_OK, 0, ident, 2,
3858 strlen(entry->motd) : 0);
3859 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3860 packet->data, packet->len, FALSE);
3861 silc_buffer_free(packet);
3862 silc_buffer_free(idp);
3866 silc_server_command_free(cmd);
3869 /* Server side of command UMODE. Client can use this command to set/unset
3870 user mode. Client actually cannot set itself to be as server/router
3871 operator so this can be used only to unset the modes. */
3873 SILC_SERVER_CMD_FUNC(umode)
3875 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3876 SilcServer server = cmd->server;
3877 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3879 unsigned char *tmp_mask, m[4];
3880 SilcUInt32 mask = 0;
3881 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3882 bool set_mask = FALSE;
3884 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3887 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2);
3889 /* Get the client's mode mask */
3890 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3892 SILC_GET32_MSB(mask, tmp_mask);
3897 /* Check that mode changing is allowed. */
3898 if (!silc_server_check_umode_rights(server, client, mask)) {
3899 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3900 SILC_STATUS_ERR_PERM_DENIED, 0);
3904 /* Anonymous mode cannot be set by client */
3905 if (mask & SILC_UMODE_ANONYMOUS) {
3906 if (!(client->mode & SILC_UMODE_ANONYMOUS)) {
3907 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3908 SILC_STATUS_ERR_PERM_DENIED, 0);
3912 if (client->mode & SILC_UMODE_ANONYMOUS) {
3913 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3914 SILC_STATUS_ERR_PERM_DENIED, 0);
3919 /* Update statistics */
3920 if (mask & SILC_UMODE_GONE) {
3921 if (!(client->mode & SILC_UMODE_GONE))
3922 server->stat.my_aways++;
3924 if (client->mode & SILC_UMODE_GONE)
3925 server->stat.my_aways--;
3928 /* Change the mode */
3929 client->mode = mask;
3931 /* Send UMODE change to primary router */
3932 if (!server->standalone)
3933 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3934 client->id, client->mode);
3936 /* Check if anyone is watching this nickname */
3937 if (server->server_type == SILC_ROUTER)
3938 silc_server_check_watcher_list(server, client, NULL,
3939 SILC_NOTIFY_TYPE_UMODE_CHANGE);
3942 /* Send command reply to sender */
3943 SILC_PUT32_MSB(client->mode, m);
3944 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3945 SILC_STATUS_OK, 0, ident, 1,
3947 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3948 packet->data, packet->len, FALSE);
3949 silc_buffer_free(packet);
3952 silc_server_command_free(cmd);
3955 /* Server side command of CMODE. Changes channel mode */
3957 SILC_SERVER_CMD_FUNC(cmode)
3959 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3960 SilcServer server = cmd->server;
3961 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3962 SilcIDListData idata = (SilcIDListData)client;
3963 SilcChannelID *channel_id = NULL;
3964 SilcChannelEntry channel;
3965 SilcChannelClientEntry chl;
3966 SilcBuffer packet, cidp;
3967 unsigned char *tmp, *tmp_id, *tmp_mask;
3968 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3969 SilcUInt32 mode_mask = 0, tmp_len, tmp_len2;
3970 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3971 bool set_mask = FALSE;
3972 SilcPublicKey founder_key = NULL;
3973 unsigned char *fkey = NULL;
3974 SilcUInt32 fkey_len = 0;
3976 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 7);
3978 /* Get Channel ID */
3979 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3981 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3982 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3985 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
3987 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3988 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3992 /* Get the channel mode mask */
3993 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3995 SILC_GET32_MSB(mode_mask, tmp_mask);
3999 /* Get channel entry */
4000 channel = silc_idlist_find_channel_by_id(server->local_list,
4003 channel = silc_idlist_find_channel_by_id(server->global_list,
4006 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4007 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4013 /* Check whether this client is on the channel */
4014 if (!silc_server_client_on_channel(client, channel, &chl)) {
4015 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4016 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4020 /* Check that client has rights to change any requested channel modes */
4021 if (set_mask && !silc_server_check_cmode_rights(server, channel, chl,
4023 silc_server_command_send_status_reply(
4024 cmd, SILC_COMMAND_CMODE,
4025 (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) ?
4026 SILC_STATUS_ERR_NO_CHANNEL_PRIV :
4027 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV), 0);
4031 /* If mode mask was not sent as argument then merely return the current
4032 mode mask to the sender. */
4035 SILC_PUT32_MSB(channel->mode, m);
4036 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4037 SILC_STATUS_OK, 0, ident, 2,
4038 2, tmp_id, tmp_len2,
4040 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4041 packet->data, packet->len, FALSE);
4042 silc_buffer_free(packet);
4047 * Check the modes. Modes that requires nothing special operation are
4051 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
4052 /* Channel uses private keys to protect traffic. Client(s) has set the
4053 key locally they want to use, server does not know that key. */
4054 /* Nothing interesting to do here */
4056 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
4057 /* The mode is removed and we need to generate and distribute
4058 new channel key. Clients are not using private channel keys
4059 anymore after this. */
4061 /* Re-generate channel key */
4062 if (!silc_server_create_channel_key(server, channel, 0))
4065 /* Send the channel key. This sends it to our local clients and if
4066 we are normal server to our router as well. */
4067 silc_server_send_channel_key(server, NULL, channel,
4068 server->server_type == SILC_ROUTER ?
4069 FALSE : !server->standalone);
4071 cipher = channel->channel_key->cipher->name;
4072 hmac = (char *)silc_hmac_get_name(channel->hmac);
4076 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
4077 /* User limit is set on channel */
4078 SilcUInt32 user_limit;
4080 /* Get user limit */
4081 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
4083 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
4084 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4085 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4089 SILC_GET32_MSB(user_limit, tmp);
4090 channel->user_limit = user_limit;
4093 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
4094 /* User limit mode is unset. Remove user limit */
4095 channel->user_limit = 0;
4098 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
4099 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
4100 /* Passphrase has been set to channel */
4102 /* Get the passphrase */
4103 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
4105 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4106 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4110 /* Save the passphrase */
4111 passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
4114 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
4115 /* Passphrase mode is unset. remove the passphrase */
4116 silc_free(channel->passphrase);
4117 channel->passphrase = NULL;
4121 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
4122 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
4123 /* Cipher to use protect the traffic */
4124 SilcCipher newkey, oldkey;
4127 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
4129 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4130 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4134 /* Delete old cipher and allocate the new one */
4135 if (!silc_cipher_alloc(cipher, &newkey)) {
4136 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4137 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4141 oldkey = channel->channel_key;
4142 channel->channel_key = newkey;
4144 /* Re-generate channel key */
4145 if (!silc_server_create_channel_key(server, channel, 0)) {
4146 /* We don't have new key, revert to old one */
4147 channel->channel_key = oldkey;
4151 /* Remove old channel key for good */
4152 silc_cipher_free(oldkey);
4154 /* Send the channel key. This sends it to our local clients and if
4155 we are normal server to our router as well. */
4156 silc_server_send_channel_key(server, NULL, channel,
4157 server->server_type == SILC_ROUTER ?
4158 FALSE : !server->standalone);
4161 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
4162 /* Cipher mode is unset. Remove the cipher and revert back to
4164 SilcCipher newkey, oldkey;
4165 cipher = channel->cipher;
4167 /* Delete old cipher and allocate default one */
4168 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
4169 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4170 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4174 oldkey = channel->channel_key;
4175 channel->channel_key = newkey;
4177 /* Re-generate channel key */
4178 if (!silc_server_create_channel_key(server, channel, 0)) {
4179 /* We don't have new key, revert to old one */
4180 channel->channel_key = oldkey;
4184 /* Remove old channel key for good */
4185 silc_cipher_free(oldkey);
4187 /* Send the channel key. This sends it to our local clients and if
4188 we are normal server to our router as well. */
4189 silc_server_send_channel_key(server, NULL, channel,
4190 server->server_type == SILC_ROUTER ?
4191 FALSE : !server->standalone);
4195 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
4196 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
4197 /* HMAC to use protect the traffic */
4198 unsigned char hash[32];
4202 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4204 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4205 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4209 /* Delete old hmac and allocate the new one */
4210 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4211 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4212 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4216 silc_hmac_free(channel->hmac);
4217 channel->hmac = newhmac;
4219 /* Set the HMAC key out of current channel key. The client must do
4221 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4222 channel->key_len / 8, hash);
4223 silc_hmac_set_key(channel->hmac, hash,
4224 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4225 memset(hash, 0, sizeof(hash));
4228 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4229 /* Hmac mode is unset. Remove the hmac and revert back to
4232 unsigned char hash[32];
4233 hmac = channel->hmac_name;
4235 /* Delete old hmac and allocate default one */
4236 silc_hmac_free(channel->hmac);
4237 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4238 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4239 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4243 silc_hmac_free(channel->hmac);
4244 channel->hmac = newhmac;
4246 /* Set the HMAC key out of current channel key. The client must do
4248 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4249 channel->key_len / 8,
4251 silc_hmac_set_key(channel->hmac, hash,
4252 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4253 memset(hash, 0, sizeof(hash));
4257 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4258 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4259 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4260 /* Set the founder authentication */
4261 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4263 silc_server_command_send_status_reply(
4264 cmd, SILC_COMMAND_CMODE,
4265 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4269 /* Verify the payload before setting the mode */
4270 if (!silc_auth_verify_data(tmp, tmp_len, SILC_AUTH_PUBLIC_KEY,
4271 idata->public_key, 0, server->sha1hash,
4272 client->id, SILC_ID_CLIENT)) {
4273 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4274 SILC_STATUS_ERR_AUTH_FAILED,
4279 /* Save the public key */
4280 channel->founder_key = silc_pkcs_public_key_copy(idata->public_key);
4281 if (!channel->founder_key) {
4282 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4283 SILC_STATUS_ERR_AUTH_FAILED,
4288 founder_key = channel->founder_key;
4289 fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
4291 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4292 SILC_STATUS_ERR_AUTH_FAILED,
4299 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4300 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4301 if (channel->founder_key)
4302 silc_pkcs_public_key_free(channel->founder_key);
4303 channel->founder_key = NULL;
4308 /* Finally, set the mode */
4309 channel->mode = mode_mask;
4311 /* Send CMODE_CHANGE notify. */
4312 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4313 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4314 SILC_NOTIFY_TYPE_CMODE_CHANGE, 6,
4315 cidp->data, cidp->len,
4317 cipher, cipher ? strlen(cipher) : 0,
4318 hmac, hmac ? strlen(hmac) : 0,
4319 passphrase, passphrase ?
4320 strlen(passphrase) : 0,
4323 /* Set CMODE notify type to network */
4324 if (!server->standalone)
4325 silc_server_send_notify_cmode(server, server->router->connection,
4326 server->server_type == SILC_ROUTER ?
4327 TRUE : FALSE, channel,
4328 mode_mask, client->id, SILC_ID_CLIENT,
4329 cipher, hmac, passphrase, founder_key);
4331 /* Send command reply to sender */
4332 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4333 SILC_STATUS_OK, 0, ident, 2,
4334 2, tmp_id, tmp_len2,
4336 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4337 packet->data, packet->len, FALSE);
4339 silc_buffer_free(packet);
4340 silc_buffer_free(cidp);
4344 silc_free(channel_id);
4345 silc_server_command_free(cmd);
4348 /* Server side of CUMODE command. Changes client's mode on a channel. */
4350 SILC_SERVER_CMD_FUNC(cumode)
4352 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4353 SilcServer server = cmd->server;
4354 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4355 SilcIDListData idata = (SilcIDListData)client;
4356 SilcChannelID *channel_id;
4357 SilcClientID *client_id;
4358 SilcChannelEntry channel;
4359 SilcClientEntry target_client;
4360 SilcChannelClientEntry chl;
4361 SilcBuffer packet, idp;
4362 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4363 SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4365 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4366 SilcPublicKey founder_key = NULL;
4367 unsigned char *fkey = NULL;
4368 SilcUInt32 fkey_len = 0;
4370 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4372 /* Get Channel ID */
4373 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4375 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4376 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4379 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
4381 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4382 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4386 /* Get channel entry */
4387 channel = silc_idlist_find_channel_by_id(server->local_list,
4390 channel = silc_idlist_find_channel_by_id(server->global_list,
4393 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4394 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4400 /* Check whether sender is on the channel */
4401 if (!silc_server_client_on_channel(client, channel, &chl)) {
4402 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4403 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4406 sender_mask = chl->mode;
4408 /* Get the target client's channel mode mask */
4409 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4411 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4412 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4416 SILC_GET32_MSB(target_mask, tmp_mask);
4418 /* Get target Client ID */
4419 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4421 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4422 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4425 client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
4427 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4428 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4432 /* Get target client's entry */
4433 target_client = silc_idlist_find_client_by_id(server->local_list,
4434 client_id, TRUE, NULL);
4435 if (!target_client) {
4436 target_client = silc_idlist_find_client_by_id(server->global_list,
4437 client_id, TRUE, NULL);
4440 if (target_client != client &&
4441 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4442 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4443 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4444 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
4448 /* Check whether target client is on the channel */
4449 if (target_client != client) {
4450 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4451 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4452 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL, 0);
4461 /* If the target client is founder, no one else can change their mode
4463 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4464 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4465 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
4470 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4471 if (target_client != client) {
4472 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4473 SILC_STATUS_ERR_NOT_YOU, 0);
4477 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4478 /* The client tries to claim the founder rights. */
4479 unsigned char *tmp_auth;
4480 SilcUInt32 tmp_auth_len;
4481 SilcChannelClientEntry chl2;
4482 SilcHashTableList htl;
4484 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4485 !channel->founder_key || !idata->public_key ||
4486 !silc_pkcs_public_key_compare(channel->founder_key,
4487 idata->public_key)) {
4488 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4489 SILC_STATUS_ERR_AUTH_FAILED, 0);
4493 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4495 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4496 SILC_STATUS_ERR_AUTH_FAILED, 0);
4500 /* Verify the authentication payload */
4501 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len, SILC_AUTH_PUBLIC_KEY,
4502 channel->founder_key, 0, server->sha1hash,
4503 client->id, SILC_ID_CLIENT)) {
4504 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4505 SILC_STATUS_ERR_AUTH_FAILED, 0);
4510 founder_key = channel->founder_key;
4511 fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
4513 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4514 SILC_STATUS_ERR_AUTH_FAILED, 0);
4518 /* There cannot be anyone else as founder on the channel now. This
4519 client is definitely the founder due to this authentication */
4520 silc_hash_table_list(channel->user_list, &htl);
4521 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
4522 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
4523 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4524 silc_server_force_cumode_change(server, NULL, channel, chl2,
4528 silc_hash_table_list_reset(&htl);
4530 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4533 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4534 if (target_client == client) {
4535 /* Remove channel founder rights from itself */
4536 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4539 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4540 SILC_STATUS_ERR_NOT_YOU, 0);
4546 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4547 /* Promote to operator */
4548 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4549 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4550 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4551 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4552 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
4557 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4561 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4562 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4563 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4564 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4565 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
4570 /* Demote to normal user */
4571 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4576 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4577 if (target_client != client) {
4578 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4579 SILC_STATUS_ERR_NOT_YOU, 0);
4583 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
4584 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4588 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4589 if (target_client != client) {
4590 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4591 SILC_STATUS_ERR_NOT_YOU, 0);
4595 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4600 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4601 if (target_client != client) {
4602 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4603 SILC_STATUS_ERR_NOT_YOU, 0);
4607 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)) {
4608 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4612 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4613 if (target_client != client) {
4614 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4615 SILC_STATUS_ERR_NOT_YOU, 0);
4619 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4624 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4625 if (target_client != client) {
4626 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4627 SILC_STATUS_ERR_NOT_YOU, 0);
4631 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)) {
4632 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4636 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4637 if (target_client != client) {
4638 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4639 SILC_STATUS_ERR_NOT_YOU, 0);
4643 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4648 if (target_mask & SILC_CHANNEL_UMODE_QUIET) {
4649 if (!(chl->mode & SILC_CHANNEL_UMODE_QUIET)) {
4650 if (client == target_client) {
4651 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4652 SILC_STATUS_ERR_PERM_DENIED, 0);
4655 chl->mode |= SILC_CHANNEL_UMODE_QUIET;
4659 if (chl->mode & SILC_CHANNEL_UMODE_QUIET) {
4660 if (client == target_client) {
4661 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4662 SILC_STATUS_ERR_PERM_DENIED, 0);
4665 chl->mode &= ~SILC_CHANNEL_UMODE_QUIET;
4670 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4671 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4673 /* Send notify to channel, notify only if mode was actually changed. */
4675 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4676 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
4677 idp->data, idp->len,
4682 /* Set CUMODE notify type to network */
4683 if (!server->standalone)
4684 silc_server_send_notify_cumode(server, server->router->connection,
4685 server->server_type == SILC_ROUTER ?
4686 TRUE : FALSE, channel,
4687 target_mask, client->id,
4689 target_client->id, founder_key);
4692 /* Send command reply to sender */
4693 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4694 SILC_STATUS_OK, 0, ident, 3,
4696 3, tmp_ch_id, tmp_ch_len,
4697 4, tmp_id, tmp_len);
4698 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4699 packet->data, packet->len, FALSE);
4701 silc_buffer_free(packet);
4702 silc_free(channel_id);
4703 silc_free(client_id);
4704 silc_buffer_free(idp);
4708 silc_server_command_free(cmd);
4711 /* Server side of KICK command. Kicks client out of channel. */
4713 SILC_SERVER_CMD_FUNC(kick)
4715 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4716 SilcServer server = cmd->server;
4717 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4718 SilcClientEntry target_client;
4719 SilcChannelID *channel_id;
4720 SilcClientID *client_id;
4721 SilcChannelEntry channel;
4722 SilcChannelClientEntry chl;
4724 SilcUInt32 tmp_len, target_idp_len;
4725 unsigned char *tmp, *comment, *target_idp;
4727 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4729 /* Get Channel ID */
4730 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4732 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4733 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4736 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4738 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4739 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4743 /* Get channel entry */
4744 channel = silc_idlist_find_channel_by_id(server->local_list,
4747 channel = silc_idlist_find_channel_by_id(server->local_list,
4750 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4751 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4757 /* Check whether sender is on the channel */
4758 if (!silc_server_client_on_channel(client, channel, &chl)) {
4759 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4760 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4764 /* Check that the kicker is channel operator or channel founder */
4765 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
4766 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4767 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4768 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
4772 /* Get target Client ID */
4773 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4775 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4776 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4779 client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
4781 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4782 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4786 /* Get target client's entry */
4787 target_client = silc_idlist_find_client_by_id(server->local_list,
4788 client_id, TRUE, NULL);
4789 if (!target_client) {
4790 target_client = silc_idlist_find_client_by_id(server->global_list,
4791 client_id, TRUE, NULL);
4794 /* Check whether target client is on the channel */
4795 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4796 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4797 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL,
4802 /* Check that the target client is not channel founder. Channel founder
4803 cannot be kicked from the channel. */
4804 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4805 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4806 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
4813 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4817 /* Send command reply to sender */
4818 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4821 /* Send KICKED notify to local clients on the channel */
4822 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4823 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4824 SILC_NOTIFY_TYPE_KICKED, 3,
4825 target_idp, target_idp_len,
4826 comment, comment ? strlen(comment) : 0,
4827 idp->data, idp->len);
4828 silc_buffer_free(idp);
4830 /* Remove the client from the channel. If the channel does not exist
4831 after removing the client then the client kicked itself off the channel
4832 and we don't have to send anything after that. */
4833 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4834 target_client, FALSE))
4837 /* Send KICKED notify to primary route */
4838 if (!server->standalone)
4839 silc_server_send_notify_kicked(server, server->router->connection,
4840 server->server_type == SILC_ROUTER ?
4841 TRUE : FALSE, channel,
4842 target_client->id, client->id, comment);
4844 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4845 /* Re-generate channel key */
4846 if (!silc_server_create_channel_key(server, channel, 0))
4849 /* Send the channel key to the channel. The key of course is not sent
4850 to the client who was kicked off the channel. */
4851 silc_server_send_channel_key(server, target_client->connection, channel,
4852 server->server_type == SILC_ROUTER ?
4853 FALSE : !server->standalone);
4857 silc_server_command_free(cmd);
4860 /* Server side of OPER command. Client uses this comand to obtain server
4861 operator privileges to this server/router. */
4863 SILC_SERVER_CMD_FUNC(oper)
4865 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4866 SilcServer server = cmd->server;
4867 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4868 unsigned char *username, *auth;
4870 SilcServerConfigAdmin *admin;
4871 SilcIDListData idata = (SilcIDListData)client;
4872 bool result = FALSE;
4873 SilcPublicKey cached_key;
4875 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4877 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4880 /* Get the username */
4881 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4883 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4884 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4889 /* Get the admin configuration */
4890 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4891 username, client->nickname);
4893 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4894 username, client->nickname);
4896 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4897 SILC_STATUS_ERR_AUTH_FAILED,
4903 /* Get the authentication payload */
4904 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4906 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4907 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4912 /* Verify the authentication data. If both passphrase and public key
4913 is set then try both of them. */
4914 if (admin->passphrase)
4915 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4916 admin->passphrase, admin->passphrase_len,
4917 idata->hash, client->id, SILC_ID_CLIENT);
4918 if (!result && admin->publickeys) {
4919 cached_key = silc_server_get_public_key(server, admin->publickeys);
4922 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4923 cached_key, 0, idata->hash,
4924 client->id, SILC_ID_CLIENT);
4927 /* Authentication failed */
4928 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4929 SILC_STATUS_ERR_AUTH_FAILED,
4934 /* Client is now server operator */
4935 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4937 /* Update statistics */
4938 if (client->connection)
4939 server->stat.my_server_ops++;
4940 if (server->server_type == SILC_ROUTER)
4941 server->stat.server_ops++;
4943 /* Send UMODE change to primary router */
4944 if (!server->standalone)
4945 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4946 client->id, client->mode);
4948 /* Check if anyone is watching this nickname */
4949 if (server->server_type == SILC_ROUTER)
4950 silc_server_check_watcher_list(server, client, NULL,
4951 SILC_NOTIFY_TYPE_UMODE_CHANGE);
4953 /* Send reply to the sender */
4954 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4958 silc_server_command_free(cmd);
4961 SILC_TASK_CALLBACK(silc_server_command_detach_cb)
4963 QuitInternal q = (QuitInternal)context;
4964 SilcClientEntry client = (SilcClientEntry)q->sock->user_data;
4966 /* If there is pending outgoing data for the client then purge it
4967 to the network before closing connection. */
4968 silc_server_packet_queue_purge(q->server, q->sock);
4970 /* Close the connection on our side */
4971 client->router = NULL;
4972 client->connection = NULL;
4973 q->sock->user_data = NULL;
4974 silc_server_close_connection(q->server, q->sock);
4979 SILC_TASK_CALLBACK(silc_server_command_detach_timeout)
4981 QuitInternal q = (QuitInternal)context;
4982 SilcClientID *client_id = (SilcClientID *)q->sock;
4983 SilcClientEntry client;
4985 client = silc_idlist_find_client_by_id(q->server->local_list, client_id,
4988 if (client && client->mode & SILC_UMODE_DETACHED)
4989 silc_server_free_client_data(q->server, NULL, client, TRUE,
4992 silc_free(client_id);
4996 /* Server side of DETACH command. Detached the client from the network
4997 by closing the connection but preserving the session. */
4999 SILC_SERVER_CMD_FUNC(detach)
5001 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5002 SilcServer server = cmd->server;
5003 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5006 if (server->config->detach_disabled) {
5007 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
5008 SILC_STATUS_ERR_UNKNOWN_COMMAND, 0);
5012 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5015 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
5017 /* Send the user mode notify to notify that client is detached */
5018 client->mode |= SILC_UMODE_DETACHED;
5019 client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
5020 client->last_command = 0;
5021 client->fast_command = 0;
5022 if (!server->standalone)
5023 silc_server_send_notify_umode(server, server->router->connection,
5024 server->server_type == SILC_SERVER ?
5025 FALSE : TRUE, client->id, client->mode);
5026 server->stat.my_detached++;
5028 /* Check if anyone is watching this nickname */
5029 if (server->server_type == SILC_ROUTER)
5030 silc_server_check_watcher_list(server, client, NULL,
5031 SILC_NOTIFY_TYPE_UMODE_CHANGE);
5033 q = silc_calloc(1, sizeof(*q));
5035 q->sock = cmd->sock;
5036 silc_schedule_task_add(server->schedule, 0, silc_server_command_detach_cb,
5037 q, 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
5039 if (server->config->detach_timeout) {
5040 q = silc_calloc(1, sizeof(*q));
5042 q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
5043 silc_schedule_task_add(server->schedule, 0,
5044 silc_server_command_detach_timeout,
5045 q, server->config->detach_timeout * 60,
5046 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
5049 /* Send reply to the sender */
5050 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
5054 silc_server_command_free(cmd);
5057 /* Server side of WATCH command. */
5059 SILC_SERVER_CMD_FUNC(watch)
5061 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5062 SilcServer server = cmd->server;
5063 char *add_nick, *del_nick;
5064 SilcUInt32 add_nick_len, del_nick_len, tmp_len;
5066 unsigned char hash[16], *tmp;
5067 SilcClientEntry client;
5068 SilcClientID *client_id = NULL;
5070 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WATCH, cmd, 1, 3);
5072 if (server->server_type == SILC_SERVER && !server->standalone) {
5073 if (!cmd->pending) {
5074 /* Send the command to router */
5076 SilcUInt16 old_ident;
5078 old_ident = silc_command_get_ident(cmd->payload);
5079 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5080 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5082 silc_server_packet_send(server, server->router->connection,
5083 SILC_PACKET_COMMAND, cmd->packet->flags,
5084 tmpbuf->data, tmpbuf->len, TRUE);
5086 /* Reprocess this packet after received reply from router */
5087 silc_server_command_pending(server, SILC_COMMAND_WATCH,
5088 silc_command_get_ident(cmd->payload),
5089 silc_server_command_watch,
5090 silc_server_command_dup(cmd));
5091 cmd->pending = TRUE;
5092 silc_command_set_ident(cmd->payload, old_ident);
5093 silc_buffer_free(tmpbuf);
5094 } else if (context2) {
5095 /* Received reply from router, just send same data to the client. */
5096 SilcServerCommandReplyContext reply = context2;
5098 silc_command_get_status(reply->payload, &status, NULL);
5099 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, status,
5106 /* We are router and keep the watch list for local cell */
5108 /* Get the client ID */
5109 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5111 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5112 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5116 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
5118 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5119 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5124 /* Get the client entry which must be in local list */
5125 client = silc_idlist_find_client_by_id(server->local_list,
5126 client_id, TRUE, NULL);
5128 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5129 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5135 add_nick = silc_argument_get_arg_type(cmd->args, 2, &add_nick_len);
5136 del_nick = silc_argument_get_arg_type(cmd->args, 3, &del_nick_len);
5137 if (!add_nick && !del_nick) {
5138 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5139 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5144 if (add_nick && add_nick_len > 128)
5145 add_nick[128] = '\0';
5146 if (del_nick && del_nick_len > 128)
5147 del_nick[128] = '\0';
5149 memset(nick, 0, sizeof(nick));
5151 /* Add new nickname to be watched in our cell */
5153 if (silc_server_name_bad_chars(add_nick, strlen(add_nick)) == TRUE) {
5154 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5155 SILC_STATUS_ERR_BAD_NICKNAME, 0);
5159 /* Hash the nick, we have the hash saved, not nicks because we can
5160 do one to one mapping to the nick from Client ID hash this way. */
5161 silc_to_lower(add_nick, nick, sizeof(nick) - 1);
5162 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
5164 /* Check whether this client is already watching this nickname */
5165 if (silc_hash_table_find_by_context(server->watcher_list, hash,
5167 /* Nickname is alredy being watched for this client */
5168 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5169 SILC_STATUS_ERR_NICKNAME_IN_USE,
5174 /* Get the nickname from the watcher list and use the same key in
5175 new entries as well. If key doesn't exist then create it. */
5176 if (!silc_hash_table_find(server->watcher_list, hash, (void **)&tmp, NULL))
5177 tmp = silc_memdup(hash, CLIENTID_HASH_LEN);
5179 /* Add the client to the watcher list with the specified nickname hash. */
5180 silc_hash_table_add(server->watcher_list, tmp, client);
5183 /* Delete nickname from watch list */
5185 if (silc_server_name_bad_chars(del_nick, strlen(del_nick)) == TRUE) {
5186 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5187 SILC_STATUS_ERR_BAD_NICKNAME, 0);
5191 /* Hash the nick, we have the hash saved, not nicks because we can
5192 do one to one mapping to the nick from Client ID hash this way. */
5193 silc_to_lower(del_nick, nick, sizeof(nick) - 1);
5194 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
5196 /* Check that this client is watching for this nickname */
5197 if (!silc_hash_table_find_by_context(server->watcher_list, hash,
5198 client, (void **)&tmp)) {
5199 /* Nickname is alredy being watched for this client */
5200 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5201 SILC_STATUS_ERR_NO_SUCH_NICK, 0);
5205 /* Delete the nickname from the watcher list. */
5206 silc_hash_table_del_by_context(server->watcher_list, hash, client);
5208 /* Now check whether there still exists entries with this key, if not
5209 then free the key to not leak memory. */
5210 if (!silc_hash_table_find(server->watcher_list, hash, NULL, NULL))
5214 /* Distribute the watch list to backup routers too */
5215 if (server->backup) {
5217 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5218 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5219 silc_server_backup_send(server, NULL, SILC_PACKET_COMMAND,
5220 cmd->packet->flags, tmpbuf->data, tmpbuf->len,
5222 silc_buffer_free(tmpbuf);
5225 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5229 silc_free(client_id);
5230 silc_server_command_free(cmd);
5233 /* Server side of SILCOPER command. Client uses this comand to obtain router
5234 operator privileges to this router. */
5236 SILC_SERVER_CMD_FUNC(silcoper)
5238 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5239 SilcServer server = cmd->server;
5240 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5241 unsigned char *username, *auth;
5243 SilcServerConfigAdmin *admin;
5244 SilcIDListData idata = (SilcIDListData)client;
5245 bool result = FALSE;
5246 SilcPublicKey cached_key;
5248 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
5250 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5253 if (server->server_type != SILC_ROUTER) {
5254 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5255 SILC_STATUS_ERR_AUTH_FAILED, 0);
5259 /* Get the username */
5260 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5262 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5263 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5268 /* Get the admin configuration */
5269 admin = silc_server_config_find_admin(server, cmd->sock->ip,
5270 username, client->nickname);
5272 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
5273 username, client->nickname);
5275 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5276 SILC_STATUS_ERR_AUTH_FAILED, 0);
5281 /* Get the authentication payload */
5282 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5284 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5285 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5290 /* Verify the authentication data. If both passphrase and public key
5291 is set then try both of them. */
5292 if (admin->passphrase)
5293 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
5294 admin->passphrase, admin->passphrase_len,
5295 idata->hash, client->id, SILC_ID_CLIENT);
5296 if (!result && admin->publickeys) {
5297 cached_key = silc_server_get_public_key(server, admin->publickeys);
5300 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
5301 cached_key, 0, idata->hash,
5302 client->id, SILC_ID_CLIENT);
5305 /* Authentication failed */
5306 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
5307 SILC_STATUS_ERR_AUTH_FAILED, 0);
5311 /* Client is now router operator */
5312 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
5314 /* Update statistics */
5315 if (client->connection)
5316 server->stat.my_router_ops++;
5317 if (server->server_type == SILC_ROUTER)
5318 server->stat.router_ops++;
5320 /* Send UMODE change to primary router */
5321 if (!server->standalone)
5322 silc_server_send_notify_umode(server, server->router->connection, TRUE,
5323 client->id, client->mode);
5325 /* Check if anyone is watching this nickname */
5326 if (server->server_type == SILC_ROUTER)
5327 silc_server_check_watcher_list(server, client, NULL,
5328 SILC_NOTIFY_TYPE_UMODE_CHANGE);
5330 /* Send reply to the sender */
5331 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5335 silc_server_command_free(cmd);
5338 /* Server side of command BAN. This is used to manage the ban list of the
5339 channel. To add clients and remove clients from the ban list. */
5341 SILC_SERVER_CMD_FUNC(ban)
5343 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5344 SilcServer server = cmd->server;
5345 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5347 SilcChannelEntry channel;
5348 SilcChannelClientEntry chl;
5349 SilcChannelID *channel_id = NULL;
5350 unsigned char *id, *add, *del;
5351 SilcUInt32 id_len, tmp_len;
5352 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5354 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5357 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
5359 /* Get Channel ID */
5360 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
5362 channel_id = silc_id_payload_parse_id(id, id_len, NULL);
5364 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5365 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5370 /* Get channel entry. The server must know about the channel since the
5371 client is expected to be on the channel. */
5372 channel = silc_idlist_find_channel_by_id(server->local_list,
5375 channel = silc_idlist_find_channel_by_id(server->global_list,
5378 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5379 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5385 /* Check whether this client is on the channel */
5386 if (!silc_server_client_on_channel(client, channel, &chl)) {
5387 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5388 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5392 /* The client must be at least channel operator. */
5393 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
5394 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5395 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
5399 /* Get the new ban and add it to the ban list */
5400 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5402 if (!channel->ban_list)
5403 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
5405 channel->ban_list = silc_realloc(channel->ban_list,
5406 sizeof(*channel->ban_list) *
5408 strlen(channel->ban_list) + 2));
5409 if (add[tmp_len - 1] == ',')
5410 add[tmp_len - 1] = '\0';
5412 strncat(channel->ban_list, add, tmp_len);
5413 strncat(channel->ban_list, ",", 1);
5416 /* Get the ban to be removed and remove it from the list */
5417 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
5418 if (del && channel->ban_list) {
5419 char *start, *end, *n;
5421 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
5422 silc_free(channel->ban_list);
5423 channel->ban_list = NULL;
5425 start = strstr(channel->ban_list, del);
5426 if (start && strlen(start) >= tmp_len) {
5427 end = start + tmp_len;
5428 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
5429 strncat(n, channel->ban_list, start - channel->ban_list);
5430 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
5432 silc_free(channel->ban_list);
5433 channel->ban_list = n;
5438 /* Send the BAN notify type to our primary router. */
5439 if (!server->standalone && (add || del))
5440 silc_server_send_notify_ban(server, server->router->connection,
5441 server->server_type == SILC_ROUTER ?
5442 TRUE : FALSE, channel, add, del);
5444 /* Send the reply back to the client */
5446 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
5447 SILC_STATUS_OK, 0, ident, 2,
5449 3, channel->ban_list,
5451 strlen(channel->ban_list) -1 : 0);
5452 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5453 packet->data, packet->len, FALSE);
5455 silc_buffer_free(packet);
5458 silc_free(channel_id);
5459 silc_server_command_free(cmd);
5462 /* Server side command of LEAVE. Removes client from a channel. */
5464 SILC_SERVER_CMD_FUNC(leave)
5466 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5467 SilcServer server = cmd->server;
5468 SilcSocketConnection sock = cmd->sock;
5469 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
5470 SilcChannelID *id = NULL;
5471 SilcChannelEntry channel;
5475 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
5477 /* Get Channel ID */
5478 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
5480 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5481 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5484 id = silc_id_payload_parse_id(tmp, len, NULL);
5486 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5487 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5491 /* Get channel entry */
5492 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5494 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5496 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5497 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5503 /* Check whether this client is on the channel */
5504 if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
5505 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5506 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5510 /* Notify routers that they should remove this client from their list
5511 of clients on the channel. Send LEAVE notify type. */
5512 if (!server->standalone)
5513 silc_server_send_notify_leave(server, server->router->connection,
5514 server->server_type == SILC_ROUTER ?
5515 TRUE : FALSE, channel, id_entry->id);
5517 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
5518 SILC_STATUS_OK, 0, 2, tmp, len);
5520 /* Remove client from channel */
5521 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5523 /* If the channel does not exist anymore we won't send anything */
5526 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5527 /* Re-generate channel key */
5528 if (!silc_server_create_channel_key(server, channel, 0))
5531 /* Send the channel key */
5532 silc_server_send_channel_key(server, NULL, channel,
5533 server->server_type == SILC_ROUTER ?
5534 FALSE : !server->standalone);
5539 silc_server_command_free(cmd);
5542 /* Server side of command USERS. Resolves clients and their USERS currently
5543 joined on the requested channel. The list of Client ID's and their modes
5544 on the channel is sent back. */
5546 SILC_SERVER_CMD_FUNC(users)
5548 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5549 SilcServer server = cmd->server;
5550 SilcChannelEntry channel;
5551 SilcChannelID *id = NULL;
5552 SilcBuffer packet, idp;
5553 unsigned char *channel_id;
5554 SilcUInt32 channel_id_len;
5555 SilcBuffer client_id_list;
5556 SilcBuffer client_mode_list;
5557 unsigned char lc[4];
5558 SilcUInt32 list_count = 0;
5559 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5562 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5564 /* Get Channel ID */
5565 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5567 /* Get channel name */
5568 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5570 if (!channel_id && !channel_name) {
5571 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5572 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5577 id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
5579 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5580 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5585 /* If we are server and we don't know about this channel we will send
5586 the command to our router. If we know about the channel then we also
5587 have the list of users already. */
5589 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5591 channel = silc_idlist_find_channel_by_name(server->local_list,
5592 channel_name, NULL);
5594 if (!channel || (!server->standalone && (channel->disabled ||
5595 !channel->users_resolved))) {
5596 if (server->server_type != SILC_ROUTER && !server->standalone &&
5600 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5601 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5603 /* Send USERS command */
5604 silc_server_packet_send(server, server->router->connection,
5605 SILC_PACKET_COMMAND, cmd->packet->flags,
5606 tmpbuf->data, tmpbuf->len, TRUE);
5608 /* Reprocess this packet after received reply */
5609 silc_server_command_pending(server, SILC_COMMAND_USERS,
5610 silc_command_get_ident(cmd->payload),
5611 silc_server_command_users,
5612 silc_server_command_dup(cmd));
5613 cmd->pending = TRUE;
5614 silc_command_set_ident(cmd->payload, ident);
5615 silc_buffer_free(tmpbuf);
5620 /* Check the global list as well. */
5622 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5624 channel = silc_idlist_find_channel_by_name(server->global_list,
5625 channel_name, NULL);
5627 /* Channel really does not exist */
5628 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5629 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5635 /* If the channel is private or secret do not send anything, unless the
5636 user requesting this command is on the channel or is server */
5637 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5638 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5639 && !silc_server_client_on_channel(cmd->sock->user_data, channel,
5641 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5642 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5647 /* Get the users list */
5648 if (!silc_server_get_users_on_channel(server, channel, &client_id_list,
5649 &client_mode_list, &list_count)) {
5651 client_id_list = NULL;
5652 client_mode_list = NULL;
5656 SILC_PUT32_MSB(list_count, lc);
5659 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5660 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5661 SILC_STATUS_OK, 0, ident, 4,
5662 2, idp->data, idp->len,
5665 client_id_list->data : NULL,
5667 client_id_list->len : 0,
5668 5, client_mode_list ?
5669 client_mode_list->data : NULL,
5671 client_mode_list->len : 0);
5672 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5673 packet->data, packet->len, FALSE);
5675 silc_buffer_free(idp);
5676 silc_buffer_free(packet);
5678 silc_buffer_free(client_id_list);
5679 if (client_mode_list)
5680 silc_buffer_free(client_mode_list);
5684 silc_server_command_free(cmd);
5687 /* Server side of command GETKEY. This fetches the client's public key
5688 from the server where to the client is connected. */
5690 SILC_SERVER_CMD_FUNC(getkey)
5692 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5693 SilcServer server = cmd->server;
5695 SilcClientEntry client;
5696 SilcServerEntry server_entry;
5697 SilcClientID *client_id = NULL;
5698 SilcServerID *server_id = NULL;
5699 SilcIDPayload idp = NULL;
5700 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5701 unsigned char *tmp, *pkdata;
5702 SilcUInt32 tmp_len, pklen;
5703 SilcBuffer pk = NULL;
5705 SilcPublicKey public_key;
5707 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5709 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5710 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5714 idp = silc_id_payload_parse(tmp, tmp_len);
5716 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5717 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5722 id_type = silc_id_payload_get_type(idp);
5723 if (id_type == SILC_ID_CLIENT) {
5724 client_id = silc_id_payload_get_id(idp);
5726 /* If the client is not found from local list there is no chance it
5727 would be locally connected client so send the command further. */
5728 client = silc_idlist_find_client_by_id(server->local_list,
5729 client_id, TRUE, NULL);
5731 client = silc_idlist_find_client_by_id(server->global_list,
5732 client_id, TRUE, NULL);
5734 if ((!client && !cmd->pending && !server->standalone) ||
5735 (client && !client->connection && !cmd->pending &&
5736 !(client->mode & SILC_UMODE_DETACHED)) ||
5737 (client && !client->data.public_key && !cmd->pending)) {
5739 SilcUInt16 old_ident;
5740 SilcSocketConnection dest_sock;
5742 dest_sock = silc_server_get_client_route(server, NULL, 0,
5743 client_id, NULL, NULL);
5747 old_ident = silc_command_get_ident(cmd->payload);
5748 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5749 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5751 silc_server_packet_send(server, dest_sock,
5752 SILC_PACKET_COMMAND, cmd->packet->flags,
5753 tmpbuf->data, tmpbuf->len, TRUE);
5755 /* Reprocess this packet after received reply from router */
5756 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5757 silc_command_get_ident(cmd->payload),
5758 silc_server_command_getkey,
5759 silc_server_command_dup(cmd));
5760 cmd->pending = TRUE;
5761 silc_command_set_ident(cmd->payload, old_ident);
5762 silc_buffer_free(tmpbuf);
5767 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5768 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5773 /* The client is locally connected, just get the public key and
5774 send it back. If they key does not exist then do not send it,
5775 send just OK reply */
5776 public_key = client->data.public_key;
5781 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5782 pk = silc_buffer_alloc(4 + tmp_len);
5783 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5784 silc_buffer_format(pk,
5785 SILC_STR_UI_SHORT(tmp_len),
5786 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5787 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5793 } else if (id_type == SILC_ID_SERVER) {
5794 server_id = silc_id_payload_get_id(idp);
5796 /* If the server is not found from local list there is no chance it
5797 would be locally connected server so send the command further. */
5798 server_entry = silc_idlist_find_server_by_id(server->local_list,
5799 server_id, TRUE, NULL);
5801 server_entry = silc_idlist_find_server_by_id(server->global_list,
5802 server_id, TRUE, NULL);
5804 if (server_entry != server->id_entry &&
5805 ((!server_entry && !cmd->pending && !server->standalone) ||
5806 (server_entry && !server_entry->connection && !cmd->pending &&
5807 !server->standalone) ||
5808 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5809 !server->standalone))) {
5811 SilcUInt16 old_ident;
5813 old_ident = silc_command_get_ident(cmd->payload);
5814 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5815 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5817 silc_server_packet_send(server, server->router->connection,
5818 SILC_PACKET_COMMAND, cmd->packet->flags,
5819 tmpbuf->data, tmpbuf->len, TRUE);
5821 /* Reprocess this packet after received reply from router */
5822 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5823 silc_command_get_ident(cmd->payload),
5824 silc_server_command_getkey,
5825 silc_server_command_dup(cmd));
5826 cmd->pending = TRUE;
5827 silc_command_set_ident(cmd->payload, old_ident);
5828 silc_buffer_free(tmpbuf);
5832 if (!server_entry) {
5833 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5834 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
5839 /* If they key does not exist then do not send it, send just OK reply */
5840 public_key = (!server_entry->data.public_key ?
5841 (server_entry == server->id_entry ? server->public_key :
5842 NULL) : server_entry->data.public_key);
5847 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5848 pk = silc_buffer_alloc(4 + tmp_len);
5849 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5850 silc_buffer_format(pk,
5851 SILC_STR_UI_SHORT(tmp_len),
5852 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5853 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5863 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5864 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5865 SILC_STATUS_OK, 0, ident,
5869 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5870 packet->data, packet->len, FALSE);
5871 silc_buffer_free(packet);
5874 silc_buffer_free(pk);
5878 silc_id_payload_free(idp);
5879 silc_free(client_id);
5880 silc_free(server_id);
5881 silc_server_command_free(cmd);
5885 /* Private range commands, specific to this implementation */
5887 /* Server side command of CONNECT. Connects us to the specified remote
5888 server or router. */
5890 SILC_SERVER_CMD_FUNC(connect)
5892 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5893 SilcServer server = cmd->server;
5894 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5895 unsigned char *tmp, *host;
5897 SilcUInt32 port = SILC_PORT;
5899 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
5901 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5904 /* Check whether client has the permissions. */
5905 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5906 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5907 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5908 SILC_STATUS_ERR_NO_SERVER_PRIV, 0);
5912 if (server->server_type == SILC_ROUTER &&
5913 client->mode & SILC_UMODE_SERVER_OPERATOR) {
5914 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5915 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
5919 /* Get the remote server */
5920 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5922 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5923 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5929 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5931 SILC_GET32_MSB(port, tmp);
5933 /* Create the connection. It is done with timeout and is async. */
5934 silc_server_create_connection(server, host, port);
5936 /* Send reply to the sender */
5937 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5941 silc_server_command_free(cmd);
5944 /* Server side command of CLOSE. Closes connection to a specified server. */
5946 SILC_SERVER_CMD_FUNC(close)
5948 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5949 SilcServer server = cmd->server;
5950 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5951 SilcServerEntry server_entry;
5952 SilcSocketConnection sock;
5955 unsigned char *name;
5956 SilcUInt32 port = SILC_PORT;
5958 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
5960 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5963 /* Check whether client has the permissions. */
5964 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5965 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5966 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5967 SILC_STATUS_ERR_NO_SERVER_PRIV,
5972 /* Get the remote server */
5973 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5975 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5976 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5982 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5984 SILC_GET32_MSB(port, tmp);
5986 server_entry = silc_idlist_find_server_by_conn(server->local_list,
5987 name, port, FALSE, NULL);
5989 server_entry = silc_idlist_find_server_by_conn(server->global_list,
5990 name, port, FALSE, NULL);
5991 if (!server_entry) {
5992 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5993 SILC_STATUS_ERR_NO_SERVER_ID, 0);
5997 /* Send reply to the sender */
5998 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
6001 /* Close the connection to the server */
6002 sock = (SilcSocketConnection)server_entry->connection;
6004 /* If we shutdown primary router connection manually then don't trigger
6005 any reconnect or backup router connections, by setting the router
6007 if (server->router == server_entry) {
6008 server->id_entry->router = NULL;
6009 server->router = NULL;
6010 server->standalone = TRUE;
6012 silc_server_free_sock_user_data(server, sock, NULL);
6013 silc_server_close_connection(server, sock);
6016 silc_server_command_free(cmd);
6019 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
6020 active connections. */
6022 SILC_SERVER_CMD_FUNC(shutdown)
6024 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
6025 SilcServer server = cmd->server;
6026 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
6028 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
6030 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
6033 /* Check whether client has the permission. */
6034 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
6035 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
6036 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
6037 SILC_STATUS_ERR_NO_SERVER_PRIV,
6042 /* Send reply to the sender */
6043 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
6046 /* Then, gracefully, or not, bring the server down. */
6047 silc_server_stop(server);
6051 silc_server_command_free(cmd);