5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2001 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,
32 SilcCommandStatus status);
34 silc_server_command_send_status_data(SilcServerCommandContext cmd,
36 SilcCommandStatus status,
41 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
42 SilcServerCommandReplyContext cmdr,
44 SILC_TASK_CALLBACK(silc_server_command_process_timeout);
46 /* Server command list. */
47 SilcServerCommand silc_command_list[] =
49 SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
50 SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
51 SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
52 SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
53 SILC_SERVER_CMD(list, LIST, SILC_CF_LAG_STRICT | SILC_CF_REG),
54 SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
55 SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
56 SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
57 SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG_STRICT | SILC_CF_REG | SILC_CF_OPER),
58 SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
59 SILC_SERVER_CMD(connect, CONNECT,
60 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
61 SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
62 SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
63 SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG_STRICT | SILC_CF_REG),
64 SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
65 SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
66 SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG_STRICT | SILC_CF_REG),
67 SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
68 SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
69 SILC_SERVER_CMD(ban, BAN, SILC_CF_LAG_STRICT | SILC_CF_REG),
70 SILC_SERVER_CMD(close, CLOSE,
71 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
72 SILC_SERVER_CMD(shutdown, SHUTDOWN, SILC_CF_LAG | SILC_CF_REG |
74 SILC_SERVER_CMD(silcoper, SILCOPER,
75 SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
76 SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
77 SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
78 SILC_SERVER_CMD(getkey, GETKEY, SILC_CF_LAG | SILC_CF_REG),
83 /* Performs several checks to the command. It first checks whether this
84 command was called as pending command callback. If it was then it checks
85 whether error occurred in the command reply where the pending command
88 It also checks that the requested command includes correct amount
90 #define SILC_SERVER_COMMAND_CHECK(command, context, min, max) \
94 SILC_LOG_DEBUG(("Start")); \
96 if (silc_server_command_pending_error_check(cmd, context2, command)) { \
97 silc_server_command_free(cmd); \
101 _argc = silc_argument_get_arg_num(cmd->args); \
103 silc_server_command_send_status_reply(cmd, command, \
104 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
105 silc_server_command_free(cmd); \
109 silc_server_command_send_status_reply(cmd, command, \
110 SILC_STATUS_ERR_TOO_MANY_PARAMS); \
111 silc_server_command_free(cmd); \
116 /* Returns TRUE if the connection is registered. Unregistered connections
117 usually cannot send commands hence the check. */
119 static int silc_server_is_registered(SilcServer server,
120 SilcSocketConnection sock,
121 SilcServerCommandContext cmd,
124 SilcIDListData idata = (SilcIDListData)sock->user_data;
129 if (idata->status & SILC_IDLIST_STATUS_REGISTERED)
132 silc_server_command_send_status_reply(cmd, command,
133 SILC_STATUS_ERR_NOT_REGISTERED);
134 silc_server_command_free(cmd);
138 /* Internal context to hold data when executed command with timeout. */
140 SilcServerCommandContext ctx;
141 SilcServerCommand *cmd;
142 } *SilcServerCommandTimeout;
144 /* Timeout callback to process commands with timeout for client. Client's
145 commands are always executed with timeout. */
147 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
149 SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
150 SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data;
152 /* Update access time */
153 client->last_command = time(NULL);
155 if (!(timeout->cmd->flags & SILC_CF_REG))
156 timeout->cmd->cb(timeout->ctx, NULL);
157 else if (silc_server_is_registered(timeout->ctx->server,
161 timeout->cmd->cb(timeout->ctx, NULL);
166 /* Processes received command packet. */
168 void silc_server_command_process(SilcServer server,
169 SilcSocketConnection sock,
170 SilcPacketContext *packet)
172 SilcServerCommandContext ctx;
173 SilcServerCommand *cmd;
176 /* Allocate command context. This must be free'd by the
177 command routine receiving it. */
178 ctx = silc_server_command_alloc();
179 ctx->server = server;
180 ctx->sock = silc_socket_dup(sock);
181 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
183 /* Parse the command payload in the packet */
184 ctx->payload = silc_command_payload_parse(packet->buffer->data,
185 packet->buffer->len);
187 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
188 silc_buffer_free(packet->buffer);
189 silc_packet_context_free(packet);
190 silc_socket_free(ctx->sock);
194 ctx->args = silc_command_get_args(ctx->payload);
196 /* Get the command */
197 command = silc_command_get(ctx->payload);
198 for (cmd = silc_command_list; cmd->cb; cmd++)
199 if (cmd->cmd == command)
203 silc_server_command_send_status_reply(ctx, command,
204 SILC_STATUS_ERR_UNKNOWN_COMMAND);
205 silc_server_command_free(ctx);
209 /* Execute client's commands always with timeout. Normally they are
210 executed with zero (0) timeout but if client is sending command more
211 frequently than once in 2 seconds, then the timeout may be 0 to 2
213 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
214 SilcClientEntry client = (SilcClientEntry)sock->user_data;
215 SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
221 if (client->last_command && (time(NULL) - client->last_command) < 2) {
222 client->fast_command++;
225 client->fast_command = ((client->fast_command - 1) <= 0 ? 0 :
226 client->fast_command--);
230 if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
231 (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
232 silc_schedule_task_add(server->schedule, sock->sock,
233 silc_server_command_process_timeout,
235 2 - (time(NULL) - client->last_command), 0,
237 SILC_TASK_PRI_NORMAL);
239 silc_schedule_task_add(server->schedule, sock->sock,
240 silc_server_command_process_timeout,
244 SILC_TASK_PRI_NORMAL);
248 /* Execute for server */
250 if (!(cmd->flags & SILC_CF_REG))
252 else if (silc_server_is_registered(server, sock, ctx, cmd->cmd))
256 /* Allocate Command Context */
258 SilcServerCommandContext silc_server_command_alloc()
260 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
265 /* Free's the command context allocated before executing the command */
267 void silc_server_command_free(SilcServerCommandContext ctx)
270 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
272 if (ctx->users < 1) {
274 silc_command_payload_free(ctx->payload);
276 silc_packet_context_free(ctx->packet);
278 silc_socket_free(ctx->sock); /* Decrease reference counter */
283 /* Duplicate Command Context by adding reference counter. The context won't
284 be free'd untill it hits zero. */
286 SilcServerCommandContext
287 silc_server_command_dup(SilcServerCommandContext ctx)
290 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
295 /* Add new pending command to be executed when reply to a command has been
296 received. The `reply_cmd' is the command that will call the `callback'
297 with `context' when reply has been received. It can be SILC_COMMAND_NONE
298 to match any command with the `ident'. If `ident' is non-zero
299 the `callback' will be executed when received reply with command
300 identifier `ident'. */
302 void silc_server_command_pending(SilcServer server,
303 SilcCommand reply_cmd,
305 SilcServerPendingDestructor destructor,
306 SilcCommandCb callback,
309 SilcServerCommandPending *reply;
311 reply = silc_calloc(1, sizeof(*reply));
312 reply->reply_cmd = reply_cmd;
313 reply->ident = ident;
314 reply->context = context;
315 reply->callback = callback;
316 reply->destructor = destructor;
317 silc_dlist_add(server->pending_commands, reply);
320 /* Deletes pending command by reply command type. */
322 void silc_server_command_pending_del(SilcServer server,
323 SilcCommand reply_cmd,
326 SilcServerCommandPending *r;
328 silc_dlist_start(server->pending_commands);
329 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
330 if (r->reply_cmd == reply_cmd && r->ident == ident) {
331 silc_dlist_del(server->pending_commands, r);
337 /* Checks for pending commands and marks callbacks to be called from
338 the command reply function. Returns TRUE if there were pending command. */
340 SilcServerCommandPendingCallbacks
341 silc_server_command_pending_check(SilcServer server,
342 SilcServerCommandReplyContext ctx,
345 uint32 *callbacks_count)
347 SilcServerCommandPending *r;
348 SilcServerCommandPendingCallbacks callbacks = NULL;
351 silc_dlist_start(server->pending_commands);
352 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
353 if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE)
354 && r->ident == ident) {
355 callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
356 callbacks[i].context = r->context;
357 callbacks[i].callback = r->callback;
358 callbacks[i].destructor = r->destructor;
364 *callbacks_count = i;
368 /* Destructor function for pending callbacks. This is called when using
369 pending commands to free the context given for the pending command. */
371 static void silc_server_command_destructor(void *context)
373 silc_server_command_free((SilcServerCommandContext)context);
376 /* Sends simple status message as command reply packet */
379 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
381 SilcCommandStatus status)
385 SILC_LOG_DEBUG(("Sending command status %d", status));
388 silc_command_reply_payload_encode_va(command, status,
389 silc_command_get_ident(cmd->payload),
391 silc_server_packet_send(cmd->server, cmd->sock,
392 SILC_PACKET_COMMAND_REPLY, 0,
393 buffer->data, buffer->len, FALSE);
394 silc_buffer_free(buffer);
397 /* Sends command status reply with one extra argument. The argument
398 type must be sent as argument. */
401 silc_server_command_send_status_data(SilcServerCommandContext cmd,
403 SilcCommandStatus status,
410 SILC_LOG_DEBUG(("Sending command status %d", status));
413 silc_command_reply_payload_encode_va(command, status,
414 silc_command_get_ident(cmd->payload),
415 1, arg_type, arg, arg_len);
416 silc_server_packet_send(cmd->server, cmd->sock,
417 SILC_PACKET_COMMAND_REPLY, 0,
418 buffer->data, buffer->len, FALSE);
419 silc_buffer_free(buffer);
422 /* This function can be called to check whether in the command reply
423 an error occurred. This function has no effect if this is called
424 when the command function was not called as pending command callback.
425 This returns TRUE if error had occurred. */
428 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
429 SilcServerCommandReplyContext cmdr,
432 SilcCommandStatus status;
434 if (!cmd->pending || !cmdr)
437 SILC_GET16_MSB(status, silc_argument_get_arg_type(cmdr->args, 1, NULL));
438 if (status != SILC_STATUS_OK &&
439 status != SILC_STATUS_LIST_START &&
440 status != SILC_STATUS_LIST_ITEM &&
441 status != SILC_STATUS_LIST_END) {
442 /* Send the error message */
443 silc_server_command_send_status_reply(cmd, command, status);
450 /******************************************************************************
454 ******************************************************************************/
457 silc_server_command_whois_parse(SilcServerCommandContext cmd,
458 SilcClientID ***client_id,
459 uint32 *client_id_count,
467 uint32 argc = silc_argument_get_arg_num(cmd->args);
470 /* If client ID is in the command it must be used instead of nickname */
471 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
473 /* No ID, get the nickname@server string and parse it. */
474 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
476 silc_parse_userfqdn(tmp, nickname, server_name);
478 silc_server_command_send_status_reply(cmd, command,
479 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
483 /* Command includes ID, we must use that. Also check whether the command
484 has more than one ID set - take them all. */
486 *client_id = silc_calloc(1, sizeof(**client_id));
487 (*client_id)[0] = silc_id_payload_parse_id(tmp, len);
488 if ((*client_id)[0] == NULL) {
489 silc_free(*client_id);
492 *client_id_count = 1;
494 /* Take all ID's from the command packet */
496 for (k = 1, i = 1; i < argc; i++) {
497 tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
499 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
500 (*client_id_count + 1));
501 (*client_id)[k] = silc_id_payload_parse_id(tmp, len);
502 if ((*client_id)[k] == NULL) {
503 /* Cleanup all and fail */
504 for (i = 0; i < *client_id_count; i++)
505 silc_free((*client_id)[i]);
506 silc_free(*client_id);
509 (*client_id_count)++;
516 /* Get the max count of reply messages allowed */
517 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
526 /* Resolve context used by both WHOIS and IDENTIFY commands */
528 SilcServerEntry router;
530 unsigned char **res_argv;
531 uint32 *res_argv_lens;
532 uint32 *res_argv_types;
534 } *SilcServerResolveContext;
537 silc_server_command_whois_check(SilcServerCommandContext cmd,
538 SilcClientEntry *clients,
539 uint32 clients_count)
541 SilcServer server = cmd->server;
542 SilcClientEntry entry;
543 SilcServerResolveContext resolve = NULL, r = NULL;
544 uint32 resolve_count = 0;
548 for (i = 0; i < clients_count; i++) {
551 if (!entry || (entry->nickname && entry->username && entry->userinfo) ||
552 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
556 /* We need to resolve this entry since it is not complete */
558 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
559 /* The entry is being resolved (and we are not the resolver) so attach
560 to the command reply and we're done with this one. */
561 silc_server_command_pending(server, SILC_COMMAND_NONE,
562 entry->resolve_cmd_ident,
563 silc_server_command_destructor,
564 silc_server_command_whois,
565 silc_server_command_dup(cmd));
568 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
569 /* We've resolved this and it still is not ready. We'll return
570 and are that this will be handled again after it is resolved. */
571 for (i = 0; i < resolve_count; i++) {
572 for (k = 0; k < r->res_argc; k++)
573 silc_free(r->res_argv[k]);
574 silc_free(r->res_argv);
575 silc_free(r->res_argv_lens);
576 silc_free(r->res_argv_types);
581 /* We'll resolve this client */
585 for (k = 0; k < resolve_count; k++) {
586 if (resolve[k].router == entry->router) {
593 resolve = silc_realloc(resolve, sizeof(*resolve) *
594 (resolve_count + 1));
595 r = &resolve[resolve_count];
596 memset(r, 0, sizeof(*r));
597 r->router = entry->router;
598 r->ident = ++server->cmd_ident;
602 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
604 r->res_argv_lens = silc_realloc(r->res_argv_lens,
605 sizeof(*r->res_argv_lens) *
607 r->res_argv_types = silc_realloc(r->res_argv_types,
608 sizeof(*r->res_argv_types) *
610 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
611 r->res_argv[r->res_argc] = silc_calloc(idp->len,
612 sizeof(**r->res_argv));
613 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
614 r->res_argv_lens[r->res_argc] = idp->len;
615 r->res_argv_types[r->res_argc] = r->res_argc + 3;
617 silc_buffer_free(idp);
619 entry->resolve_cmd_ident = r->ident;
620 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
621 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
626 /* Do the resolving */
627 for (i = 0; i < resolve_count; i++) {
632 /* Send WHOIS request. We send WHOIS since we're doing the requesting
633 now anyway so make it a good one. */
634 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
635 r->res_argc, r->res_argv,
639 silc_server_packet_send(server, r->router->connection,
640 SILC_PACKET_COMMAND, cmd->packet->flags,
641 res_cmd->data, res_cmd->len, FALSE);
643 /* Reprocess this packet after received reply */
644 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
646 silc_server_command_destructor,
647 silc_server_command_whois,
648 silc_server_command_dup(cmd));
651 silc_buffer_free(res_cmd);
652 for (k = 0; k < r->res_argc; k++)
653 silc_free(r->res_argv[k]);
654 silc_free(r->res_argv);
655 silc_free(r->res_argv_lens);
656 silc_free(r->res_argv_types);
665 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
666 SilcClientEntry *clients,
667 uint32 clients_count,
670 SilcServer server = cmd->server;
673 SilcBuffer packet, idp, channels;
674 SilcClientEntry entry;
675 SilcCommandStatus status;
676 uint16 ident = silc_command_get_ident(cmd->payload);
677 char nh[256], uh[256];
678 unsigned char idle[4], mode[4];
679 unsigned char *fingerprint;
680 SilcSocketConnection hsock;
683 for (i = 0; i < clients_count; i++)
684 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
687 if (len == 0 && clients_count) {
689 if (entry->nickname) {
690 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
691 SILC_STATUS_ERR_NO_SUCH_NICK,
693 strlen(entry->nickname));
695 SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
696 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
697 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
698 2, idp->data, idp->len);
699 silc_buffer_free(idp);
705 status = SILC_STATUS_OK;
707 status = SILC_STATUS_LIST_START;
709 for (i = 0, k = 0; i < clients_count; i++) {
712 if (!(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
713 if (clients_count == 1) {
714 if (entry->nickname) {
715 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
716 SILC_STATUS_ERR_NO_SUCH_NICK,
718 strlen(entry->nickname));
720 SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
721 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
722 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
723 2, idp->data, idp->len);
724 silc_buffer_free(idp);
731 status = SILC_STATUS_LIST_ITEM;
733 if (clients_count > 1 && k == clients_count - 1)
734 status = SILC_STATUS_LIST_END;
736 if (count && k - 1 == count)
737 status = SILC_STATUS_LIST_END;
739 if (count && k - 1 > count)
742 /* Sanity check, however these should never fail. However, as
743 this sanity check has been added here they have failed. */
744 if (!entry->nickname || !entry->username || !entry->userinfo)
747 /* Send WHOIS reply */
748 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
749 tmp = silc_argument_get_first_arg(cmd->args, NULL);
751 memset(uh, 0, sizeof(uh));
752 memset(nh, 0, sizeof(nh));
753 memset(idle, 0, sizeof(idle));
755 strncat(nh, entry->nickname, strlen(entry->nickname));
756 if (!strchr(entry->nickname, '@')) {
758 if (entry->servername) {
759 strncat(nh, entry->servername, strlen(entry->servername));
761 len = entry->router ? strlen(entry->router->server_name) :
762 strlen(server->server_name);
763 strncat(nh, entry->router ? entry->router->server_name :
764 server->server_name, len);
768 strncat(uh, entry->username, strlen(entry->username));
769 if (!strchr(entry->username, '@')) {
771 hsock = (SilcSocketConnection)entry->connection;
772 len = strlen(hsock->hostname);
773 strncat(uh, hsock->hostname, len);
776 channels = silc_server_get_client_channel_list(server, entry);
778 if (entry->data.fingerprint[0] != 0 && entry->data.fingerprint[1] != 0)
779 fingerprint = entry->data.fingerprint;
783 SILC_PUT32_MSB(entry->mode, mode);
785 if (entry->connection) {
786 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
790 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
792 2, idp->data, idp->len,
796 strlen(entry->userinfo),
797 6, channels ? channels->data : NULL,
798 channels ? channels->len : 0,
802 fingerprint ? 20 : 0);
804 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
805 0, packet->data, packet->len, FALSE);
807 silc_buffer_free(packet);
808 silc_buffer_free(idp);
810 silc_buffer_free(channels);
817 silc_server_command_whois_process(SilcServerCommandContext cmd)
819 SilcServer server = cmd->server;
820 char *nick = NULL, *server_name = NULL;
822 SilcClientEntry *clients = NULL, entry;
823 SilcClientID **client_id = NULL;
824 uint32 client_id_count = 0, clients_count = 0;
826 bool check_global = FALSE;
828 /* Protocol dictates that we must always send the received WHOIS request
829 to our router if we are normal server, so let's do it now unless we
830 are standalone. We will not send any replies to the client until we
831 have received reply from the router. */
832 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
833 server->server_type == SILC_SERVER && !cmd->pending &&
834 !server->standalone) {
838 old_ident = silc_command_get_ident(cmd->payload);
839 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
840 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
842 /* Send WHOIS command to our router */
843 silc_server_packet_send(server, (SilcSocketConnection)
844 server->router->connection,
845 SILC_PACKET_COMMAND, cmd->packet->flags,
846 tmpbuf->data, tmpbuf->len, TRUE);
848 /* Reprocess this packet after received reply from router */
849 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
850 silc_command_get_ident(cmd->payload),
851 silc_server_command_destructor,
852 silc_server_command_whois,
853 silc_server_command_dup(cmd));
856 silc_command_set_ident(cmd->payload, old_ident);
858 silc_buffer_free(tmpbuf);
863 /* We are ready to process the command request. Let's search for the
864 requested client and send reply to the requesting client. */
866 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
868 else if (server->server_type != SILC_SERVER)
871 /* Parse the whois request */
872 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
873 &nick, &server_name, &count,
877 /* Get all clients matching that ID or nickname from local list */
878 if (client_id_count) {
879 /* Check all Client ID's received in the command packet */
880 for (i = 0; i < client_id_count; i++) {
881 entry = silc_idlist_find_client_by_id(server->local_list,
882 client_id[i], TRUE, NULL);
883 if (!entry && check_global)
884 entry = silc_idlist_find_client_by_id(server->global_list,
885 client_id[i], TRUE, NULL);
887 clients = silc_realloc(clients, sizeof(*clients) *
888 (clients_count + 1));
889 clients[clients_count++] = entry;
893 if (!silc_idlist_get_clients_by_hash(server->local_list,
894 nick, server->md5hash,
895 &clients, &clients_count))
896 silc_idlist_get_clients_by_nickname(server->local_list,
898 &clients, &clients_count);
900 if (!silc_idlist_get_clients_by_hash(server->global_list,
901 nick, server->md5hash,
902 &clients, &clients_count))
903 silc_idlist_get_clients_by_nickname(server->global_list,
905 &clients, &clients_count);
910 /* Such client(s) really does not exist in the SILC network. */
911 if (!client_id_count) {
912 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
913 SILC_STATUS_ERR_NO_SUCH_NICK,
914 3, nick, strlen(nick));
916 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
917 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
918 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
919 2, idp->data, idp->len);
920 silc_buffer_free(idp);
925 /* Router always finds the client entry if it exists in the SILC network.
926 However, it might be incomplete entry and does not include all the
927 mandatory fields that WHOIS command reply requires. Check for these and
928 make query from the server who owns the client if some fields are
930 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
935 /* Send the command reply */
936 silc_server_command_whois_send_reply(cmd, clients, clients_count,
940 if (client_id_count) {
941 for (i = 0; i < client_id_count; i++)
942 silc_free(client_id[i]);
943 silc_free(client_id);
947 silc_free(server_name);
952 /* Server side of command WHOIS. Processes user's query and sends found
953 results as command replies back to the client. */
955 SILC_SERVER_CMD_FUNC(whois)
957 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
960 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 3328);
962 ret = silc_server_command_whois_process(cmd);
965 silc_server_command_free(cmd);
968 /******************************************************************************
972 ******************************************************************************/
975 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
983 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
985 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
986 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
990 /* Get the nickname@server string and parse it. */
991 silc_parse_userfqdn(tmp, nickname, server_name);
993 /* Get the max count of reply messages allowed */
994 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1004 silc_server_command_whowas_check(SilcServerCommandContext cmd,
1005 SilcClientEntry *clients,
1006 uint32 clients_count)
1008 SilcServer server = cmd->server;
1010 SilcClientEntry entry;
1012 for (i = 0; i < clients_count; i++) {
1015 if (!entry->nickname || !entry->username) {
1022 old_ident = silc_command_get_ident(cmd->payload);
1023 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1024 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1026 /* Send WHOWAS command */
1027 silc_server_packet_send(server, entry->router->connection,
1028 SILC_PACKET_COMMAND, cmd->packet->flags,
1029 tmpbuf->data, tmpbuf->len, TRUE);
1031 /* Reprocess this packet after received reply */
1032 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1033 silc_command_get_ident(cmd->payload),
1034 silc_server_command_destructor,
1035 silc_server_command_whowas,
1036 silc_server_command_dup(cmd));
1037 cmd->pending = TRUE;
1039 silc_command_set_ident(cmd->payload, old_ident);
1041 silc_buffer_free(tmpbuf);
1050 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1051 SilcClientEntry *clients,
1052 uint32 clients_count)
1054 SilcServer server = cmd->server;
1056 int i, count = 0, len;
1057 SilcBuffer packet, idp;
1058 SilcClientEntry entry = NULL;
1059 SilcCommandStatus status;
1060 uint16 ident = silc_command_get_ident(cmd->payload);
1062 char nh[256], uh[256];
1064 status = SILC_STATUS_OK;
1065 if (clients_count > 1)
1066 status = SILC_STATUS_LIST_START;
1068 for (i = 0; i < clients_count; i++) {
1071 /* We will take only clients that are not valid anymore. They are the
1072 ones that are not registered anymore but still have a ID. They
1073 have disconnected us, and thus valid for WHOWAS. */
1074 if (entry->data.status & SILC_IDLIST_STATUS_REGISTERED)
1076 if (entry->id == NULL)
1079 if (count && i - 1 == count)
1084 if (clients_count > 2)
1085 status = SILC_STATUS_LIST_ITEM;
1087 if (clients_count > 1 && i == clients_count - 1)
1088 status = SILC_STATUS_LIST_END;
1090 /* Sanity check, however these should never fail. However, as
1091 this sanity check has been added here they have failed. */
1092 if (!entry->nickname || !entry->username)
1095 /* Send WHOWAS reply */
1096 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1097 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1099 memset(uh, 0, sizeof(uh));
1100 memset(nh, 0, sizeof(nh));
1102 strncat(nh, entry->nickname, strlen(entry->nickname));
1103 if (!strchr(entry->nickname, '@')) {
1104 strncat(nh, "@", 1);
1105 if (entry->servername) {
1106 strncat(nh, entry->servername, strlen(entry->servername));
1108 len = entry->router ? strlen(entry->router->server_name) :
1109 strlen(server->server_name);
1110 strncat(nh, entry->router ? entry->router->server_name :
1111 server->server_name, len);
1115 strncat(uh, entry->username, strlen(entry->username));
1116 if (!strchr(entry->username, '@')) {
1117 strncat(uh, "@", 1);
1118 strcat(uh, "*private*");
1122 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1124 2, idp->data, idp->len,
1129 strlen(entry->userinfo) : 0);
1130 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1131 0, packet->data, packet->len, FALSE);
1133 silc_buffer_free(packet);
1134 silc_buffer_free(idp);
1137 if (found == FALSE && entry)
1138 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1139 SILC_STATUS_ERR_NO_SUCH_NICK,
1141 strlen(entry->nickname));
1145 silc_server_command_whowas_process(SilcServerCommandContext cmd)
1147 SilcServer server = cmd->server;
1148 char *nick = NULL, *server_name = NULL;
1150 SilcClientEntry *clients = NULL;
1151 uint32 clients_count = 0;
1153 bool check_global = FALSE;
1155 /* Protocol dictates that we must always send the received WHOWAS request
1156 to our router if we are normal server, so let's do it now unless we
1157 are standalone. We will not send any replies to the client until we
1158 have received reply from the router. */
1159 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1160 server->server_type == SILC_SERVER && !cmd->pending &&
1161 !server->standalone) {
1165 old_ident = silc_command_get_ident(cmd->payload);
1166 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1167 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1169 /* Send WHOWAS command to our router */
1170 silc_server_packet_send(server, (SilcSocketConnection)
1171 server->router->connection,
1172 SILC_PACKET_COMMAND, cmd->packet->flags,
1173 tmpbuf->data, tmpbuf->len, TRUE);
1175 /* Reprocess this packet after received reply from router */
1176 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1177 silc_command_get_ident(cmd->payload),
1178 silc_server_command_destructor,
1179 silc_server_command_whowas,
1180 silc_server_command_dup(cmd));
1181 cmd->pending = TRUE;
1183 silc_command_set_ident(cmd->payload, old_ident);
1185 silc_buffer_free(tmpbuf);
1190 /* We are ready to process the command request. Let's search for the
1191 requested client and send reply to the requesting client. */
1193 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1194 check_global = TRUE;
1195 else if (server->server_type != SILC_SERVER)
1196 check_global = TRUE;
1198 /* Parse the whowas request */
1199 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1202 /* Get all clients matching that nickname from local list */
1203 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1205 &clients, &clients_count))
1206 silc_idlist_get_clients_by_hash(server->local_list,
1207 nick, server->md5hash,
1208 &clients, &clients_count);
1210 /* Check global list as well */
1212 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1214 &clients, &clients_count))
1215 silc_idlist_get_clients_by_hash(server->global_list,
1216 nick, server->md5hash,
1217 &clients, &clients_count);
1221 /* Such a client really does not exist in the SILC network. */
1222 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1223 SILC_STATUS_ERR_NO_SUCH_NICK,
1224 3, nick, strlen(nick));
1228 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1233 /* Send the command reply to the client */
1234 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1239 silc_free(server_name);
1244 /* Server side of command WHOWAS. */
1246 SILC_SERVER_CMD_FUNC(whowas)
1248 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1251 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1253 ret = silc_server_command_whowas_process(cmd);
1256 silc_server_command_free(cmd);
1259 /******************************************************************************
1263 ******************************************************************************/
1266 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1267 SilcClientEntry **clients,
1268 uint32 *clients_count,
1269 SilcServerEntry **servers,
1270 uint32 *servers_count,
1271 SilcChannelEntry **channels,
1272 uint32 *channels_count,
1275 SilcServer server = cmd->server;
1278 uint32 argc = silc_argument_get_arg_num(cmd->args);
1280 bool check_global = FALSE;
1285 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1286 check_global = TRUE;
1287 else if (server->server_type != SILC_SERVER)
1288 check_global = TRUE;
1290 /* If ID Payload is in the command it must be used instead of names */
1291 tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1293 /* No ID, get the names. */
1295 /* Try to get nickname@server. */
1296 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1299 char *nick_server = NULL;
1301 silc_parse_userfqdn(tmp, &nick, &nick_server);
1303 if (!silc_idlist_get_clients_by_hash(server->local_list,
1304 nick, server->md5hash,
1305 clients, clients_count))
1306 silc_idlist_get_clients_by_nickname(server->local_list,
1308 clients, clients_count);
1310 if (!silc_idlist_get_clients_by_hash(server->global_list,
1311 nick, server->md5hash,
1312 clients, clients_count))
1313 silc_idlist_get_clients_by_nickname(server->global_list,
1315 clients, clients_count);
1319 silc_free(nick_server);
1322 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1323 SILC_STATUS_ERR_NO_SUCH_NICK,
1324 3, tmp, strlen(tmp));
1329 /* Try to get server name */
1330 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1332 entry = silc_idlist_find_server_by_name(server->local_list,
1334 if (!entry && check_global)
1335 entry = silc_idlist_find_server_by_name(server->global_list,
1338 *servers = silc_realloc(*servers, sizeof(**servers) *
1339 (*servers_count + 1));
1340 (*servers)[(*servers_count)++] = entry;
1344 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1345 SILC_STATUS_ERR_NO_SUCH_SERVER,
1346 3, tmp, strlen(tmp));
1351 /* Try to get channel name */
1352 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1354 entry = silc_idlist_find_channel_by_name(server->local_list,
1356 if (!entry && check_global)
1357 entry = silc_idlist_find_channel_by_name(server->global_list,
1360 *channels = silc_realloc(*channels, sizeof(**channels) *
1361 (*channels_count + 1));
1362 (*channels)[(*channels_count)++] = entry;
1366 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1367 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1368 3, tmp, strlen(tmp));
1373 if (!(*clients) && !(*servers) && !(*channels)) {
1374 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1375 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1379 /* Command includes ID, we must use that. Also check whether the command
1380 has more than one ID set - take them all. */
1382 /* Take all ID's from the command packet */
1383 for (i = 0; i < argc; i++) {
1386 tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
1390 idp = silc_id_payload_parse(tmp, len);
1392 silc_free(*clients);
1393 silc_free(*servers);
1394 silc_free(*channels);
1395 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1396 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1400 id = silc_id_payload_get_id(idp);
1402 switch (silc_id_payload_get_type(idp)) {
1404 case SILC_ID_CLIENT:
1405 entry = (void *)silc_idlist_find_client_by_id(server->local_list,
1407 if (!entry && check_global)
1408 entry = (void *)silc_idlist_find_client_by_id(server->global_list,
1411 *clients = silc_realloc(*clients, sizeof(**clients) *
1412 (*clients_count + 1));
1413 (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
1415 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1416 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1423 case SILC_ID_SERVER:
1424 entry = (void *)silc_idlist_find_server_by_id(server->local_list,
1426 if (!entry && check_global)
1427 entry = (void *)silc_idlist_find_server_by_id(server->global_list,
1430 *servers = silc_realloc(*servers, sizeof(**servers) *
1431 (*servers_count + 1));
1432 (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
1434 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1435 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
1441 case SILC_ID_CHANNEL:
1442 entry = (void *)silc_idlist_find_channel_by_id(server->local_list,
1444 if (!entry && check_global)
1445 entry = (void *)silc_idlist_find_channel_by_id(server->global_list,
1448 *channels = silc_realloc(*channels, sizeof(**channels) *
1449 (*channels_count + 1));
1450 (*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
1452 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1453 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
1465 silc_free(*clients);
1466 silc_free(*servers);
1467 silc_free(*channels);
1471 /* Get the max count of reply messages allowed */
1472 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1481 /* Checks that all mandatory fields in client entry are present. If not
1482 then send WHOIS request to the server who owns the client. We use
1483 WHOIS because we want to get as much information as possible at once. */
1486 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1487 SilcClientEntry *clients,
1488 uint32 clients_count)
1490 SilcServer server = cmd->server;
1491 SilcClientEntry entry;
1492 SilcServerResolveContext resolve = NULL, r = NULL;
1493 uint32 resolve_count = 0;
1497 for (i = 0; i < clients_count; i++) {
1500 if (!entry || entry->nickname ||
1501 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
1505 /* We need to resolve this entry since it is not complete */
1507 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1508 /* The entry is being resolved (and we are not the resolver) so attach
1509 to the command reply and we're done with this one. */
1510 silc_server_command_pending(server, SILC_COMMAND_NONE,
1511 entry->resolve_cmd_ident,
1512 silc_server_command_destructor,
1513 silc_server_command_identify,
1514 silc_server_command_dup(cmd));
1517 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1518 /* We've resolved this and it still is not ready. We'll return
1519 and are that this will be handled again after it is resolved. */
1520 for (i = 0; i < resolve_count; i++) {
1521 for (k = 0; k < r->res_argc; k++)
1522 silc_free(r->res_argv[k]);
1523 silc_free(r->res_argv);
1524 silc_free(r->res_argv_lens);
1525 silc_free(r->res_argv_types);
1530 /* We'll resolve this client */
1534 for (k = 0; k < resolve_count; k++) {
1535 if (resolve[k].router == entry->router) {
1542 resolve = silc_realloc(resolve, sizeof(*resolve) *
1543 (resolve_count + 1));
1544 r = &resolve[resolve_count];
1545 memset(r, 0, sizeof(*r));
1546 r->router = entry->router;
1547 r->ident = ++server->cmd_ident;
1551 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1553 r->res_argv_lens = silc_realloc(r->res_argv_lens,
1554 sizeof(*r->res_argv_lens) *
1556 r->res_argv_types = silc_realloc(r->res_argv_types,
1557 sizeof(*r->res_argv_types) *
1559 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1560 r->res_argv[r->res_argc] = silc_calloc(idp->len,
1561 sizeof(**r->res_argv));
1562 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1563 r->res_argv_lens[r->res_argc] = idp->len;
1564 r->res_argv_types[r->res_argc] = r->res_argc + 3;
1566 silc_buffer_free(idp);
1568 entry->resolve_cmd_ident = r->ident;
1569 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1570 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1575 /* Do the resolving */
1576 for (i = 0; i < resolve_count; i++) {
1581 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1582 now anyway so make it a good one. */
1583 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1584 r->res_argc, r->res_argv,
1588 silc_server_packet_send(server, r->router->connection,
1589 SILC_PACKET_COMMAND, cmd->packet->flags,
1590 res_cmd->data, res_cmd->len, FALSE);
1592 /* Reprocess this packet after received reply */
1593 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1595 silc_server_command_destructor,
1596 silc_server_command_identify,
1597 silc_server_command_dup(cmd));
1598 cmd->pending = TRUE;
1600 silc_buffer_free(res_cmd);
1601 for (k = 0; k < r->res_argc; k++)
1602 silc_free(r->res_argv[k]);
1603 silc_free(r->res_argv);
1604 silc_free(r->res_argv_lens);
1605 silc_free(r->res_argv_types);
1614 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1615 SilcClientEntry *clients,
1616 uint32 clients_count,
1617 SilcServerEntry *servers,
1618 uint32 servers_count,
1619 SilcChannelEntry *channels,
1620 uint32 channels_count,
1623 SilcServer server = cmd->server;
1625 SilcBuffer packet, idp;
1626 SilcCommandStatus status;
1627 uint16 ident = silc_command_get_ident(cmd->payload);
1628 char nh[256], uh[256];
1629 SilcSocketConnection hsock;
1631 status = SILC_STATUS_OK;
1634 SilcClientEntry entry;
1637 for (i = 0; i < clients_count; i++)
1638 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1641 if (len == 0 && clients_count) {
1643 if (entry->nickname) {
1644 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1645 SILC_STATUS_ERR_NO_SUCH_NICK,
1647 strlen(entry->nickname));
1649 SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1650 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1651 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1652 2, idp->data, idp->len);
1653 silc_buffer_free(idp);
1660 status = SILC_STATUS_LIST_START;
1662 for (i = 0, k = 0; i < clients_count; i++) {
1665 if (!(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1666 if (clients_count == 1) {
1667 SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1668 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1669 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1670 2, idp->data, idp->len);
1671 silc_buffer_free(idp);
1677 status = SILC_STATUS_LIST_ITEM;
1678 if (clients_count > 1 && k == clients_count - 1
1679 && !servers_count && !channels_count)
1680 status = SILC_STATUS_LIST_END;
1681 if (count && k - 1 == count)
1682 status = SILC_STATUS_LIST_END;
1683 if (count && k - 1 > count)
1686 /* Send IDENTIFY reply */
1687 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1689 memset(uh, 0, sizeof(uh));
1690 memset(nh, 0, sizeof(nh));
1692 strncat(nh, entry->nickname, strlen(entry->nickname));
1693 if (!strchr(entry->nickname, '@')) {
1694 strncat(nh, "@", 1);
1695 if (entry->servername) {
1696 strncat(nh, entry->servername, strlen(entry->servername));
1698 len = entry->router ? strlen(entry->router->server_name) :
1699 strlen(server->server_name);
1700 strncat(nh, entry->router ? entry->router->server_name :
1701 server->server_name, len);
1705 if (!entry->username) {
1706 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1708 2, idp->data, idp->len,
1711 strncat(uh, entry->username, strlen(entry->username));
1712 if (!strchr(entry->username, '@')) {
1713 strncat(uh, "@", 1);
1714 hsock = (SilcSocketConnection)entry->connection;
1715 len = strlen(hsock->hostname);
1716 strncat(uh, hsock->hostname, len);
1719 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1721 2, idp->data, idp->len,
1726 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1727 0, packet->data, packet->len, FALSE);
1729 silc_buffer_free(packet);
1730 silc_buffer_free(idp);
1736 status = (status == SILC_STATUS_LIST_ITEM ?
1737 SILC_STATUS_LIST_ITEM : SILC_STATUS_OK);
1740 SilcServerEntry entry;
1742 if (status == SILC_STATUS_OK && servers_count > 1)
1743 status = SILC_STATUS_LIST_START;
1745 for (i = 0, k = 0; i < servers_count; i++) {
1749 status = SILC_STATUS_LIST_ITEM;
1750 if (servers_count > 1 && k == servers_count - 1 && !channels_count)
1751 status = SILC_STATUS_LIST_END;
1752 if (count && k - 1 == count)
1753 status = SILC_STATUS_LIST_END;
1754 if (count && k - 1 > count)
1757 /* Send IDENTIFY reply */
1758 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1760 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1762 2, idp->data, idp->len,
1763 3, entry->server_name,
1764 entry->server_name ?
1765 strlen(entry->server_name) : 0);
1766 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1767 0, packet->data, packet->len, FALSE);
1769 silc_buffer_free(packet);
1770 silc_buffer_free(idp);
1776 status = (status == SILC_STATUS_LIST_ITEM ?
1777 SILC_STATUS_LIST_ITEM : SILC_STATUS_OK);
1780 SilcChannelEntry entry;
1782 if (status == SILC_STATUS_OK && channels_count > 1)
1783 status = SILC_STATUS_LIST_START;
1785 for (i = 0, k = 0; i < channels_count; i++) {
1786 entry = channels[i];
1789 status = SILC_STATUS_LIST_ITEM;
1790 if (channels_count > 1 && k == channels_count - 1)
1791 status = SILC_STATUS_LIST_END;
1792 if (count && k - 1 == count)
1793 status = SILC_STATUS_LIST_END;
1794 if (count && k - 1 > count)
1797 /* Send IDENTIFY reply */
1798 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1800 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1802 2, idp->data, idp->len,
1803 3, entry->channel_name,
1804 entry->channel_name ?
1805 strlen(entry->channel_name): 0);
1806 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1807 0, packet->data, packet->len, FALSE);
1809 silc_buffer_free(packet);
1810 silc_buffer_free(idp);
1818 silc_server_command_identify_process(SilcServerCommandContext cmd)
1820 SilcServer server = cmd->server;
1823 SilcClientEntry *clients = NULL;
1824 SilcServerEntry *servers = NULL;
1825 SilcChannelEntry *channels = NULL;
1826 uint32 clients_count = 0, servers_count = 0, channels_count = 0;
1828 /* Protocol dictates that we must always send the received IDENTIFY request
1829 to our router if we are normal server, so let's do it now unless we
1830 are standalone. We will not send any replies to the client until we
1831 have received reply from the router. */
1832 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1833 server->server_type == SILC_SERVER && !cmd->pending &&
1834 !server->standalone) {
1838 old_ident = silc_command_get_ident(cmd->payload);
1839 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1840 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1842 /* Send IDENTIFY command to our router */
1843 silc_server_packet_send(server, (SilcSocketConnection)
1844 server->router->connection,
1845 SILC_PACKET_COMMAND, cmd->packet->flags,
1846 tmpbuf->data, tmpbuf->len, TRUE);
1848 /* Reprocess this packet after received reply from router */
1849 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1850 silc_command_get_ident(cmd->payload),
1851 silc_server_command_destructor,
1852 silc_server_command_identify,
1853 silc_server_command_dup(cmd));
1854 cmd->pending = TRUE;
1856 silc_command_set_ident(cmd->payload, old_ident);
1858 silc_buffer_free(tmpbuf);
1863 /* We are ready to process the command request. Let's search for the
1864 requested client and send reply to the requesting client. */
1866 /* Parse the IDENTIFY request */
1867 if (!silc_server_command_identify_parse(cmd,
1868 &clients, &clients_count,
1869 &servers, &servers_count,
1870 &channels, &channels_count,
1874 /* Check that all mandatory fields are present and request those data
1875 from the server who owns the client if necessary. */
1876 if (clients && !silc_server_command_identify_check_client(cmd, clients,
1882 /* Send the command reply to the client */
1883 silc_server_command_identify_send_reply(cmd,
1884 clients, clients_count,
1885 servers, servers_count,
1886 channels, channels_count,
1892 silc_free(channels);
1897 SILC_SERVER_CMD_FUNC(identify)
1899 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1902 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1904 ret = silc_server_command_identify_process(cmd);
1907 silc_server_command_free(cmd);
1910 /* Checks string for bad characters and returns TRUE if they are found. */
1912 static int silc_server_command_bad_chars(char *nick)
1916 for (i = 0; i < strlen(nick); i++) {
1917 if (!isascii(nick[i]))
1919 if (nick[i] <= 32) return TRUE;
1920 if (nick[i] == ' ') return TRUE;
1921 if (nick[i] == '*') return TRUE;
1922 if (nick[i] == '?') return TRUE;
1923 if (nick[i] == ',') return TRUE;
1929 /* Server side of command NICK. Sets nickname for user. Setting
1930 nickname causes generation of a new client ID for the client. The
1931 new client ID is sent to the client after changing the nickname. */
1933 SILC_SERVER_CMD_FUNC(nick)
1935 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1936 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1937 SilcServer server = cmd->server;
1938 SilcBuffer packet, nidp, oidp = NULL;
1939 SilcClientID *new_id;
1941 uint16 ident = silc_command_get_ident(cmd->payload);
1944 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1947 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
1949 /* Check nickname */
1950 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1951 if (silc_server_command_bad_chars(nick) == TRUE) {
1952 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1953 SILC_STATUS_ERR_BAD_NICKNAME);
1957 if (strlen(nick) > 128)
1960 /* Check for same nickname */
1961 if (!strcmp(client->nickname, nick)) {
1962 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1966 /* Create new Client ID */
1967 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
1969 cmd->server->md5hash, nick,
1972 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
1975 /* Send notify about nickname change to our router. We send the new
1976 ID and ask to replace it with the old one. If we are router the
1977 packet is broadcasted. Send NICK_CHANGE notify. */
1978 if (!server->standalone)
1979 silc_server_send_notify_nick_change(server, server->router->connection,
1980 server->server_type == SILC_SERVER ?
1981 FALSE : TRUE, client->id,
1984 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1986 /* Remove old cache entry */
1987 silc_idcache_del_by_context(server->local_list->clients, client);
1990 silc_free(client->id);
1992 /* Save the nickname as this client is our local client */
1993 silc_free(client->nickname);
1995 client->nickname = strdup(nick);
1996 client->id = new_id;
1998 /* Update client cache */
1999 silc_idcache_add(server->local_list->clients, client->nickname,
2000 client->id, (void *)client, FALSE);
2002 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2004 /* Send NICK_CHANGE notify to the client's channels */
2005 silc_server_send_notify_on_channels(server, NULL, client,
2006 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
2007 oidp->data, oidp->len,
2008 nidp->data, nidp->len);
2011 /* Send the new Client ID as reply command back to client */
2012 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
2013 SILC_STATUS_OK, ident, 1,
2014 2, nidp->data, nidp->len);
2015 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2016 0, packet->data, packet->len, FALSE);
2018 silc_buffer_free(packet);
2019 silc_buffer_free(nidp);
2021 silc_buffer_free(oidp);
2024 silc_server_command_free(cmd);
2027 /* Sends the LIST command reply */
2030 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2031 SilcChannelEntry *lch,
2033 SilcChannelEntry *gch,
2037 SilcBuffer packet, idp;
2038 SilcChannelEntry entry;
2039 SilcCommandStatus status;
2040 uint16 ident = silc_command_get_ident(cmd->payload);
2042 unsigned char usercount[4];
2045 for (i = 0; i < lch_count; i++)
2046 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2048 for (i = 0; i < gch_count; i++)
2049 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2052 status = SILC_STATUS_OK;
2053 if ((lch_count + gch_count) > 1)
2054 status = SILC_STATUS_LIST_START;
2057 for (i = 0; i < lch_count; i++) {
2063 status = SILC_STATUS_LIST_ITEM;
2064 if (i >= 1 && i == lch_count - 1 && !gch_count)
2065 status = SILC_STATUS_LIST_END;
2067 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2069 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2070 topic = "*private*";
2071 memset(usercount, 0, sizeof(usercount));
2073 topic = entry->topic;
2074 users = silc_hash_table_count(entry->user_list);
2075 SILC_PUT32_MSB(users, usercount);
2078 /* Send the reply */
2080 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2082 2, idp->data, idp->len,
2083 3, entry->channel_name,
2084 strlen(entry->channel_name),
2085 4, topic, topic ? strlen(topic) : 0,
2087 silc_server_packet_send(cmd->server, cmd->sock,
2088 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2089 packet->len, FALSE);
2090 silc_buffer_free(packet);
2091 silc_buffer_free(idp);
2095 for (i = 0; i < gch_count; i++) {
2101 status = SILC_STATUS_LIST_ITEM;
2102 if (i >= 1 && i == gch_count - 1)
2103 status = SILC_STATUS_LIST_END;
2105 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2107 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2108 topic = "*private*";
2109 memset(usercount, 0, sizeof(usercount));
2111 topic = entry->topic;
2112 users = silc_hash_table_count(entry->user_list);
2113 SILC_PUT32_MSB(users, usercount);
2116 /* Send the reply */
2118 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2120 2, idp->data, idp->len,
2121 3, entry->channel_name,
2122 strlen(entry->channel_name),
2123 4, topic, topic ? strlen(topic) : 0,
2125 silc_server_packet_send(cmd->server, cmd->sock,
2126 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2127 packet->len, FALSE);
2128 silc_buffer_free(packet);
2129 silc_buffer_free(idp);
2133 /* Server side of LIST command. This lists the channel of the requested
2134 server. Secret channels are not listed. */
2136 SILC_SERVER_CMD_FUNC(list)
2138 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2139 SilcServer server = cmd->server;
2140 SilcChannelID *channel_id = NULL;
2143 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2144 uint32 lch_count = 0, gch_count = 0;
2146 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2148 /* If we are normal server, send the command to router, since we
2149 want to know all channels in the network. */
2150 if (!cmd->pending && server->server_type == SILC_SERVER &&
2151 !server->standalone) {
2155 old_ident = silc_command_get_ident(cmd->payload);
2156 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2157 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2158 silc_server_packet_send(server, server->router->connection,
2159 SILC_PACKET_COMMAND, cmd->packet->flags,
2160 tmpbuf->data, tmpbuf->len, TRUE);
2162 /* Reprocess this packet after received reply from router */
2163 silc_server_command_pending(server, SILC_COMMAND_LIST,
2164 silc_command_get_ident(cmd->payload),
2165 silc_server_command_destructor,
2166 silc_server_command_list,
2167 silc_server_command_dup(cmd));
2168 cmd->pending = TRUE;
2169 silc_command_set_ident(cmd->payload, old_ident);
2170 silc_buffer_free(tmpbuf);
2174 /* Get Channel ID */
2175 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2177 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2179 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2180 SILC_STATUS_ERR_NO_CHANNEL_ID);
2185 /* Get the channels from local list */
2186 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2189 /* Get the channels from global list */
2190 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2193 /* Send the reply */
2194 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2195 gchannels, gch_count);
2198 silc_server_command_free(cmd);
2201 /* Server side of TOPIC command. Sets topic for channel and/or returns
2202 current topic to client. */
2204 SILC_SERVER_CMD_FUNC(topic)
2206 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2207 SilcServer server = cmd->server;
2208 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2209 SilcChannelID *channel_id;
2210 SilcChannelEntry channel;
2211 SilcChannelClientEntry chl;
2212 SilcBuffer packet, idp;
2214 uint32 argc, tmp_len;
2215 uint16 ident = silc_command_get_ident(cmd->payload);
2217 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2219 argc = silc_argument_get_arg_num(cmd->args);
2221 /* Get Channel ID */
2222 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2224 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2225 SILC_STATUS_ERR_NO_CHANNEL_ID);
2228 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2230 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2231 SILC_STATUS_ERR_NO_CHANNEL_ID);
2235 /* Check whether the channel exists */
2236 channel = silc_idlist_find_channel_by_id(server->local_list,
2239 channel = silc_idlist_find_channel_by_id(server->global_list,
2242 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2243 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2250 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2252 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2253 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2257 if (strlen(tmp) > 256) {
2258 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2259 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2263 /* See whether the client is on channel and has rights to change topic */
2264 if (!silc_hash_table_find(channel->user_list, client, NULL,
2266 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2267 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2271 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2272 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2273 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2274 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2279 /* Set the topic for channel */
2280 silc_free(channel->topic);
2281 channel->topic = strdup(tmp);
2283 /* Send TOPIC_SET notify type to the network */
2284 if (!server->standalone)
2285 silc_server_send_notify_topic_set(server, server->router->connection,
2286 server->server_type == SILC_ROUTER ?
2287 TRUE : FALSE, channel, client->id,
2290 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2292 /* Send notify about topic change to all clients on the channel */
2293 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2294 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2295 idp->data, idp->len,
2296 channel->topic, strlen(channel->topic));
2297 silc_buffer_free(idp);
2300 /* Send the topic to client as reply packet */
2301 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2302 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2303 SILC_STATUS_OK, ident, 2,
2304 2, idp->data, idp->len,
2307 strlen(channel->topic) : 0);
2308 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2309 0, packet->data, packet->len, FALSE);
2311 silc_buffer_free(packet);
2312 silc_buffer_free(idp);
2313 silc_free(channel_id);
2316 silc_server_command_free(cmd);
2319 /* Server side of INVITE command. Invites some client to join some channel.
2320 This command is also used to manage the invite list of the channel. */
2322 SILC_SERVER_CMD_FUNC(invite)
2324 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2325 SilcServer server = cmd->server;
2326 SilcSocketConnection sock = cmd->sock, dest_sock;
2327 SilcChannelClientEntry chl;
2328 SilcClientEntry sender, dest;
2329 SilcClientID *dest_id = NULL;
2330 SilcChannelEntry channel;
2331 SilcChannelID *channel_id = NULL;
2332 SilcIDListData idata;
2333 SilcBuffer idp, idp2, packet;
2334 unsigned char *tmp, *add, *del;
2336 uint16 ident = silc_command_get_ident(cmd->payload);
2338 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2340 /* Get Channel ID */
2341 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2343 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2344 SILC_STATUS_ERR_NO_CHANNEL_ID);
2347 channel_id = silc_id_payload_parse_id(tmp, len);
2349 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2350 SILC_STATUS_ERR_NO_CHANNEL_ID);
2354 /* Get the channel entry */
2355 channel = silc_idlist_find_channel_by_id(server->local_list,
2358 channel = silc_idlist_find_channel_by_id(server->global_list,
2361 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2362 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2367 /* Check whether the sender of this command is on the channel. */
2368 sender = (SilcClientEntry)sock->user_data;
2369 if (!silc_server_client_on_channel(sender, channel)) {
2370 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2371 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2375 /* Check whether the channel is invite-only channel. If yes then the
2376 sender of this command must be at least channel operator. */
2377 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2378 silc_hash_table_find(channel->user_list, sender, NULL, (void *)&chl);
2379 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2380 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2381 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2386 /* Get destination client ID */
2387 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2391 dest_id = silc_id_payload_parse_id(tmp, len);
2393 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2394 SILC_STATUS_ERR_NO_CLIENT_ID);
2398 /* Get the client entry */
2399 dest = silc_server_get_client_resolve(server, dest_id);
2401 if (server->server_type != SILC_SERVER) {
2402 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2403 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2407 /* The client info is being resolved. Reprocess this packet after
2408 receiving the reply to the query. */
2409 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2411 silc_server_command_destructor,
2412 silc_server_command_invite,
2413 silc_server_command_dup(cmd));
2414 cmd->pending = TRUE;
2415 silc_free(channel_id);
2420 /* Check whether the requested client is already on the channel. */
2421 if (silc_server_client_on_channel(dest, channel)) {
2422 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2423 SILC_STATUS_ERR_USER_ON_CHANNEL);
2427 /* Get route to the client */
2428 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2430 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2431 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2435 memset(invite, 0, sizeof(invite));
2436 strncat(invite, dest->nickname, strlen(dest->nickname));
2437 strncat(invite, "!", 1);
2438 strncat(invite, dest->username, strlen(dest->username));
2439 if (!strchr(dest->username, '@')) {
2440 strncat(invite, "@", 1);
2441 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2444 len = strlen(invite);
2445 if (!channel->invite_list)
2446 channel->invite_list = silc_calloc(len + 2,
2447 sizeof(*channel->invite_list));
2449 channel->invite_list = silc_realloc(channel->invite_list,
2450 sizeof(*channel->invite_list) *
2452 strlen(channel->invite_list) + 2));
2453 strncat(channel->invite_list, invite, len);
2454 strncat(channel->invite_list, ",", 1);
2456 /* Send notify to the client that is invited to the channel */
2457 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2458 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2459 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2461 SILC_NOTIFY_TYPE_INVITE, 3,
2462 idp->data, idp->len,
2463 channel->channel_name,
2464 strlen(channel->channel_name),
2465 idp2->data, idp2->len);
2466 silc_buffer_free(idp);
2467 silc_buffer_free(idp2);
2470 /* Add the client to the invite list of the channel */
2471 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2473 if (!channel->invite_list)
2474 channel->invite_list = silc_calloc(len + 2,
2475 sizeof(*channel->invite_list));
2477 channel->invite_list = silc_realloc(channel->invite_list,
2478 sizeof(*channel->invite_list) *
2480 strlen(channel->invite_list) + 2));
2481 if (add[len - 1] == ',')
2482 add[len - 1] = '\0';
2484 strncat(channel->invite_list, add, len);
2485 strncat(channel->invite_list, ",", 1);
2488 /* Get the invite to be removed and remove it from the list */
2489 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2490 if (del && channel->invite_list) {
2491 char *start, *end, *n;
2493 if (!strncmp(channel->invite_list, del,
2494 strlen(channel->invite_list) - 1)) {
2495 silc_free(channel->invite_list);
2496 channel->invite_list = NULL;
2498 start = strstr(channel->invite_list, del);
2499 if (start && strlen(start) >= len) {
2501 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2502 strncat(n, channel->invite_list, start - channel->invite_list);
2503 strncat(n, end + 1, ((channel->invite_list +
2504 strlen(channel->invite_list)) - end) - 1);
2505 silc_free(channel->invite_list);
2506 channel->invite_list = n;
2511 /* Send notify to the primary router */
2512 if (!server->standalone)
2513 silc_server_send_notify_invite(server, server->router->connection,
2514 server->server_type == SILC_ROUTER ?
2515 TRUE : FALSE, channel,
2516 sender->id, add, del);
2518 /* Send command reply */
2519 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2523 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2524 SILC_STATUS_OK, ident, 2,
2526 3, channel->invite_list,
2527 channel->invite_list ?
2528 strlen(channel->invite_list) : 0);
2531 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2532 SILC_STATUS_OK, ident, 1,
2534 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2535 packet->data, packet->len, FALSE);
2536 silc_buffer_free(packet);
2540 silc_free(channel_id);
2541 silc_server_command_free(cmd);
2546 SilcSocketConnection sock;
2550 /* Quits connection to client. This gets called if client won't
2551 close the connection even when it has issued QUIT command. */
2553 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2555 QuitInternal q = (QuitInternal)context;
2557 /* Free all client specific data, such as client entry and entires
2558 on channels this client may be on. */
2559 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2561 q->sock->user_data = NULL;
2563 /* Close the connection on our side */
2564 silc_server_close_connection(q->server, q->sock);
2566 silc_free(q->signoff);
2570 /* Quits SILC session. This is the normal way to disconnect client. */
2572 SILC_SERVER_CMD_FUNC(quit)
2574 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2575 SilcServer server = cmd->server;
2576 SilcSocketConnection sock = cmd->sock;
2578 unsigned char *tmp = NULL;
2581 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2583 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2586 /* Get destination ID */
2587 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2591 q = silc_calloc(1, sizeof(*q));
2594 q->signoff = tmp ? strdup(tmp) : NULL;
2596 /* We quit the connection with little timeout */
2597 silc_schedule_task_add(server->schedule, sock->sock,
2598 silc_server_command_quit_cb, (void *)q,
2599 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2602 silc_server_command_free(cmd);
2605 /* Server side of command KILL. This command is used by router operator
2606 to remove an client from the SILC Network temporarily. */
2608 SILC_SERVER_CMD_FUNC(kill)
2610 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2611 SilcServer server = cmd->server;
2612 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2613 SilcClientEntry remote_client;
2614 SilcClientID *client_id;
2615 unsigned char *tmp, *comment;
2616 uint32 tmp_len, tmp_len2;
2618 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2620 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2623 /* KILL command works only on router */
2624 if (server->server_type != SILC_ROUTER) {
2625 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2626 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2630 /* Check whether client has the permissions. */
2631 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2632 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2633 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2637 /* Get the client ID */
2638 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2640 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2641 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2644 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2646 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2647 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2651 /* Get the client entry */
2652 remote_client = silc_idlist_find_client_by_id(server->local_list,
2653 client_id, TRUE, NULL);
2654 if (!remote_client) {
2655 remote_client = silc_idlist_find_client_by_id(server->global_list,
2656 client_id, TRUE, NULL);
2657 if (!remote_client) {
2658 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2659 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2665 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2669 /* Send reply to the sender */
2670 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2673 /* Send the KILL notify packets. First send it to the channel, then
2674 to our primary router and then directly to the client who is being
2675 killed right now. */
2677 /* Send KILLED notify to the channels. It is not sent to the client
2678 as it will be sent differently destined directly to the client and not
2680 silc_server_send_notify_on_channels(server, remote_client,
2681 remote_client, SILC_NOTIFY_TYPE_KILLED,
2684 comment, comment ? tmp_len2 : 0);
2686 /* Send KILLED notify to primary route */
2687 if (!server->standalone)
2688 silc_server_send_notify_killed(server, server->router->connection, TRUE,
2689 remote_client->id, comment);
2691 /* Send KILLED notify to the client directly */
2692 silc_server_send_notify_killed(server, remote_client->connection ?
2693 remote_client->connection :
2694 remote_client->router->connection, FALSE,
2695 remote_client->id, comment);
2697 /* Remove the client from all channels. This generates new keys to the
2698 channels as well. */
2699 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2702 /* Remove the client entry, If it is locally connected then we will also
2703 disconnect the client here */
2704 if (remote_client->connection) {
2705 /* Remove locally conneted client */
2706 SilcSocketConnection sock = remote_client->connection;
2707 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2708 silc_server_close_connection(server, sock);
2710 /* Remove remote client */
2711 if (!silc_idlist_del_client(server->global_list, remote_client))
2712 silc_idlist_del_client(server->local_list, remote_client);
2716 silc_server_command_free(cmd);
2719 /* Server side of command INFO. This sends information about us to
2720 the client. If client requested specific server we will send the
2721 command to that server. */
2723 SILC_SERVER_CMD_FUNC(info)
2725 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2726 SilcServer server = cmd->server;
2727 SilcBuffer packet, idp;
2730 char *dest_server, *server_info = NULL, *server_name;
2731 uint16 ident = silc_command_get_ident(cmd->payload);
2732 SilcServerEntry entry = NULL;
2733 SilcServerID *server_id = NULL;
2735 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2737 /* Get server name */
2738 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2741 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2743 server_id = silc_id_payload_parse_id(tmp, tmp_len);
2745 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2746 SILC_STATUS_ERR_NO_SERVER_ID);
2752 /* Check whether we have this server cached */
2753 entry = silc_idlist_find_server_by_id(server->local_list,
2754 server_id, TRUE, NULL);
2756 entry = silc_idlist_find_server_by_id(server->global_list,
2757 server_id, TRUE, NULL);
2758 if (!entry && server->server_type != SILC_SERVER) {
2759 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2760 SILC_STATUS_ERR_NO_SUCH_SERVER);
2766 /* Some buggy servers has sent request to router about themselves. */
2767 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2770 if ((!dest_server && !server_id && !entry) || (entry &&
2771 entry == server->id_entry) ||
2772 (dest_server && !cmd->pending &&
2773 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2774 /* Send our reply */
2775 char info_string[256];
2777 memset(info_string, 0, sizeof(info_string));
2778 snprintf(info_string, sizeof(info_string),
2779 "location: %s server: %s admin: %s <%s>",
2780 server->config->admin_info->location,
2781 server->config->admin_info->server_type,
2782 server->config->admin_info->admin_name,
2783 server->config->admin_info->admin_email);
2785 server_info = info_string;
2786 entry = server->id_entry;
2788 /* Check whether we have this server cached */
2789 if (!entry && dest_server) {
2790 entry = silc_idlist_find_server_by_name(server->global_list,
2791 dest_server, TRUE, NULL);
2793 entry = silc_idlist_find_server_by_name(server->local_list,
2794 dest_server, TRUE, NULL);
2798 if (!cmd->pending &&
2799 server->server_type != SILC_SERVER && entry && !entry->server_info) {
2800 /* Send to the server */
2804 old_ident = silc_command_get_ident(cmd->payload);
2805 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2806 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2808 silc_server_packet_send(server, entry->connection,
2809 SILC_PACKET_COMMAND, cmd->packet->flags,
2810 tmpbuf->data, tmpbuf->len, TRUE);
2812 /* Reprocess this packet after received reply from router */
2813 silc_server_command_pending(server, SILC_COMMAND_INFO,
2814 silc_command_get_ident(cmd->payload),
2815 silc_server_command_destructor,
2816 silc_server_command_info,
2817 silc_server_command_dup(cmd));
2818 cmd->pending = TRUE;
2819 silc_command_set_ident(cmd->payload, old_ident);
2820 silc_buffer_free(tmpbuf);
2824 if (!entry && !cmd->pending && !server->standalone) {
2825 /* Send to the primary router */
2829 old_ident = silc_command_get_ident(cmd->payload);
2830 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2831 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2833 silc_server_packet_send(server, server->router->connection,
2834 SILC_PACKET_COMMAND, cmd->packet->flags,
2835 tmpbuf->data, tmpbuf->len, TRUE);
2837 /* Reprocess this packet after received reply from router */
2838 silc_server_command_pending(server, SILC_COMMAND_INFO,
2839 silc_command_get_ident(cmd->payload),
2840 silc_server_command_destructor,
2841 silc_server_command_info,
2842 silc_server_command_dup(cmd));
2843 cmd->pending = TRUE;
2844 silc_command_set_ident(cmd->payload, old_ident);
2845 silc_buffer_free(tmpbuf);
2850 silc_free(server_id);
2853 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2854 SILC_STATUS_ERR_NO_SUCH_SERVER);
2858 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2860 server_info = entry->server_info;
2861 server_name = entry->server_name;
2863 /* Send the reply */
2864 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2865 SILC_STATUS_OK, ident, 3,
2866 2, idp->data, idp->len,
2868 strlen(server_name),
2871 strlen(server_info) : 0);
2872 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2873 packet->data, packet->len, FALSE);
2875 silc_buffer_free(packet);
2876 silc_buffer_free(idp);
2879 silc_server_command_free(cmd);
2882 /* Server side of command PING. This just replies to the ping. */
2884 SILC_SERVER_CMD_FUNC(ping)
2886 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2887 SilcServer server = cmd->server;
2892 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
2895 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2897 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2898 SILC_STATUS_ERR_NO_SERVER_ID);
2901 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2905 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2906 /* Send our reply */
2907 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2910 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2911 SILC_STATUS_ERR_NO_SUCH_SERVER);
2918 silc_server_command_free(cmd);
2921 /* Internal routine to join channel. The channel sent to this function
2922 has been either created or resolved from ID lists. This joins the sent
2923 client to the channel. */
2925 static void silc_server_command_join_channel(SilcServer server,
2926 SilcServerCommandContext cmd,
2927 SilcChannelEntry channel,
2928 SilcClientID *client_id,
2933 SilcSocketConnection sock = cmd->sock;
2935 uint32 tmp_len, user_count;
2936 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
2937 SilcClientEntry client;
2938 SilcChannelClientEntry chl;
2939 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
2940 uint16 ident = silc_command_get_ident(cmd->payload);
2941 char check[512], check2[512];
2943 SILC_LOG_DEBUG(("Start"));
2948 /* Get the client entry */
2949 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2950 client = (SilcClientEntry)sock->user_data;
2952 client = silc_server_get_client_resolve(server, client_id);
2957 /* The client info is being resolved. Reprocess this packet after
2958 receiving the reply to the query. */
2959 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2960 server->cmd_ident, NULL,
2961 silc_server_command_join,
2962 silc_server_command_dup(cmd));
2963 cmd->pending = TRUE;
2967 cmd->pending = FALSE;
2971 * Check channel modes
2974 memset(check, 0, sizeof(check));
2975 memset(check2, 0, sizeof(check2));
2976 strncat(check, client->nickname, strlen(client->nickname));
2977 strncat(check, "!", 1);
2978 strncat(check, client->username, strlen(client->username));
2979 if (!strchr(client->username, '@')) {
2980 strncat(check, "@", 1);
2981 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
2984 strncat(check2, client->nickname, strlen(client->nickname));
2985 if (!strchr(client->nickname, '@')) {
2986 strncat(check2, "@", 1);
2987 strncat(check2, server->server_name, strlen(server->server_name));
2989 strncat(check2, "!", 1);
2990 strncat(check2, client->username, strlen(client->username));
2991 if (!strchr(client->username, '@')) {
2992 strncat(check2, "@", 1);
2993 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
2996 /* Check invite list if channel is invite-only channel */
2997 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2998 if (!channel->invite_list ||
2999 (!silc_string_match(channel->invite_list, check) &&
3000 !silc_string_match(channel->invite_list, check2))) {
3001 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3002 SILC_STATUS_ERR_NOT_INVITED);
3007 /* Check ban list if it exists. If the client's nickname, server,
3008 username and/or hostname is in the ban list the access to the
3009 channel is denied. */
3010 if (channel->ban_list) {
3011 if (!channel->ban_list ||
3012 silc_string_match(channel->ban_list, check) ||
3013 silc_string_match(channel->ban_list, check2)) {
3014 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3015 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
3020 /* Get passphrase */
3021 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3023 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
3024 memcpy(passphrase, tmp, tmp_len);
3027 /* Check the channel passphrase if set. */
3028 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3029 if (!passphrase || !channel->passphrase ||
3030 memcmp(channel->passphrase, passphrase,
3031 strlen(channel->passphrase))) {
3032 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3033 SILC_STATUS_ERR_BAD_PASSWORD);
3038 /* Check user count limit if set. */
3039 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3040 if (silc_hash_table_count(channel->user_list) + 1 >
3041 channel->user_limit) {
3042 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3043 SILC_STATUS_ERR_CHANNEL_IS_FULL);
3049 * Client is allowed to join to the channel. Make it happen.
3052 /* Check whether the client already is on the channel */
3053 if (silc_server_client_on_channel(client, channel)) {
3054 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3055 SILC_STATUS_ERR_USER_ON_CHANNEL);
3059 /* Generate new channel key as protocol dictates */
3061 if (!silc_server_create_channel_key(server, channel, 0))
3064 /* Send the channel key. This is broadcasted to the channel but is not
3065 sent to the client who is joining to the channel. */
3066 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3067 silc_server_send_channel_key(server, NULL, channel,
3068 server->server_type == SILC_ROUTER ?
3069 FALSE : !server->standalone);
3072 /* Join the client to the channel by adding it to channel's user list.
3073 Add also the channel to client entry's channels list for fast cross-
3075 chl = silc_calloc(1, sizeof(*chl));
3077 chl->client = client;
3078 chl->channel = channel;
3079 silc_hash_table_add(channel->user_list, client, chl);
3080 silc_hash_table_add(client->channels, channel, chl);
3082 /* Get users on the channel */
3083 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3086 /* Encode Client ID Payload of the original client who wants to join */
3087 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3089 /* Encode command reply packet */
3090 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3091 SILC_PUT32_MSB(channel->mode, mode);
3092 SILC_PUT32_MSB(created, tmp2);
3093 SILC_PUT32_MSB(user_count, tmp3);
3095 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3096 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3097 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
3098 strlen(channel->channel_key->
3100 channel->channel_key->cipher->name,
3101 channel->key_len / 8, channel->key);
3106 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3107 SILC_STATUS_OK, ident, 13,
3108 2, channel->channel_name,
3109 strlen(channel->channel_name),
3110 3, chidp->data, chidp->len,
3111 4, clidp->data, clidp->len,
3114 7, keyp ? keyp->data : NULL,
3115 keyp ? keyp->len : 0,
3116 8, channel->ban_list,
3118 strlen(channel->ban_list) : 0,
3119 9, channel->invite_list,
3120 channel->invite_list ?
3121 strlen(channel->invite_list) : 0,
3124 strlen(channel->topic) : 0,
3125 11, silc_hmac_get_name(channel->hmac),
3126 strlen(silc_hmac_get_name(channel->
3129 13, user_list->data, user_list->len,
3130 14, mode_list->data,
3133 /* Send command reply */
3134 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3135 reply->data, reply->len, FALSE);
3137 /* Send JOIN notify to locally connected clients on the channel. If
3138 we are normal server then router will send or have sent JOIN notify
3139 already. However since we've added the client already to our channel
3140 we'll ignore it (in packet_receive.c) so we must send it here. If
3141 we are router then this will send it to local clients and local
3143 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3144 SILC_NOTIFY_TYPE_JOIN, 2,
3145 clidp->data, clidp->len,
3146 chidp->data, chidp->len);
3148 if (!cmd->pending) {
3149 /* Send JOIN notify packet to our primary router */
3150 if (!server->standalone)
3151 silc_server_send_notify_join(server, server->router->connection,
3152 server->server_type == SILC_ROUTER ?
3153 TRUE : FALSE, channel, client->id);
3156 /* Distribute the channel key to all backup routers. */
3157 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3158 keyp->data, keyp->len, FALSE, TRUE);
3161 silc_buffer_free(reply);
3162 silc_buffer_free(clidp);
3163 silc_buffer_free(chidp);
3164 silc_buffer_free(keyp);
3165 silc_buffer_free(user_list);
3166 silc_buffer_free(mode_list);
3169 silc_free(passphrase);
3172 /* Server side of command JOIN. Joins client into requested channel. If
3173 the channel does not exist it will be created. */
3175 SILC_SERVER_CMD_FUNC(join)
3177 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3178 SilcServer server = cmd->server;
3180 char *tmp, *channel_name = NULL, *cipher, *hmac;
3181 SilcChannelEntry channel;
3183 bool created = FALSE, create_key = TRUE;
3184 SilcClientID *client_id;
3186 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 1, 4);
3188 /* Get channel name */
3189 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3191 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3192 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3197 if (strlen(channel_name) > 256)
3198 channel_name[255] = '\0';
3200 if (silc_server_command_bad_chars(channel_name) == TRUE) {
3201 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3202 SILC_STATUS_ERR_BAD_CHANNEL);
3206 /* Get Client ID of the client who is joining to the channel */
3207 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3209 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3210 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3213 client_id = silc_id_payload_parse_id(tmp, tmp_len);
3215 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3216 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3220 /* Get cipher and hmac name */
3221 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3222 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3224 /* See if the channel exists */
3225 channel = silc_idlist_find_channel_by_name(server->local_list,
3226 channel_name, NULL);
3228 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3229 /* If this is coming from client the Client ID in the command packet must
3230 be same as the client's ID. */
3231 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3232 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3233 if (!SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
3234 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3235 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3240 if (!channel || channel->disabled) {
3241 /* Channel not found */
3243 /* If we are standalone server we don't have a router, we just create
3244 the channel by ourselves. */
3245 if (server->standalone) {
3246 channel = silc_server_create_new_channel(server, server->id, cipher,
3247 hmac, channel_name, TRUE);
3249 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3250 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3254 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3260 /* The channel does not exist on our server. If we are normal server
3261 we will send JOIN command to our router which will handle the
3262 joining procedure (either creates the channel if it doesn't exist
3263 or joins the client to it). */
3264 if (server->server_type != SILC_ROUTER) {
3268 /* If this is pending command callback then we've resolved
3269 it and it didn't work, return since we've notified the
3270 client already in the command reply callback. */
3274 old_ident = silc_command_get_ident(cmd->payload);
3275 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3276 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3278 /* Send JOIN command to our router */
3279 silc_server_packet_send(server, (SilcSocketConnection)
3280 server->router->connection,
3281 SILC_PACKET_COMMAND, cmd->packet->flags,
3282 tmpbuf->data, tmpbuf->len, TRUE);
3284 /* Reprocess this packet after received reply from router */
3285 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3286 silc_command_get_ident(cmd->payload),
3287 silc_server_command_destructor,
3288 silc_server_command_join,
3289 silc_server_command_dup(cmd));
3290 cmd->pending = TRUE;
3294 /* We are router and the channel does not seem exist so we will check
3295 our global list as well for the channel. */
3296 channel = silc_idlist_find_channel_by_name(server->global_list,
3297 channel_name, NULL);
3299 /* Channel really does not exist, create it */
3300 channel = silc_server_create_new_channel(server, server->id, cipher,
3301 hmac, channel_name, TRUE);
3303 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3304 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3308 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3316 /* Channel not found */
3318 /* If the command came from router and we are normal server then
3319 something went wrong with the joining as the channel was not found.
3320 We can't do anything else but ignore this. */
3321 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3322 server->server_type != SILC_ROUTER)
3325 /* We are router and the channel does not seem exist so we will check
3326 our global list as well for the channel. */
3327 channel = silc_idlist_find_channel_by_name(server->global_list,
3328 channel_name, NULL);
3330 /* Channel really does not exist, create it */
3331 channel = silc_server_create_new_channel(server, server->id, cipher,
3332 hmac, channel_name, TRUE);
3334 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3335 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3339 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3346 /* Check whether the channel was created by our router */
3347 if (cmd->pending && context2) {
3348 SilcServerCommandReplyContext reply =
3349 (SilcServerCommandReplyContext)context2;
3350 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3351 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3352 SILC_GET32_MSB(created, tmp);
3353 create_key = FALSE; /* Router returned the key already */
3357 /* If the channel does not have global users and is also empty the client
3358 will be the channel founder and operator. */
3359 if (!channel->global_users && !silc_hash_table_count(channel->user_list))
3360 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3362 /* Join to the channel */
3363 silc_server_command_join_channel(server, cmd, channel, client_id,
3364 created, create_key, umode);
3366 silc_free(client_id);
3369 silc_server_command_free(cmd);
3372 /* Server side of command MOTD. Sends server's current "message of the
3373 day" to the client. */
3375 SILC_SERVER_CMD_FUNC(motd)
3377 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3378 SilcServer server = cmd->server;
3379 SilcBuffer packet, idp;
3380 char *motd, *dest_server;
3382 uint16 ident = silc_command_get_ident(cmd->payload);
3384 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3386 /* Get server name */
3387 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3389 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3390 SILC_STATUS_ERR_NO_SUCH_SERVER);
3394 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3397 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3399 if (server->config && server->config->motd &&
3400 server->config->motd->motd_file) {
3402 motd = silc_file_readfile(server->config->motd->motd_file, &motd_len);
3407 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3408 SILC_STATUS_OK, ident, 2,
3413 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3414 SILC_STATUS_OK, ident, 1,
3418 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3419 packet->data, packet->len, FALSE);
3420 silc_buffer_free(packet);
3421 silc_buffer_free(idp);
3423 SilcServerEntry entry;
3425 /* Check whether we have this server cached */
3426 entry = silc_idlist_find_server_by_name(server->global_list,
3427 dest_server, TRUE, NULL);
3429 entry = silc_idlist_find_server_by_name(server->local_list,
3430 dest_server, TRUE, NULL);
3433 if (server->server_type != SILC_SERVER && !cmd->pending &&
3434 entry && !entry->motd) {
3435 /* Send to the server */
3439 old_ident = silc_command_get_ident(cmd->payload);
3440 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3441 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3443 silc_server_packet_send(server, entry->connection,
3444 SILC_PACKET_COMMAND, cmd->packet->flags,
3445 tmpbuf->data, tmpbuf->len, TRUE);
3447 /* Reprocess this packet after received reply from router */
3448 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3449 silc_command_get_ident(cmd->payload),
3450 silc_server_command_destructor,
3451 silc_server_command_motd,
3452 silc_server_command_dup(cmd));
3453 cmd->pending = TRUE;
3454 silc_command_set_ident(cmd->payload, old_ident);
3455 silc_buffer_free(tmpbuf);
3459 if (!entry && !cmd->pending && !server->standalone) {
3460 /* Send to the primary router */
3464 old_ident = silc_command_get_ident(cmd->payload);
3465 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3466 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3468 silc_server_packet_send(server, server->router->connection,
3469 SILC_PACKET_COMMAND, cmd->packet->flags,
3470 tmpbuf->data, tmpbuf->len, TRUE);
3472 /* Reprocess this packet after received reply from router */
3473 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3474 silc_command_get_ident(cmd->payload),
3475 silc_server_command_destructor,
3476 silc_server_command_motd,
3477 silc_server_command_dup(cmd));
3478 cmd->pending = TRUE;
3479 silc_command_set_ident(cmd->payload, old_ident);
3480 silc_buffer_free(tmpbuf);
3485 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3486 SILC_STATUS_ERR_NO_SUCH_SERVER);
3490 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3491 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3492 SILC_STATUS_OK, ident, 2,
3496 strlen(entry->motd) : 0);
3497 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3498 packet->data, packet->len, FALSE);
3499 silc_buffer_free(packet);
3500 silc_buffer_free(idp);
3504 silc_server_command_free(cmd);
3507 /* Server side of command UMODE. Client can use this command to set/unset
3508 user mode. Client actually cannot set itself to be as server/router
3509 operator so this can be used only to unset the modes. */
3511 SILC_SERVER_CMD_FUNC(umode)
3513 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3514 SilcServer server = cmd->server;
3515 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3517 unsigned char *tmp_mask;
3519 uint16 ident = silc_command_get_ident(cmd->payload);
3521 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3524 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 2, 2);
3526 /* Get the client's mode mask */
3527 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3529 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3530 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3533 SILC_GET32_MSB(mask, tmp_mask);
3539 if (mask & SILC_UMODE_SERVER_OPERATOR) {
3540 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR)) {
3541 /* Cannot operator mode */
3542 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3543 SILC_STATUS_ERR_PERM_DENIED);
3547 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
3548 /* Remove the server operator rights */
3549 client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3552 if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3553 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
3554 /* Cannot operator mode */
3555 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3556 SILC_STATUS_ERR_PERM_DENIED);
3560 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
3561 /* Remove the router operator rights */
3562 client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3565 if (mask & SILC_UMODE_GONE) {
3566 client->mode |= SILC_UMODE_GONE;
3568 if (client->mode & SILC_UMODE_GONE)
3569 /* Remove the gone status */
3570 client->mode &= ~SILC_UMODE_GONE;
3573 /* Send UMODE change to primary router */
3574 if (!server->standalone)
3575 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3576 client->id, client->mode);
3578 /* Send command reply to sender */
3579 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3580 SILC_STATUS_OK, ident, 1,
3582 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3583 packet->data, packet->len, FALSE);
3584 silc_buffer_free(packet);
3587 silc_server_command_free(cmd);
3590 /* Checks that client has rights to add or remove channel modes. If any
3591 of the checks fails FALSE is returned. */
3593 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3594 SilcChannelClientEntry client,
3597 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3598 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3600 /* Check whether has rights to change anything */
3601 if (!is_op && !is_fo)
3604 /* Check whether has rights to change everything */
3608 /* We know that client is channel operator, check that they are not
3609 changing anything that requires channel founder rights. Rest of the
3610 modes are available automatically for channel operator. */
3612 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3613 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3614 if (is_op && !is_fo)
3617 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3618 if (is_op && !is_fo)
3623 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3624 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE))
3625 if (is_op && !is_fo)
3628 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3629 if (is_op && !is_fo)
3634 if (mode & SILC_CHANNEL_MODE_CIPHER) {
3635 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER))
3636 if (is_op && !is_fo)
3639 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3640 if (is_op && !is_fo)
3645 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3646 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH))
3647 if (is_op && !is_fo)
3650 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3651 if (is_op && !is_fo)
3659 /* Server side command of CMODE. Changes channel mode */
3661 SILC_SERVER_CMD_FUNC(cmode)
3663 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3664 SilcServer server = cmd->server;
3665 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3666 SilcIDListData idata = (SilcIDListData)client;
3667 SilcChannelID *channel_id;
3668 SilcChannelEntry channel;
3669 SilcChannelClientEntry chl;
3670 SilcBuffer packet, cidp;
3671 unsigned char *tmp, *tmp_id, *tmp_mask;
3672 char *cipher = NULL, *hmac = NULL;
3673 uint32 mode_mask, tmp_len, tmp_len2;
3674 uint16 ident = silc_command_get_ident(cmd->payload);
3676 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 2, 7);
3678 /* Get Channel ID */
3679 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3681 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3682 SILC_STATUS_ERR_NO_CHANNEL_ID);
3685 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3687 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3688 SILC_STATUS_ERR_NO_CHANNEL_ID);
3692 /* Get the channel mode mask */
3693 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3695 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3696 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3699 SILC_GET32_MSB(mode_mask, tmp_mask);
3701 /* Get channel entry */
3702 channel = silc_idlist_find_channel_by_id(server->local_list,
3705 channel = silc_idlist_find_channel_by_id(server->global_list,
3708 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3709 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3714 /* Check whether this client is on the channel */
3715 if (!silc_server_client_on_channel(client, channel)) {
3716 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3717 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3721 /* Get entry to the channel user list */
3722 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
3724 /* Check that client has rights to change any requested channel modes */
3725 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3726 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3727 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3732 * Check the modes. Modes that requires nothing special operation are
3736 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3737 /* Channel uses private keys to protect traffic. Client(s) has set the
3738 key locally they want to use, server does not know that key. */
3739 /* Nothing interesting to do here */
3741 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3742 /* The mode is removed and we need to generate and distribute
3743 new channel key. Clients are not using private channel keys
3744 anymore after this. */
3746 /* Re-generate channel key */
3747 if (!silc_server_create_channel_key(server, channel, 0))
3750 /* Send the channel key. This sends it to our local clients and if
3751 we are normal server to our router as well. */
3752 silc_server_send_channel_key(server, NULL, channel,
3753 server->server_type == SILC_ROUTER ?
3754 FALSE : !server->standalone);
3756 cipher = channel->channel_key->cipher->name;
3757 hmac = (char *)silc_hmac_get_name(channel->hmac);
3761 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3762 /* User limit is set on channel */
3765 /* Get user limit */
3766 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3768 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3769 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3770 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3774 SILC_GET32_MSB(user_limit, tmp);
3775 channel->user_limit = user_limit;
3778 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3779 /* User limit mode is unset. Remove user limit */
3780 channel->user_limit = 0;
3783 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3784 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3785 /* Passphrase has been set to channel */
3787 /* Get the passphrase */
3788 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3790 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3791 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3795 /* Save the passphrase */
3796 channel->passphrase = strdup(tmp);
3799 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3800 /* Passphrase mode is unset. remove the passphrase */
3801 if (channel->passphrase) {
3802 silc_free(channel->passphrase);
3803 channel->passphrase = NULL;
3808 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3809 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3810 /* Cipher to use protect the traffic */
3811 SilcCipher newkey, oldkey;
3814 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3816 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3817 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3821 /* Delete old cipher and allocate the new one */
3822 if (!silc_cipher_alloc(cipher, &newkey)) {
3823 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3824 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3828 oldkey = channel->channel_key;
3829 channel->channel_key = newkey;
3831 /* Re-generate channel key */
3832 if (!silc_server_create_channel_key(server, channel, 0)) {
3833 /* We don't have new key, revert to old one */
3834 channel->channel_key = oldkey;
3838 /* Remove old channel key for good */
3839 silc_cipher_free(oldkey);
3841 /* Send the channel key. This sends it to our local clients and if
3842 we are normal server to our router as well. */
3843 silc_server_send_channel_key(server, NULL, channel,
3844 server->server_type == SILC_ROUTER ?
3845 FALSE : !server->standalone);
3848 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3849 /* Cipher mode is unset. Remove the cipher and revert back to
3851 SilcCipher newkey, oldkey;
3852 cipher = channel->cipher;
3854 /* Delete old cipher and allocate default one */
3855 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
3856 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3857 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3861 oldkey = channel->channel_key;
3862 channel->channel_key = newkey;
3864 /* Re-generate channel key */
3865 if (!silc_server_create_channel_key(server, channel, 0)) {
3866 /* We don't have new key, revert to old one */
3867 channel->channel_key = oldkey;
3871 /* Remove old channel key for good */
3872 silc_cipher_free(oldkey);
3874 /* Send the channel key. This sends it to our local clients and if
3875 we are normal server to our router as well. */
3876 silc_server_send_channel_key(server, NULL, channel,
3877 server->server_type == SILC_ROUTER ?
3878 FALSE : !server->standalone);
3882 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3883 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3884 /* HMAC to use protect the traffic */
3885 unsigned char hash[32];
3889 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3891 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3892 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3896 /* Delete old hmac and allocate the new one */
3897 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
3898 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3899 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3903 silc_hmac_free(channel->hmac);
3904 channel->hmac = newhmac;
3906 /* Set the HMAC key out of current channel key. The client must do
3908 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
3909 channel->key_len / 8, hash);
3910 silc_hmac_set_key(channel->hmac, hash,
3911 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3912 memset(hash, 0, sizeof(hash));
3915 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
3916 /* Hmac mode is unset. Remove the hmac and revert back to
3919 unsigned char hash[32];
3920 hmac = channel->hmac_name;
3922 /* Delete old hmac and allocate default one */
3923 silc_hmac_free(channel->hmac);
3924 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
3925 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3926 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3930 silc_hmac_free(channel->hmac);
3931 channel->hmac = newhmac;
3933 /* Set the HMAC key out of current channel key. The client must do
3935 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
3936 channel->key_len / 8,
3938 silc_hmac_set_key(channel->hmac, hash,
3939 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3940 memset(hash, 0, sizeof(hash));
3944 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3945 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3946 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
3947 /* Set the founder authentication */
3948 SilcAuthPayload auth;
3950 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
3952 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3953 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3957 auth = silc_auth_payload_parse(tmp, tmp_len);
3959 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3960 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3964 /* Save the public key */
3965 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
3966 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
3969 channel->founder_method = silc_auth_get_method(auth);
3971 if (channel->founder_method == SILC_AUTH_PASSWORD) {
3972 tmp = silc_auth_get_data(auth, &tmp_len);
3973 channel->founder_passwd =
3974 silc_calloc(tmp_len + 1, sizeof(*channel->founder_passwd));
3975 memcpy(channel->founder_passwd, tmp, tmp_len);
3976 channel->founder_passwd_len = tmp_len;
3978 /* Verify the payload before setting the mode */
3979 if (!silc_auth_verify(auth, channel->founder_method,
3980 channel->founder_key, 0, idata->hash,
3981 client->id, SILC_ID_CLIENT)) {
3982 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3983 SILC_STATUS_ERR_AUTH_FAILED);
3988 silc_auth_payload_free(auth);
3992 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3993 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3994 if (channel->founder_key)
3995 silc_pkcs_public_key_free(channel->founder_key);
3996 if (channel->founder_passwd) {
3997 silc_free(channel->founder_passwd);
3998 channel->founder_passwd = NULL;
4004 /* Finally, set the mode */
4005 channel->mode = mode_mask;
4007 /* Send CMODE_CHANGE notify */
4008 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4009 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4010 SILC_NOTIFY_TYPE_CMODE_CHANGE, 4,
4011 cidp->data, cidp->len,
4013 cipher, cipher ? strlen(cipher) : 0,
4014 hmac, hmac ? strlen(hmac) : 0);
4016 /* Set CMODE notify type to network */
4017 if (!server->standalone)
4018 silc_server_send_notify_cmode(server, server->router->connection,
4019 server->server_type == SILC_ROUTER ?
4020 TRUE : FALSE, channel,
4021 mode_mask, client->id, SILC_ID_CLIENT,
4024 /* Send command reply to sender */
4025 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4026 SILC_STATUS_OK, ident, 2,
4027 2, tmp_id, tmp_len2,
4029 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4030 packet->data, packet->len, FALSE);
4032 silc_buffer_free(packet);
4033 silc_free(channel_id);
4037 silc_server_command_free(cmd);
4040 /* Server side of CUMODE command. Changes client's mode on a channel. */
4042 SILC_SERVER_CMD_FUNC(cumode)
4044 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4045 SilcServer server = cmd->server;
4046 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4047 SilcIDListData idata = (SilcIDListData)client;
4048 SilcChannelID *channel_id;
4049 SilcClientID *client_id;
4050 SilcChannelEntry channel;
4051 SilcClientEntry target_client;
4052 SilcChannelClientEntry chl;
4053 SilcBuffer packet, idp;
4054 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4055 uint32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4057 uint16 ident = silc_command_get_ident(cmd->payload);
4059 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4061 /* Get Channel ID */
4062 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4064 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4065 SILC_STATUS_ERR_NO_CHANNEL_ID);
4068 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
4070 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4071 SILC_STATUS_ERR_NO_CHANNEL_ID);
4075 /* Get channel entry */
4076 channel = silc_idlist_find_channel_by_id(server->local_list,
4079 channel = silc_idlist_find_channel_by_id(server->global_list,
4082 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4083 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4088 /* Check whether sender is on the channel */
4089 if (!silc_server_client_on_channel(client, channel)) {
4090 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4091 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4095 /* Check that client has rights to change other's rights */
4096 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4097 sender_mask = chl->mode;
4099 /* Get the target client's channel mode mask */
4100 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4102 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4103 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4106 SILC_GET32_MSB(target_mask, tmp_mask);
4108 /* Get target Client ID */
4109 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4111 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4112 SILC_STATUS_ERR_NO_CLIENT_ID);
4115 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
4117 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4118 SILC_STATUS_ERR_NO_CLIENT_ID);
4122 /* Get target client's entry */
4123 target_client = silc_idlist_find_client_by_id(server->local_list,
4124 client_id, TRUE, NULL);
4125 if (!target_client) {
4126 target_client = silc_idlist_find_client_by_id(server->global_list,
4127 client_id, TRUE, NULL);
4130 if (target_client != client &&
4131 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4132 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4133 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4134 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4138 /* Check whether target client is on the channel */
4139 if (target_client != client) {
4140 if (!silc_server_client_on_channel(target_client, channel)) {
4141 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4142 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4146 /* Get entry to the channel user list */
4147 silc_hash_table_find(channel->user_list, target_client, NULL,
4155 /* If the target client is founder, no one else can change their mode
4157 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
4158 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4159 SILC_STATUS_ERR_NOT_YOU);
4163 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4164 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4165 /* The client tries to claim the founder rights. */
4166 unsigned char *tmp_auth;
4167 uint32 tmp_auth_len, auth_len;
4170 if (target_client != client) {
4171 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4172 SILC_STATUS_ERR_NOT_YOU);
4176 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4177 !channel->founder_key || !idata->public_key ||
4178 !silc_pkcs_public_key_compare(channel->founder_key,
4179 idata->public_key)) {
4180 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4181 SILC_STATUS_ERR_NOT_YOU);
4185 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4187 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4188 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4192 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4193 (void *)channel->founder_passwd : (void *)channel->founder_key);
4194 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4195 channel->founder_passwd_len : 0);
4197 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4198 channel->founder_method, auth, auth_len,
4199 idata->hash, client->id, SILC_ID_CLIENT)) {
4200 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4201 SILC_STATUS_ERR_AUTH_FAILED);
4205 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4209 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4210 if (target_client == client) {
4211 /* Remove channel founder rights from itself */
4212 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4215 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4216 SILC_STATUS_ERR_NOT_YOU);
4222 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4223 /* Promote to operator */
4224 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4225 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4226 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4227 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4228 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4232 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4236 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4237 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4238 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4239 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4240 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4244 /* Demote to normal user */
4245 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4250 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4251 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4253 /* Send notify to channel, notify only if mode was actually changed. */
4255 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4256 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4257 idp->data, idp->len,
4261 /* Set CUMODE notify type to network */
4262 if (!server->standalone)
4263 silc_server_send_notify_cumode(server, server->router->connection,
4264 server->server_type == SILC_ROUTER ?
4265 TRUE : FALSE, channel,
4266 target_mask, client->id,
4271 /* Send command reply to sender */
4272 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4273 SILC_STATUS_OK, ident, 3,
4275 3, tmp_ch_id, tmp_ch_len,
4276 4, tmp_id, tmp_len);
4277 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4278 packet->data, packet->len, FALSE);
4280 silc_buffer_free(packet);
4281 silc_free(channel_id);
4282 silc_free(client_id);
4283 silc_buffer_free(idp);
4286 silc_server_command_free(cmd);
4289 /* Server side of KICK command. Kicks client out of channel. */
4291 SILC_SERVER_CMD_FUNC(kick)
4293 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4294 SilcServer server = cmd->server;
4295 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4296 SilcClientEntry target_client;
4297 SilcChannelID *channel_id;
4298 SilcClientID *client_id;
4299 SilcChannelEntry channel;
4300 SilcChannelClientEntry chl;
4302 uint32 tmp_len, target_idp_len;
4303 unsigned char *tmp, *comment, *target_idp;
4305 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4307 /* Get Channel ID */
4308 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4310 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4311 SILC_STATUS_ERR_NO_CHANNEL_ID);
4314 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
4316 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4317 SILC_STATUS_ERR_NO_CHANNEL_ID);
4321 /* Get channel entry */
4322 channel = silc_idlist_find_channel_by_id(server->local_list,
4325 channel = silc_idlist_find_channel_by_id(server->local_list,
4328 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4329 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4334 /* Check whether sender is on the channel */
4335 if (!silc_server_client_on_channel(client, channel)) {
4336 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4337 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4341 /* Check that the kicker is channel operator or channel founder */
4342 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4343 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4344 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4345 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4349 /* Get target Client ID */
4350 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4352 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4353 SILC_STATUS_ERR_NO_CLIENT_ID);
4356 client_id = silc_id_payload_parse_id(target_idp, target_idp_len);
4358 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4359 SILC_STATUS_ERR_NO_CLIENT_ID);
4363 /* Get target client's entry */
4364 target_client = silc_idlist_find_client_by_id(server->local_list,
4365 client_id, TRUE, NULL);
4366 if (!target_client) {
4367 target_client = silc_idlist_find_client_by_id(server->global_list,
4368 client_id, TRUE, NULL);
4371 /* Check that the target client is not channel founder. Channel founder
4372 cannot be kicked from the channel. */
4373 silc_hash_table_find(channel->user_list, target_client, NULL, (void *)&chl);
4374 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4375 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4376 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4380 /* Check whether target client is on the channel */
4381 if (!silc_server_client_on_channel(target_client, channel)) {
4382 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4383 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4389 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4393 /* Send command reply to sender */
4394 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4397 /* Send KICKED notify to local clients on the channel */
4398 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4399 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4400 SILC_NOTIFY_TYPE_KICKED, 3,
4401 target_idp, target_idp_len,
4402 comment, comment ? strlen(comment) : 0,
4403 idp->data, idp->len);
4404 silc_buffer_free(idp);
4406 /* Remove the client from the channel. If the channel does not exist
4407 after removing the client then the client kicked itself off the channel
4408 and we don't have to send anything after that. */
4409 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4410 target_client, FALSE))
4413 /* Send KICKED notify to primary route */
4414 if (!server->standalone)
4415 silc_server_send_notify_kicked(server, server->router->connection,
4416 server->server_type == SILC_ROUTER ?
4417 TRUE : FALSE, channel,
4418 target_client->id, comment);
4420 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4421 /* Re-generate channel key */
4422 if (!silc_server_create_channel_key(server, channel, 0))
4425 /* Send the channel key to the channel. The key of course is not sent
4426 to the client who was kicked off the channel. */
4427 silc_server_send_channel_key(server, target_client->connection, channel,
4428 server->server_type == SILC_ROUTER ?
4429 FALSE : !server->standalone);
4433 silc_server_command_free(cmd);
4436 /* Server side of OPER command. Client uses this comand to obtain server
4437 operator privileges to this server/router. */
4439 SILC_SERVER_CMD_FUNC(oper)
4441 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4442 SilcServer server = cmd->server;
4443 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4444 unsigned char *username, *auth;
4446 SilcServerConfigSectionAdminConnection *admin;
4447 SilcIDListData idata = (SilcIDListData)client;
4449 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4451 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4454 /* Get the username */
4455 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4457 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4458 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4462 /* Get the admin configuration */
4463 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4464 username, client->nickname);
4466 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4467 username, client->nickname);
4469 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4470 SILC_STATUS_ERR_AUTH_FAILED);
4475 /* Get the authentication payload */
4476 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4478 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4479 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4483 /* Verify the authentication data */
4484 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4485 admin->auth_data, admin->auth_data_len,
4486 idata->hash, client->id, SILC_ID_CLIENT)) {
4487 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4488 SILC_STATUS_ERR_AUTH_FAILED);
4492 /* Client is now server operator */
4493 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4495 /* Send UMODE change to primary router */
4496 if (!server->standalone)
4497 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4498 client->id, client->mode);
4500 /* Send reply to the sender */
4501 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4505 silc_server_command_free(cmd);
4508 /* Server side of SILCOPER command. Client uses this comand to obtain router
4509 operator privileges to this router. */
4511 SILC_SERVER_CMD_FUNC(silcoper)
4513 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4514 SilcServer server = cmd->server;
4515 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4516 unsigned char *username, *auth;
4518 SilcServerConfigSectionAdminConnection *admin;
4519 SilcIDListData idata = (SilcIDListData)client;
4521 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4523 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4526 if (server->server_type != SILC_ROUTER) {
4527 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4528 SILC_STATUS_ERR_AUTH_FAILED);
4532 /* Get the username */
4533 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4535 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4536 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4540 /* Get the admin configuration */
4541 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4542 username, client->nickname);
4544 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4545 username, client->nickname);
4547 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4548 SILC_STATUS_ERR_AUTH_FAILED);
4553 /* Get the authentication payload */
4554 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4556 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4557 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4561 /* Verify the authentication data */
4562 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4563 admin->auth_data, admin->auth_data_len,
4564 idata->hash, client->id, SILC_ID_CLIENT)) {
4565 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4566 SILC_STATUS_ERR_AUTH_FAILED);
4570 /* Client is now router operator */
4571 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4573 /* Send UMODE change to primary router */
4574 if (!server->standalone)
4575 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4576 client->id, client->mode);
4578 /* Send reply to the sender */
4579 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4583 silc_server_command_free(cmd);
4586 /* Server side command of CONNECT. Connects us to the specified remote
4587 server or router. */
4589 SILC_SERVER_CMD_FUNC(connect)
4591 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4592 SilcServer server = cmd->server;
4593 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4594 unsigned char *tmp, *host;
4596 uint32 port = SILC_PORT;
4598 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CONNECT, cmd, 1, 2);
4600 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4603 /* Check whether client has the permissions. */
4604 if (client->mode == SILC_UMODE_NONE) {
4605 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4606 SILC_STATUS_ERR_NO_SERVER_PRIV);
4610 if (server->server_type == SILC_ROUTER &&
4611 client->mode & SILC_UMODE_SERVER_OPERATOR) {
4612 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4613 SILC_STATUS_ERR_NO_ROUTER_PRIV);
4617 /* Get the remote server */
4618 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4620 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4621 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4626 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4628 SILC_GET32_MSB(port, tmp);
4630 /* Create the connection. It is done with timeout and is async. */
4631 silc_server_create_connection(server, host, port);
4633 /* Send reply to the sender */
4634 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4638 silc_server_command_free(cmd);
4641 /* Server side of command BAN. This is used to manage the ban list of the
4642 channel. To add clients and remove clients from the ban list. */
4644 SILC_SERVER_CMD_FUNC(ban)
4646 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4647 SilcServer server = cmd->server;
4648 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4650 SilcChannelEntry channel;
4651 SilcChannelClientEntry chl;
4652 SilcChannelID *channel_id = NULL;
4653 unsigned char *id, *add, *del;
4654 uint32 id_len, tmp_len;
4655 uint16 ident = silc_command_get_ident(cmd->payload);
4657 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4660 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4662 /* Get Channel ID */
4663 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4665 channel_id = silc_id_payload_parse_id(id, id_len);
4667 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4668 SILC_STATUS_ERR_NO_CHANNEL_ID);
4673 /* Get channel entry. The server must know about the channel since the
4674 client is expected to be on the channel. */
4675 channel = silc_idlist_find_channel_by_id(server->local_list,
4678 channel = silc_idlist_find_channel_by_id(server->global_list,
4681 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4682 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4687 /* Check whether this client is on the channel */
4688 if (!silc_server_client_on_channel(client, channel)) {
4689 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4690 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4694 /* Get entry to the channel user list */
4695 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4697 /* The client must be at least channel operator. */
4698 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4699 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4700 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4704 /* Get the new ban and add it to the ban list */
4705 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4707 if (!channel->ban_list)
4708 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4710 channel->ban_list = silc_realloc(channel->ban_list,
4711 sizeof(*channel->ban_list) *
4713 strlen(channel->ban_list) + 2));
4714 if (add[tmp_len - 1] == ',')
4715 add[tmp_len - 1] = '\0';
4717 strncat(channel->ban_list, add, tmp_len);
4718 strncat(channel->ban_list, ",", 1);
4721 /* Get the ban to be removed and remove it from the list */
4722 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4723 if (del && channel->ban_list) {
4724 char *start, *end, *n;
4726 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4727 silc_free(channel->ban_list);
4728 channel->ban_list = NULL;
4730 start = strstr(channel->ban_list, del);
4731 if (start && strlen(start) >= tmp_len) {
4732 end = start + tmp_len;
4733 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4734 strncat(n, channel->ban_list, start - channel->ban_list);
4735 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4737 silc_free(channel->ban_list);
4738 channel->ban_list = n;
4743 /* Send the BAN notify type to our primary router. */
4744 if (!server->standalone && (add || del))
4745 silc_server_send_notify_ban(server, server->router->connection,
4746 server->server_type == SILC_ROUTER ?
4747 TRUE : FALSE, channel, add, del);
4749 /* Send the reply back to the client */
4751 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4752 SILC_STATUS_OK, ident, 2,
4754 3, channel->ban_list,
4756 strlen(channel->ban_list) - 1 : 0);
4757 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4758 packet->data, packet->len, FALSE);
4760 silc_buffer_free(packet);
4763 silc_free(channel_id);
4764 silc_server_command_free(cmd);
4767 /* Server side command of CLOSE. Closes connection to a specified server. */
4769 SILC_SERVER_CMD_FUNC(close)
4771 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4772 SilcServer server = cmd->server;
4773 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4774 SilcServerEntry server_entry;
4775 SilcSocketConnection sock;
4778 unsigned char *name;
4779 uint32 port = SILC_PORT;
4781 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CLOSE, cmd, 1, 2);
4783 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4786 /* Check whether client has the permissions. */
4787 if (client->mode == SILC_UMODE_NONE) {
4788 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4789 SILC_STATUS_ERR_NO_SERVER_PRIV);
4793 /* Get the remote server */
4794 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4796 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4797 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4802 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4804 SILC_GET32_MSB(port, tmp);
4806 server_entry = silc_idlist_find_server_by_conn(server->local_list,
4807 name, port, FALSE, NULL);
4809 server_entry = silc_idlist_find_server_by_conn(server->global_list,
4810 name, port, FALSE, NULL);
4811 if (!server_entry) {
4812 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4813 SILC_STATUS_ERR_NO_SERVER_ID);
4817 /* Send reply to the sender */
4818 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4821 /* Close the connection to the server */
4822 sock = (SilcSocketConnection)server_entry->connection;
4824 /* If we shutdown primary router connection manually then don't trigger
4825 any reconnect or backup router connections, by setting the router
4827 if (server->router == server_entry) {
4828 server->id_entry->router = NULL;
4829 server->router = NULL;
4830 server->standalone = TRUE;
4832 silc_server_free_sock_user_data(server, sock);
4833 silc_server_close_connection(server, sock);
4836 silc_server_command_free(cmd);
4839 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4840 active connections. */
4842 SILC_SERVER_CMD_FUNC(shutdown)
4844 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4845 SilcServer server = cmd->server;
4846 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4848 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4850 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4853 /* Check whether client has the permission. */
4854 if (client->mode == SILC_UMODE_NONE) {
4855 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4856 SILC_STATUS_ERR_NO_SERVER_PRIV);
4860 /* Send reply to the sender */
4861 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4864 /* Then, gracefully, or not, bring the server down. */
4865 silc_server_stop(server);
4869 silc_server_command_free(cmd);
4872 /* Server side command of LEAVE. Removes client from a channel. */
4874 SILC_SERVER_CMD_FUNC(leave)
4876 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4877 SilcServer server = cmd->server;
4878 SilcSocketConnection sock = cmd->sock;
4879 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4880 SilcChannelID *id = NULL;
4881 SilcChannelEntry channel;
4885 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4887 /* Get Channel ID */
4888 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4890 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4891 SILC_STATUS_ERR_NO_CHANNEL_ID);
4894 id = silc_id_payload_parse_id(tmp, len);
4896 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4897 SILC_STATUS_ERR_NO_CHANNEL_ID);
4901 /* Get channel entry */
4902 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4904 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4906 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4907 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4912 /* Check whether this client is on the channel */
4913 if (!silc_server_client_on_channel(id_entry, channel)) {
4914 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4915 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4919 /* Notify routers that they should remove this client from their list
4920 of clients on the channel. Send LEAVE notify type. */
4921 if (!server->standalone)
4922 silc_server_send_notify_leave(server, server->router->connection,
4923 server->server_type == SILC_ROUTER ?
4924 TRUE : FALSE, channel, id_entry->id);
4926 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4929 /* Remove client from channel */
4930 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4932 /* If the channel does not exist anymore we won't send anything */
4935 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4936 /* Re-generate channel key */
4937 if (!silc_server_create_channel_key(server, channel, 0))
4940 /* Send the channel key */
4941 silc_server_send_channel_key(server, NULL, channel,
4942 server->server_type == SILC_ROUTER ?
4943 FALSE : !server->standalone);
4948 silc_server_command_free(cmd);
4951 /* Server side of command USERS. Resolves clients and their USERS currently
4952 joined on the requested channel. The list of Client ID's and their modes
4953 on the channel is sent back. */
4955 SILC_SERVER_CMD_FUNC(users)
4957 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4958 SilcServer server = cmd->server;
4959 SilcChannelEntry channel;
4960 SilcChannelID *id = NULL;
4961 SilcBuffer packet, idp;
4962 unsigned char *channel_id;
4963 uint32 channel_id_len;
4964 SilcBuffer client_id_list;
4965 SilcBuffer client_mode_list;
4966 unsigned char lc[4];
4967 uint32 list_count = 0;
4968 uint16 ident = silc_command_get_ident(cmd->payload);
4971 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
4973 /* Get Channel ID */
4974 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4976 /* Get channel name */
4977 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
4979 if (!channel_id && !channel_name) {
4980 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4981 SILC_STATUS_ERR_NO_CHANNEL_ID);
4986 id = silc_id_payload_parse_id(channel_id, channel_id_len);
4988 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4989 SILC_STATUS_ERR_NO_CHANNEL_ID);
4994 /* If we are server and we don't know about this channel we will send
4995 the command to our router. If we know about the channel then we also
4996 have the list of users already. */
4998 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5000 channel = silc_idlist_find_channel_by_name(server->local_list,
5001 channel_name, NULL);
5003 if (!channel || channel->disabled) {
5004 if (server->server_type != SILC_ROUTER && !server->standalone &&
5008 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5009 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5011 /* Send USERS command */
5012 silc_server_packet_send(server, server->router->connection,
5013 SILC_PACKET_COMMAND, cmd->packet->flags,
5014 tmpbuf->data, tmpbuf->len, TRUE);
5016 /* Reprocess this packet after received reply */
5017 silc_server_command_pending(server, SILC_COMMAND_USERS,
5018 silc_command_get_ident(cmd->payload),
5019 silc_server_command_destructor,
5020 silc_server_command_users,
5021 silc_server_command_dup(cmd));
5022 cmd->pending = TRUE;
5023 silc_command_set_ident(cmd->payload, ident);
5025 silc_buffer_free(tmpbuf);
5030 /* Check the global list as well. */
5032 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5034 channel = silc_idlist_find_channel_by_name(server->global_list,
5035 channel_name, NULL);
5037 /* Channel really does not exist */
5038 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5039 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5044 /* If the channel is private or secret do not send anything, unless the
5045 user requesting this command is on the channel. */
5046 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5047 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5048 && !silc_server_client_on_channel(cmd->sock->user_data, channel)) {
5049 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5050 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5055 (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
5056 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5057 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5062 /* Get the users list */
5063 silc_server_get_users_on_channel(server, channel, &client_id_list,
5064 &client_mode_list, &list_count);
5067 SILC_PUT32_MSB(list_count, lc);
5070 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5071 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5072 SILC_STATUS_OK, ident, 4,
5073 2, idp->data, idp->len,
5075 4, client_id_list->data,
5076 client_id_list->len,
5077 5, client_mode_list->data,
5078 client_mode_list->len);
5079 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5080 packet->data, packet->len, FALSE);
5082 silc_buffer_free(idp);
5083 silc_buffer_free(packet);
5084 silc_buffer_free(client_id_list);
5085 silc_buffer_free(client_mode_list);
5089 silc_server_command_free(cmd);
5092 /* Server side of command GETKEY. This fetches the client's public key
5093 from the server where to the client is connected. */
5095 SILC_SERVER_CMD_FUNC(getkey)
5097 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5098 SilcServer server = cmd->server;
5100 SilcClientEntry client;
5101 SilcServerEntry server_entry;
5102 SilcClientID *client_id = NULL;
5103 SilcServerID *server_id = NULL;
5104 SilcIDPayload idp = NULL;
5105 uint16 ident = silc_command_get_ident(cmd->payload);
5106 unsigned char *tmp, *pkdata;
5107 uint32 tmp_len, pklen;
5108 SilcBuffer pk = NULL;
5111 SILC_LOG_DEBUG(("Start"));
5113 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5115 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5116 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5119 idp = silc_id_payload_parse(tmp, tmp_len);
5121 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5122 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5126 id_type = silc_id_payload_get_type(idp);
5127 if (id_type == SILC_ID_CLIENT) {
5128 client_id = silc_id_payload_get_id(idp);
5130 /* If the client is not found from local list there is no chance it
5131 would be locally connected client so send the command further. */
5132 client = silc_idlist_find_client_by_id(server->local_list,
5133 client_id, TRUE, NULL);
5135 client = silc_idlist_find_client_by_id(server->global_list,
5136 client_id, TRUE, NULL);
5138 if ((!client && !cmd->pending && !server->standalone) ||
5139 (client && !client->connection && !cmd->pending) ||
5140 (client && !client->data.public_key && !cmd->pending)) {
5143 SilcSocketConnection dest_sock;
5145 dest_sock = silc_server_get_client_route(server, NULL, 0,
5150 old_ident = silc_command_get_ident(cmd->payload);
5151 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5152 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5154 silc_server_packet_send(server, dest_sock,
5155 SILC_PACKET_COMMAND, cmd->packet->flags,
5156 tmpbuf->data, tmpbuf->len, TRUE);
5158 /* Reprocess this packet after received reply from router */
5159 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5160 silc_command_get_ident(cmd->payload),
5161 silc_server_command_destructor,
5162 silc_server_command_getkey,
5163 silc_server_command_dup(cmd));
5164 cmd->pending = TRUE;
5166 silc_command_set_ident(cmd->payload, old_ident);
5167 silc_buffer_free(tmpbuf);
5172 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5173 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5177 /* The client is locally connected, just get the public key and
5178 send it back. If they key does not exist then do not send it,
5179 send just OK reply */
5180 if (!client->data.public_key) {
5184 tmp = silc_pkcs_public_key_encode(client->data.public_key, &tmp_len);
5185 pk = silc_buffer_alloc(4 + tmp_len);
5186 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5187 silc_buffer_format(pk,
5188 SILC_STR_UI_SHORT(tmp_len),
5189 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5190 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5196 } else if (id_type == SILC_ID_SERVER) {
5197 server_id = silc_id_payload_get_id(idp);
5199 /* If the server is not found from local list there is no chance it
5200 would be locally connected server so send the command further. */
5201 server_entry = silc_idlist_find_server_by_id(server->local_list,
5202 server_id, TRUE, NULL);
5204 server_entry = silc_idlist_find_server_by_id(server->global_list,
5205 server_id, TRUE, NULL);
5207 if (server_entry != server->id_entry &&
5208 ((!server_entry && !cmd->pending && !server->standalone) ||
5209 (server_entry && !server_entry->connection && !cmd->pending &&
5210 !server->standalone) ||
5211 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5212 !server->standalone))) {
5216 old_ident = silc_command_get_ident(cmd->payload);
5217 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5218 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5220 silc_server_packet_send(server, server->router->connection,
5221 SILC_PACKET_COMMAND, cmd->packet->flags,
5222 tmpbuf->data, tmpbuf->len, TRUE);
5224 /* Reprocess this packet after received reply from router */
5225 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5226 silc_command_get_ident(cmd->payload),
5227 silc_server_command_destructor,
5228 silc_server_command_getkey,
5229 silc_server_command_dup(cmd));
5230 cmd->pending = TRUE;
5232 silc_command_set_ident(cmd->payload, old_ident);
5233 silc_buffer_free(tmpbuf);
5237 if (!server_entry) {
5238 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5239 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5243 /* If they key does not exist then do not send it, send just OK reply */
5244 if (!server_entry->data.public_key) {
5248 tmp = silc_pkcs_public_key_encode(server_entry->data.public_key,
5250 pk = silc_buffer_alloc(4 + tmp_len);
5251 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5252 silc_buffer_format(pk,
5253 SILC_STR_UI_SHORT(tmp_len),
5254 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5255 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5265 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5266 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5267 SILC_STATUS_OK, ident,
5271 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5272 packet->data, packet->len, FALSE);
5273 silc_buffer_free(packet);
5276 silc_buffer_free(pk);
5280 silc_id_payload_free(idp);
5281 silc_free(client_id);
5282 silc_free(server_id);
5283 silc_server_command_free(cmd);