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);
2197 silc_free(lchannels);
2198 silc_free(gchannels);
2201 silc_server_command_free(cmd);
2204 /* Server side of TOPIC command. Sets topic for channel and/or returns
2205 current topic to client. */
2207 SILC_SERVER_CMD_FUNC(topic)
2209 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2210 SilcServer server = cmd->server;
2211 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2212 SilcChannelID *channel_id;
2213 SilcChannelEntry channel;
2214 SilcChannelClientEntry chl;
2215 SilcBuffer packet, idp;
2217 uint32 argc, tmp_len;
2218 uint16 ident = silc_command_get_ident(cmd->payload);
2220 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2222 argc = silc_argument_get_arg_num(cmd->args);
2224 /* Get Channel ID */
2225 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2227 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2228 SILC_STATUS_ERR_NO_CHANNEL_ID);
2231 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2233 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2234 SILC_STATUS_ERR_NO_CHANNEL_ID);
2238 /* Check whether the channel exists */
2239 channel = silc_idlist_find_channel_by_id(server->local_list,
2242 channel = silc_idlist_find_channel_by_id(server->global_list,
2245 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2246 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2253 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2255 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2256 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2260 if (strlen(tmp) > 256) {
2261 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2262 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2266 /* See whether the client is on channel and has rights to change topic */
2267 if (!silc_hash_table_find(channel->user_list, client, NULL,
2269 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2270 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2274 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2275 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2276 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2277 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2282 /* Set the topic for channel */
2283 silc_free(channel->topic);
2284 channel->topic = strdup(tmp);
2286 /* Send TOPIC_SET notify type to the network */
2287 if (!server->standalone)
2288 silc_server_send_notify_topic_set(server, server->router->connection,
2289 server->server_type == SILC_ROUTER ?
2290 TRUE : FALSE, channel, client->id,
2293 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2295 /* Send notify about topic change to all clients on the channel */
2296 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2297 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2298 idp->data, idp->len,
2299 channel->topic, strlen(channel->topic));
2300 silc_buffer_free(idp);
2303 /* Send the topic to client as reply packet */
2304 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2305 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2306 SILC_STATUS_OK, ident, 2,
2307 2, idp->data, idp->len,
2310 strlen(channel->topic) : 0);
2311 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2312 0, packet->data, packet->len, FALSE);
2314 silc_buffer_free(packet);
2315 silc_buffer_free(idp);
2316 silc_free(channel_id);
2319 silc_server_command_free(cmd);
2322 /* Server side of INVITE command. Invites some client to join some channel.
2323 This command is also used to manage the invite list of the channel. */
2325 SILC_SERVER_CMD_FUNC(invite)
2327 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2328 SilcServer server = cmd->server;
2329 SilcSocketConnection sock = cmd->sock, dest_sock;
2330 SilcChannelClientEntry chl;
2331 SilcClientEntry sender, dest;
2332 SilcClientID *dest_id = NULL;
2333 SilcChannelEntry channel;
2334 SilcChannelID *channel_id = NULL;
2335 SilcIDListData idata;
2336 SilcBuffer idp, idp2, packet;
2337 unsigned char *tmp, *add, *del;
2339 uint16 ident = silc_command_get_ident(cmd->payload);
2341 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2343 /* Get Channel ID */
2344 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2346 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2347 SILC_STATUS_ERR_NO_CHANNEL_ID);
2350 channel_id = silc_id_payload_parse_id(tmp, len);
2352 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2353 SILC_STATUS_ERR_NO_CHANNEL_ID);
2357 /* Get the channel entry */
2358 channel = silc_idlist_find_channel_by_id(server->local_list,
2361 channel = silc_idlist_find_channel_by_id(server->global_list,
2364 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2365 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2370 /* Check whether the sender of this command is on the channel. */
2371 sender = (SilcClientEntry)sock->user_data;
2372 if (!silc_server_client_on_channel(sender, channel)) {
2373 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2374 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2378 /* Check whether the channel is invite-only channel. If yes then the
2379 sender of this command must be at least channel operator. */
2380 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2381 silc_hash_table_find(channel->user_list, sender, NULL, (void *)&chl);
2382 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2383 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2384 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2389 /* Get destination client ID */
2390 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2394 dest_id = silc_id_payload_parse_id(tmp, len);
2396 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2397 SILC_STATUS_ERR_NO_CLIENT_ID);
2401 /* Get the client entry */
2402 dest = silc_server_get_client_resolve(server, dest_id);
2404 if (server->server_type != SILC_SERVER) {
2405 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2406 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2410 /* The client info is being resolved. Reprocess this packet after
2411 receiving the reply to the query. */
2412 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2414 silc_server_command_destructor,
2415 silc_server_command_invite,
2416 silc_server_command_dup(cmd));
2417 cmd->pending = TRUE;
2418 silc_free(channel_id);
2423 /* Check whether the requested client is already on the channel. */
2424 if (silc_server_client_on_channel(dest, channel)) {
2425 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2426 SILC_STATUS_ERR_USER_ON_CHANNEL);
2430 /* Get route to the client */
2431 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2433 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2434 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2438 memset(invite, 0, sizeof(invite));
2439 strncat(invite, dest->nickname, strlen(dest->nickname));
2440 strncat(invite, "!", 1);
2441 strncat(invite, dest->username, strlen(dest->username));
2442 if (!strchr(dest->username, '@')) {
2443 strncat(invite, "@", 1);
2444 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2447 len = strlen(invite);
2448 if (!channel->invite_list)
2449 channel->invite_list = silc_calloc(len + 2,
2450 sizeof(*channel->invite_list));
2452 channel->invite_list = silc_realloc(channel->invite_list,
2453 sizeof(*channel->invite_list) *
2455 strlen(channel->invite_list) + 2));
2456 strncat(channel->invite_list, invite, len);
2457 strncat(channel->invite_list, ",", 1);
2459 /* Send notify to the client that is invited to the channel */
2460 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2461 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2462 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2464 SILC_NOTIFY_TYPE_INVITE, 3,
2465 idp->data, idp->len,
2466 channel->channel_name,
2467 strlen(channel->channel_name),
2468 idp2->data, idp2->len);
2469 silc_buffer_free(idp);
2470 silc_buffer_free(idp2);
2473 /* Add the client to the invite list of the channel */
2474 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2476 if (!channel->invite_list)
2477 channel->invite_list = silc_calloc(len + 2,
2478 sizeof(*channel->invite_list));
2480 channel->invite_list = silc_realloc(channel->invite_list,
2481 sizeof(*channel->invite_list) *
2483 strlen(channel->invite_list) + 2));
2484 if (add[len - 1] == ',')
2485 add[len - 1] = '\0';
2487 strncat(channel->invite_list, add, len);
2488 strncat(channel->invite_list, ",", 1);
2491 /* Get the invite to be removed and remove it from the list */
2492 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2493 if (del && channel->invite_list) {
2494 char *start, *end, *n;
2496 if (!strncmp(channel->invite_list, del,
2497 strlen(channel->invite_list) - 1)) {
2498 silc_free(channel->invite_list);
2499 channel->invite_list = NULL;
2501 start = strstr(channel->invite_list, del);
2502 if (start && strlen(start) >= len) {
2504 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2505 strncat(n, channel->invite_list, start - channel->invite_list);
2506 strncat(n, end + 1, ((channel->invite_list +
2507 strlen(channel->invite_list)) - end) - 1);
2508 silc_free(channel->invite_list);
2509 channel->invite_list = n;
2514 /* Send notify to the primary router */
2515 if (!server->standalone)
2516 silc_server_send_notify_invite(server, server->router->connection,
2517 server->server_type == SILC_ROUTER ?
2518 TRUE : FALSE, channel,
2519 sender->id, add, del);
2521 /* Send command reply */
2522 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2526 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2527 SILC_STATUS_OK, ident, 2,
2529 3, channel->invite_list,
2530 channel->invite_list ?
2531 strlen(channel->invite_list) : 0);
2534 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2535 SILC_STATUS_OK, ident, 1,
2537 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2538 packet->data, packet->len, FALSE);
2539 silc_buffer_free(packet);
2543 silc_free(channel_id);
2544 silc_server_command_free(cmd);
2549 SilcSocketConnection sock;
2553 /* Quits connection to client. This gets called if client won't
2554 close the connection even when it has issued QUIT command. */
2556 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2558 QuitInternal q = (QuitInternal)context;
2560 /* Free all client specific data, such as client entry and entires
2561 on channels this client may be on. */
2562 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2564 q->sock->user_data = NULL;
2566 /* Close the connection on our side */
2567 silc_server_close_connection(q->server, q->sock);
2569 silc_free(q->signoff);
2573 /* Quits SILC session. This is the normal way to disconnect client. */
2575 SILC_SERVER_CMD_FUNC(quit)
2577 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2578 SilcServer server = cmd->server;
2579 SilcSocketConnection sock = cmd->sock;
2581 unsigned char *tmp = NULL;
2584 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2586 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2589 /* Get destination ID */
2590 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2594 q = silc_calloc(1, sizeof(*q));
2597 q->signoff = tmp ? strdup(tmp) : NULL;
2599 /* We quit the connection with little timeout */
2600 silc_schedule_task_add(server->schedule, sock->sock,
2601 silc_server_command_quit_cb, (void *)q,
2602 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2605 silc_server_command_free(cmd);
2608 /* Server side of command KILL. This command is used by router operator
2609 to remove an client from the SILC Network temporarily. */
2611 SILC_SERVER_CMD_FUNC(kill)
2613 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2614 SilcServer server = cmd->server;
2615 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2616 SilcClientEntry remote_client;
2617 SilcClientID *client_id;
2618 unsigned char *tmp, *comment;
2619 uint32 tmp_len, tmp_len2;
2621 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2623 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2626 /* KILL command works only on router */
2627 if (server->server_type != SILC_ROUTER) {
2628 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2629 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2633 /* Check whether client has the permissions. */
2634 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2635 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2636 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2640 /* Get the client ID */
2641 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2643 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2644 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2647 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2649 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2650 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2654 /* Get the client entry */
2655 remote_client = silc_idlist_find_client_by_id(server->local_list,
2656 client_id, TRUE, NULL);
2657 if (!remote_client) {
2658 remote_client = silc_idlist_find_client_by_id(server->global_list,
2659 client_id, TRUE, NULL);
2660 if (!remote_client) {
2661 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2662 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2668 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2672 /* Send reply to the sender */
2673 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2676 /* Send the KILL notify packets. First send it to the channel, then
2677 to our primary router and then directly to the client who is being
2678 killed right now. */
2680 /* Send KILLED notify to the channels. It is not sent to the client
2681 as it will be sent differently destined directly to the client and not
2683 silc_server_send_notify_on_channels(server, remote_client,
2684 remote_client, SILC_NOTIFY_TYPE_KILLED,
2687 comment, comment ? tmp_len2 : 0);
2689 /* Send KILLED notify to primary route */
2690 if (!server->standalone)
2691 silc_server_send_notify_killed(server, server->router->connection, TRUE,
2692 remote_client->id, comment);
2694 /* Send KILLED notify to the client directly */
2695 silc_server_send_notify_killed(server, remote_client->connection ?
2696 remote_client->connection :
2697 remote_client->router->connection, FALSE,
2698 remote_client->id, comment);
2700 /* Remove the client from all channels. This generates new keys to the
2701 channels as well. */
2702 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2705 /* Remove the client entry, If it is locally connected then we will also
2706 disconnect the client here */
2707 if (remote_client->connection) {
2708 /* Remove locally conneted client */
2709 SilcSocketConnection sock = remote_client->connection;
2710 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2711 silc_server_close_connection(server, sock);
2713 /* Remove remote client */
2714 if (!silc_idlist_del_client(server->global_list, remote_client))
2715 silc_idlist_del_client(server->local_list, remote_client);
2719 silc_server_command_free(cmd);
2722 /* Server side of command INFO. This sends information about us to
2723 the client. If client requested specific server we will send the
2724 command to that server. */
2726 SILC_SERVER_CMD_FUNC(info)
2728 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2729 SilcServer server = cmd->server;
2730 SilcBuffer packet, idp;
2733 char *dest_server, *server_info = NULL, *server_name;
2734 uint16 ident = silc_command_get_ident(cmd->payload);
2735 SilcServerEntry entry = NULL;
2736 SilcServerID *server_id = NULL;
2738 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2740 /* Get server name */
2741 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2744 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2746 server_id = silc_id_payload_parse_id(tmp, tmp_len);
2748 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2749 SILC_STATUS_ERR_NO_SERVER_ID);
2755 /* Check whether we have this server cached */
2756 entry = silc_idlist_find_server_by_id(server->local_list,
2757 server_id, TRUE, NULL);
2759 entry = silc_idlist_find_server_by_id(server->global_list,
2760 server_id, TRUE, NULL);
2761 if (!entry && server->server_type != SILC_SERVER) {
2762 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2763 SILC_STATUS_ERR_NO_SUCH_SERVER);
2769 /* Some buggy servers has sent request to router about themselves. */
2770 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2773 if ((!dest_server && !server_id && !entry) || (entry &&
2774 entry == server->id_entry) ||
2775 (dest_server && !cmd->pending &&
2776 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2777 /* Send our reply */
2778 char info_string[256];
2780 memset(info_string, 0, sizeof(info_string));
2781 snprintf(info_string, sizeof(info_string),
2782 "location: %s server: %s admin: %s <%s>",
2783 server->config->admin_info->location,
2784 server->config->admin_info->server_type,
2785 server->config->admin_info->admin_name,
2786 server->config->admin_info->admin_email);
2788 server_info = info_string;
2789 entry = server->id_entry;
2791 /* Check whether we have this server cached */
2792 if (!entry && dest_server) {
2793 entry = silc_idlist_find_server_by_name(server->global_list,
2794 dest_server, TRUE, NULL);
2796 entry = silc_idlist_find_server_by_name(server->local_list,
2797 dest_server, TRUE, NULL);
2801 if (!cmd->pending &&
2802 server->server_type != SILC_SERVER && entry && !entry->server_info) {
2803 /* Send to the server */
2807 old_ident = silc_command_get_ident(cmd->payload);
2808 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2809 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2811 silc_server_packet_send(server, entry->connection,
2812 SILC_PACKET_COMMAND, cmd->packet->flags,
2813 tmpbuf->data, tmpbuf->len, TRUE);
2815 /* Reprocess this packet after received reply from router */
2816 silc_server_command_pending(server, SILC_COMMAND_INFO,
2817 silc_command_get_ident(cmd->payload),
2818 silc_server_command_destructor,
2819 silc_server_command_info,
2820 silc_server_command_dup(cmd));
2821 cmd->pending = TRUE;
2822 silc_command_set_ident(cmd->payload, old_ident);
2823 silc_buffer_free(tmpbuf);
2827 if (!entry && !cmd->pending && !server->standalone) {
2828 /* Send to the primary router */
2832 old_ident = silc_command_get_ident(cmd->payload);
2833 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2834 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2836 silc_server_packet_send(server, server->router->connection,
2837 SILC_PACKET_COMMAND, cmd->packet->flags,
2838 tmpbuf->data, tmpbuf->len, TRUE);
2840 /* Reprocess this packet after received reply from router */
2841 silc_server_command_pending(server, SILC_COMMAND_INFO,
2842 silc_command_get_ident(cmd->payload),
2843 silc_server_command_destructor,
2844 silc_server_command_info,
2845 silc_server_command_dup(cmd));
2846 cmd->pending = TRUE;
2847 silc_command_set_ident(cmd->payload, old_ident);
2848 silc_buffer_free(tmpbuf);
2853 silc_free(server_id);
2856 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2857 SILC_STATUS_ERR_NO_SUCH_SERVER);
2861 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2863 server_info = entry->server_info;
2864 server_name = entry->server_name;
2866 /* Send the reply */
2867 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2868 SILC_STATUS_OK, ident, 3,
2869 2, idp->data, idp->len,
2871 strlen(server_name),
2874 strlen(server_info) : 0);
2875 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2876 packet->data, packet->len, FALSE);
2878 silc_buffer_free(packet);
2879 silc_buffer_free(idp);
2882 silc_server_command_free(cmd);
2885 /* Server side of command PING. This just replies to the ping. */
2887 SILC_SERVER_CMD_FUNC(ping)
2889 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2890 SilcServer server = cmd->server;
2895 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
2898 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2900 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2901 SILC_STATUS_ERR_NO_SERVER_ID);
2904 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2908 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2909 /* Send our reply */
2910 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2913 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2914 SILC_STATUS_ERR_NO_SUCH_SERVER);
2921 silc_server_command_free(cmd);
2924 /* Internal routine to join channel. The channel sent to this function
2925 has been either created or resolved from ID lists. This joins the sent
2926 client to the channel. */
2928 static void silc_server_command_join_channel(SilcServer server,
2929 SilcServerCommandContext cmd,
2930 SilcChannelEntry channel,
2931 SilcClientID *client_id,
2936 SilcSocketConnection sock = cmd->sock;
2938 uint32 tmp_len, user_count;
2939 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
2940 SilcClientEntry client;
2941 SilcChannelClientEntry chl;
2942 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
2943 uint16 ident = silc_command_get_ident(cmd->payload);
2944 char check[512], check2[512];
2946 SILC_LOG_DEBUG(("Start"));
2951 /* Get the client entry */
2952 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2953 client = (SilcClientEntry)sock->user_data;
2955 client = silc_server_get_client_resolve(server, client_id);
2960 /* The client info is being resolved. Reprocess this packet after
2961 receiving the reply to the query. */
2962 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2963 server->cmd_ident, NULL,
2964 silc_server_command_join,
2965 silc_server_command_dup(cmd));
2966 cmd->pending = TRUE;
2970 cmd->pending = FALSE;
2974 * Check channel modes
2977 memset(check, 0, sizeof(check));
2978 memset(check2, 0, sizeof(check2));
2979 strncat(check, client->nickname, strlen(client->nickname));
2980 strncat(check, "!", 1);
2981 strncat(check, client->username, strlen(client->username));
2982 if (!strchr(client->username, '@')) {
2983 strncat(check, "@", 1);
2984 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
2987 strncat(check2, client->nickname, strlen(client->nickname));
2988 if (!strchr(client->nickname, '@')) {
2989 strncat(check2, "@", 1);
2990 strncat(check2, server->server_name, strlen(server->server_name));
2992 strncat(check2, "!", 1);
2993 strncat(check2, client->username, strlen(client->username));
2994 if (!strchr(client->username, '@')) {
2995 strncat(check2, "@", 1);
2996 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
2999 /* Check invite list if channel is invite-only channel */
3000 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3001 if (!channel->invite_list ||
3002 (!silc_string_match(channel->invite_list, check) &&
3003 !silc_string_match(channel->invite_list, check2))) {
3004 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3005 SILC_STATUS_ERR_NOT_INVITED);
3010 /* Check ban list if it exists. If the client's nickname, server,
3011 username and/or hostname is in the ban list the access to the
3012 channel is denied. */
3013 if (channel->ban_list) {
3014 if (!channel->ban_list ||
3015 silc_string_match(channel->ban_list, check) ||
3016 silc_string_match(channel->ban_list, check2)) {
3017 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3018 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
3023 /* Get passphrase */
3024 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3026 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
3027 memcpy(passphrase, tmp, tmp_len);
3030 /* Check the channel passphrase if set. */
3031 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3032 if (!passphrase || !channel->passphrase ||
3033 memcmp(channel->passphrase, passphrase,
3034 strlen(channel->passphrase))) {
3035 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3036 SILC_STATUS_ERR_BAD_PASSWORD);
3041 /* Check user count limit if set. */
3042 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3043 if (silc_hash_table_count(channel->user_list) + 1 >
3044 channel->user_limit) {
3045 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3046 SILC_STATUS_ERR_CHANNEL_IS_FULL);
3052 * Client is allowed to join to the channel. Make it happen.
3055 /* Check whether the client already is on the channel */
3056 if (silc_server_client_on_channel(client, channel)) {
3057 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3058 SILC_STATUS_ERR_USER_ON_CHANNEL);
3062 /* Generate new channel key as protocol dictates */
3064 if (!silc_server_create_channel_key(server, channel, 0))
3067 /* Send the channel key. This is broadcasted to the channel but is not
3068 sent to the client who is joining to the channel. */
3069 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3070 silc_server_send_channel_key(server, NULL, channel,
3071 server->server_type == SILC_ROUTER ?
3072 FALSE : !server->standalone);
3075 /* Join the client to the channel by adding it to channel's user list.
3076 Add also the channel to client entry's channels list for fast cross-
3078 chl = silc_calloc(1, sizeof(*chl));
3080 chl->client = client;
3081 chl->channel = channel;
3082 silc_hash_table_add(channel->user_list, client, chl);
3083 silc_hash_table_add(client->channels, channel, chl);
3085 /* Get users on the channel */
3086 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3089 /* Encode Client ID Payload of the original client who wants to join */
3090 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3092 /* Encode command reply packet */
3093 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3094 SILC_PUT32_MSB(channel->mode, mode);
3095 SILC_PUT32_MSB(created, tmp2);
3096 SILC_PUT32_MSB(user_count, tmp3);
3098 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3099 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3100 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
3101 strlen(channel->channel_key->
3103 channel->channel_key->cipher->name,
3104 channel->key_len / 8, channel->key);
3109 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3110 SILC_STATUS_OK, ident, 13,
3111 2, channel->channel_name,
3112 strlen(channel->channel_name),
3113 3, chidp->data, chidp->len,
3114 4, clidp->data, clidp->len,
3117 7, keyp ? keyp->data : NULL,
3118 keyp ? keyp->len : 0,
3119 8, channel->ban_list,
3121 strlen(channel->ban_list) : 0,
3122 9, channel->invite_list,
3123 channel->invite_list ?
3124 strlen(channel->invite_list) : 0,
3127 strlen(channel->topic) : 0,
3128 11, silc_hmac_get_name(channel->hmac),
3129 strlen(silc_hmac_get_name(channel->
3132 13, user_list->data, user_list->len,
3133 14, mode_list->data,
3136 /* Send command reply */
3137 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3138 reply->data, reply->len, FALSE);
3140 /* Send JOIN notify to locally connected clients on the channel. If
3141 we are normal server then router will send or have sent JOIN notify
3142 already. However since we've added the client already to our channel
3143 we'll ignore it (in packet_receive.c) so we must send it here. If
3144 we are router then this will send it to local clients and local
3146 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3147 SILC_NOTIFY_TYPE_JOIN, 2,
3148 clidp->data, clidp->len,
3149 chidp->data, chidp->len);
3151 if (!cmd->pending) {
3152 /* Send JOIN notify packet to our primary router */
3153 if (!server->standalone)
3154 silc_server_send_notify_join(server, server->router->connection,
3155 server->server_type == SILC_ROUTER ?
3156 TRUE : FALSE, channel, client->id);
3159 /* Distribute the channel key to all backup routers. */
3160 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3161 keyp->data, keyp->len, FALSE, TRUE);
3164 silc_buffer_free(reply);
3165 silc_buffer_free(clidp);
3166 silc_buffer_free(chidp);
3167 silc_buffer_free(keyp);
3168 silc_buffer_free(user_list);
3169 silc_buffer_free(mode_list);
3172 silc_free(passphrase);
3175 /* Server side of command JOIN. Joins client into requested channel. If
3176 the channel does not exist it will be created. */
3178 SILC_SERVER_CMD_FUNC(join)
3180 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3181 SilcServer server = cmd->server;
3183 char *tmp, *channel_name = NULL, *cipher, *hmac;
3184 SilcChannelEntry channel;
3186 bool created = FALSE, create_key = TRUE;
3187 SilcClientID *client_id;
3189 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 1, 4);
3191 /* Get channel name */
3192 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3194 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3195 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3200 if (strlen(channel_name) > 256)
3201 channel_name[255] = '\0';
3203 if (silc_server_command_bad_chars(channel_name) == TRUE) {
3204 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3205 SILC_STATUS_ERR_BAD_CHANNEL);
3209 /* Get Client ID of the client who is joining to the channel */
3210 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3212 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3213 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3216 client_id = silc_id_payload_parse_id(tmp, tmp_len);
3218 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3219 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3223 /* Get cipher and hmac name */
3224 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3225 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3227 /* See if the channel exists */
3228 channel = silc_idlist_find_channel_by_name(server->local_list,
3229 channel_name, NULL);
3231 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3232 /* If this is coming from client the Client ID in the command packet must
3233 be same as the client's ID. */
3234 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3235 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3236 if (!SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
3237 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3238 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3243 if (!channel || channel->disabled) {
3244 /* Channel not found */
3246 /* If we are standalone server we don't have a router, we just create
3247 the channel by ourselves. */
3248 if (server->standalone) {
3249 channel = silc_server_create_new_channel(server, server->id, cipher,
3250 hmac, channel_name, TRUE);
3252 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3253 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3257 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3263 /* The channel does not exist on our server. If we are normal server
3264 we will send JOIN command to our router which will handle the
3265 joining procedure (either creates the channel if it doesn't exist
3266 or joins the client to it). */
3267 if (server->server_type != SILC_ROUTER) {
3271 /* If this is pending command callback then we've resolved
3272 it and it didn't work, return since we've notified the
3273 client already in the command reply callback. */
3277 old_ident = silc_command_get_ident(cmd->payload);
3278 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3279 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3281 /* Send JOIN command to our router */
3282 silc_server_packet_send(server, (SilcSocketConnection)
3283 server->router->connection,
3284 SILC_PACKET_COMMAND, cmd->packet->flags,
3285 tmpbuf->data, tmpbuf->len, TRUE);
3287 /* Reprocess this packet after received reply from router */
3288 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3289 silc_command_get_ident(cmd->payload),
3290 silc_server_command_destructor,
3291 silc_server_command_join,
3292 silc_server_command_dup(cmd));
3293 cmd->pending = TRUE;
3297 /* We are router and the channel does not seem exist so we will check
3298 our global list as well for the channel. */
3299 channel = silc_idlist_find_channel_by_name(server->global_list,
3300 channel_name, NULL);
3302 /* Channel really does not exist, create it */
3303 channel = silc_server_create_new_channel(server, server->id, cipher,
3304 hmac, channel_name, TRUE);
3306 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3307 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3311 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3319 /* Channel not found */
3321 /* If the command came from router and we are normal server then
3322 something went wrong with the joining as the channel was not found.
3323 We can't do anything else but ignore this. */
3324 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3325 server->server_type != SILC_ROUTER)
3328 /* We are router and the channel does not seem exist so we will check
3329 our global list as well for the channel. */
3330 channel = silc_idlist_find_channel_by_name(server->global_list,
3331 channel_name, NULL);
3333 /* Channel really does not exist, create it */
3334 channel = silc_server_create_new_channel(server, server->id, cipher,
3335 hmac, channel_name, TRUE);
3337 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3338 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3342 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3349 /* Check whether the channel was created by our router */
3350 if (cmd->pending && context2) {
3351 SilcServerCommandReplyContext reply =
3352 (SilcServerCommandReplyContext)context2;
3353 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3354 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3355 SILC_GET32_MSB(created, tmp);
3356 create_key = FALSE; /* Router returned the key already */
3360 /* If the channel does not have global users and is also empty the client
3361 will be the channel founder and operator. */
3362 if (!channel->global_users && !silc_hash_table_count(channel->user_list))
3363 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3365 /* Join to the channel */
3366 silc_server_command_join_channel(server, cmd, channel, client_id,
3367 created, create_key, umode);
3369 silc_free(client_id);
3372 silc_server_command_free(cmd);
3375 /* Server side of command MOTD. Sends server's current "message of the
3376 day" to the client. */
3378 SILC_SERVER_CMD_FUNC(motd)
3380 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3381 SilcServer server = cmd->server;
3382 SilcBuffer packet, idp;
3383 char *motd, *dest_server;
3385 uint16 ident = silc_command_get_ident(cmd->payload);
3387 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3389 /* Get server name */
3390 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3392 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3393 SILC_STATUS_ERR_NO_SUCH_SERVER);
3397 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3400 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3402 if (server->config && server->config->motd &&
3403 server->config->motd->motd_file) {
3405 motd = silc_file_readfile(server->config->motd->motd_file, &motd_len);
3410 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3411 SILC_STATUS_OK, ident, 2,
3416 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3417 SILC_STATUS_OK, ident, 1,
3421 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3422 packet->data, packet->len, FALSE);
3423 silc_buffer_free(packet);
3424 silc_buffer_free(idp);
3426 SilcServerEntry entry;
3428 /* Check whether we have this server cached */
3429 entry = silc_idlist_find_server_by_name(server->global_list,
3430 dest_server, TRUE, NULL);
3432 entry = silc_idlist_find_server_by_name(server->local_list,
3433 dest_server, TRUE, NULL);
3436 if (server->server_type != SILC_SERVER && !cmd->pending &&
3437 entry && !entry->motd) {
3438 /* Send to the server */
3442 old_ident = silc_command_get_ident(cmd->payload);
3443 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3444 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3446 silc_server_packet_send(server, entry->connection,
3447 SILC_PACKET_COMMAND, cmd->packet->flags,
3448 tmpbuf->data, tmpbuf->len, TRUE);
3450 /* Reprocess this packet after received reply from router */
3451 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3452 silc_command_get_ident(cmd->payload),
3453 silc_server_command_destructor,
3454 silc_server_command_motd,
3455 silc_server_command_dup(cmd));
3456 cmd->pending = TRUE;
3457 silc_command_set_ident(cmd->payload, old_ident);
3458 silc_buffer_free(tmpbuf);
3462 if (!entry && !cmd->pending && !server->standalone) {
3463 /* Send to the primary router */
3467 old_ident = silc_command_get_ident(cmd->payload);
3468 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3469 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3471 silc_server_packet_send(server, server->router->connection,
3472 SILC_PACKET_COMMAND, cmd->packet->flags,
3473 tmpbuf->data, tmpbuf->len, TRUE);
3475 /* Reprocess this packet after received reply from router */
3476 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3477 silc_command_get_ident(cmd->payload),
3478 silc_server_command_destructor,
3479 silc_server_command_motd,
3480 silc_server_command_dup(cmd));
3481 cmd->pending = TRUE;
3482 silc_command_set_ident(cmd->payload, old_ident);
3483 silc_buffer_free(tmpbuf);
3488 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3489 SILC_STATUS_ERR_NO_SUCH_SERVER);
3493 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3494 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3495 SILC_STATUS_OK, ident, 2,
3499 strlen(entry->motd) : 0);
3500 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3501 packet->data, packet->len, FALSE);
3502 silc_buffer_free(packet);
3503 silc_buffer_free(idp);
3507 silc_server_command_free(cmd);
3510 /* Server side of command UMODE. Client can use this command to set/unset
3511 user mode. Client actually cannot set itself to be as server/router
3512 operator so this can be used only to unset the modes. */
3514 SILC_SERVER_CMD_FUNC(umode)
3516 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3517 SilcServer server = cmd->server;
3518 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3520 unsigned char *tmp_mask;
3522 uint16 ident = silc_command_get_ident(cmd->payload);
3524 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3527 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 2, 2);
3529 /* Get the client's mode mask */
3530 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3532 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3533 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3536 SILC_GET32_MSB(mask, tmp_mask);
3542 if (mask & SILC_UMODE_SERVER_OPERATOR) {
3543 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR)) {
3544 /* Cannot operator mode */
3545 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3546 SILC_STATUS_ERR_PERM_DENIED);
3550 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
3551 /* Remove the server operator rights */
3552 client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3555 if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3556 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
3557 /* Cannot operator mode */
3558 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3559 SILC_STATUS_ERR_PERM_DENIED);
3563 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
3564 /* Remove the router operator rights */
3565 client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3568 if (mask & SILC_UMODE_GONE) {
3569 client->mode |= SILC_UMODE_GONE;
3571 if (client->mode & SILC_UMODE_GONE)
3572 /* Remove the gone status */
3573 client->mode &= ~SILC_UMODE_GONE;
3576 /* Send UMODE change to primary router */
3577 if (!server->standalone)
3578 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3579 client->id, client->mode);
3581 /* Send command reply to sender */
3582 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3583 SILC_STATUS_OK, ident, 1,
3585 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3586 packet->data, packet->len, FALSE);
3587 silc_buffer_free(packet);
3590 silc_server_command_free(cmd);
3593 /* Checks that client has rights to add or remove channel modes. If any
3594 of the checks fails FALSE is returned. */
3596 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3597 SilcChannelClientEntry client,
3600 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3601 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3603 /* Check whether has rights to change anything */
3604 if (!is_op && !is_fo)
3607 /* Check whether has rights to change everything */
3611 /* We know that client is channel operator, check that they are not
3612 changing anything that requires channel founder rights. Rest of the
3613 modes are available automatically for channel operator. */
3615 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3616 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3617 if (is_op && !is_fo)
3620 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3621 if (is_op && !is_fo)
3626 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3627 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE))
3628 if (is_op && !is_fo)
3631 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3632 if (is_op && !is_fo)
3637 if (mode & SILC_CHANNEL_MODE_CIPHER) {
3638 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER))
3639 if (is_op && !is_fo)
3642 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3643 if (is_op && !is_fo)
3648 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3649 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH))
3650 if (is_op && !is_fo)
3653 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3654 if (is_op && !is_fo)
3662 /* Server side command of CMODE. Changes channel mode */
3664 SILC_SERVER_CMD_FUNC(cmode)
3666 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3667 SilcServer server = cmd->server;
3668 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3669 SilcIDListData idata = (SilcIDListData)client;
3670 SilcChannelID *channel_id;
3671 SilcChannelEntry channel;
3672 SilcChannelClientEntry chl;
3673 SilcBuffer packet, cidp;
3674 unsigned char *tmp, *tmp_id, *tmp_mask;
3675 char *cipher = NULL, *hmac = NULL;
3676 uint32 mode_mask, tmp_len, tmp_len2;
3677 uint16 ident = silc_command_get_ident(cmd->payload);
3679 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 2, 7);
3681 /* Get Channel ID */
3682 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3684 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3685 SILC_STATUS_ERR_NO_CHANNEL_ID);
3688 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3690 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3691 SILC_STATUS_ERR_NO_CHANNEL_ID);
3695 /* Get the channel mode mask */
3696 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3698 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3699 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3702 SILC_GET32_MSB(mode_mask, tmp_mask);
3704 /* Get channel entry */
3705 channel = silc_idlist_find_channel_by_id(server->local_list,
3708 channel = silc_idlist_find_channel_by_id(server->global_list,
3711 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3712 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3717 /* Check whether this client is on the channel */
3718 if (!silc_server_client_on_channel(client, channel)) {
3719 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3720 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3724 /* Get entry to the channel user list */
3725 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
3727 /* Check that client has rights to change any requested channel modes */
3728 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3729 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3730 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3735 * Check the modes. Modes that requires nothing special operation are
3739 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3740 /* Channel uses private keys to protect traffic. Client(s) has set the
3741 key locally they want to use, server does not know that key. */
3742 /* Nothing interesting to do here */
3744 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3745 /* The mode is removed and we need to generate and distribute
3746 new channel key. Clients are not using private channel keys
3747 anymore after this. */
3749 /* Re-generate channel key */
3750 if (!silc_server_create_channel_key(server, channel, 0))
3753 /* Send the channel key. This sends it to our local clients and if
3754 we are normal server to our router as well. */
3755 silc_server_send_channel_key(server, NULL, channel,
3756 server->server_type == SILC_ROUTER ?
3757 FALSE : !server->standalone);
3759 cipher = channel->channel_key->cipher->name;
3760 hmac = (char *)silc_hmac_get_name(channel->hmac);
3764 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3765 /* User limit is set on channel */
3768 /* Get user limit */
3769 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3771 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3772 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3773 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3777 SILC_GET32_MSB(user_limit, tmp);
3778 channel->user_limit = user_limit;
3781 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3782 /* User limit mode is unset. Remove user limit */
3783 channel->user_limit = 0;
3786 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3787 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3788 /* Passphrase has been set to channel */
3790 /* Get the passphrase */
3791 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3793 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3794 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3798 /* Save the passphrase */
3799 channel->passphrase = strdup(tmp);
3802 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3803 /* Passphrase mode is unset. remove the passphrase */
3804 if (channel->passphrase) {
3805 silc_free(channel->passphrase);
3806 channel->passphrase = NULL;
3811 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3812 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3813 /* Cipher to use protect the traffic */
3814 SilcCipher newkey, oldkey;
3817 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3819 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3820 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3824 /* Delete old cipher and allocate the new one */
3825 if (!silc_cipher_alloc(cipher, &newkey)) {
3826 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3827 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3831 oldkey = channel->channel_key;
3832 channel->channel_key = newkey;
3834 /* Re-generate channel key */
3835 if (!silc_server_create_channel_key(server, channel, 0)) {
3836 /* We don't have new key, revert to old one */
3837 channel->channel_key = oldkey;
3841 /* Remove old channel key for good */
3842 silc_cipher_free(oldkey);
3844 /* Send the channel key. This sends it to our local clients and if
3845 we are normal server to our router as well. */
3846 silc_server_send_channel_key(server, NULL, channel,
3847 server->server_type == SILC_ROUTER ?
3848 FALSE : !server->standalone);
3851 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3852 /* Cipher mode is unset. Remove the cipher and revert back to
3854 SilcCipher newkey, oldkey;
3855 cipher = channel->cipher;
3857 /* Delete old cipher and allocate default one */
3858 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
3859 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3860 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3864 oldkey = channel->channel_key;
3865 channel->channel_key = newkey;
3867 /* Re-generate channel key */
3868 if (!silc_server_create_channel_key(server, channel, 0)) {
3869 /* We don't have new key, revert to old one */
3870 channel->channel_key = oldkey;
3874 /* Remove old channel key for good */
3875 silc_cipher_free(oldkey);
3877 /* Send the channel key. This sends it to our local clients and if
3878 we are normal server to our router as well. */
3879 silc_server_send_channel_key(server, NULL, channel,
3880 server->server_type == SILC_ROUTER ?
3881 FALSE : !server->standalone);
3885 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3886 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3887 /* HMAC to use protect the traffic */
3888 unsigned char hash[32];
3892 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3894 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3895 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3899 /* Delete old hmac and allocate the new one */
3900 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
3901 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3902 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3906 silc_hmac_free(channel->hmac);
3907 channel->hmac = newhmac;
3909 /* Set the HMAC key out of current channel key. The client must do
3911 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
3912 channel->key_len / 8, hash);
3913 silc_hmac_set_key(channel->hmac, hash,
3914 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3915 memset(hash, 0, sizeof(hash));
3918 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
3919 /* Hmac mode is unset. Remove the hmac and revert back to
3922 unsigned char hash[32];
3923 hmac = channel->hmac_name;
3925 /* Delete old hmac and allocate default one */
3926 silc_hmac_free(channel->hmac);
3927 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
3928 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3929 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3933 silc_hmac_free(channel->hmac);
3934 channel->hmac = newhmac;
3936 /* Set the HMAC key out of current channel key. The client must do
3938 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
3939 channel->key_len / 8,
3941 silc_hmac_set_key(channel->hmac, hash,
3942 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3943 memset(hash, 0, sizeof(hash));
3947 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3948 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3949 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
3950 /* Set the founder authentication */
3951 SilcAuthPayload auth;
3953 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
3955 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3956 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3960 auth = silc_auth_payload_parse(tmp, tmp_len);
3962 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3963 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3967 /* Save the public key */
3968 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
3969 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
3972 channel->founder_method = silc_auth_get_method(auth);
3974 if (channel->founder_method == SILC_AUTH_PASSWORD) {
3975 tmp = silc_auth_get_data(auth, &tmp_len);
3976 channel->founder_passwd =
3977 silc_calloc(tmp_len + 1, sizeof(*channel->founder_passwd));
3978 memcpy(channel->founder_passwd, tmp, tmp_len);
3979 channel->founder_passwd_len = tmp_len;
3981 /* Verify the payload before setting the mode */
3982 if (!silc_auth_verify(auth, channel->founder_method,
3983 channel->founder_key, 0, idata->hash,
3984 client->id, SILC_ID_CLIENT)) {
3985 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3986 SILC_STATUS_ERR_AUTH_FAILED);
3991 silc_auth_payload_free(auth);
3995 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3996 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3997 if (channel->founder_key)
3998 silc_pkcs_public_key_free(channel->founder_key);
3999 if (channel->founder_passwd) {
4000 silc_free(channel->founder_passwd);
4001 channel->founder_passwd = NULL;
4007 /* Finally, set the mode */
4008 channel->mode = mode_mask;
4010 /* Send CMODE_CHANGE notify */
4011 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4012 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4013 SILC_NOTIFY_TYPE_CMODE_CHANGE, 4,
4014 cidp->data, cidp->len,
4016 cipher, cipher ? strlen(cipher) : 0,
4017 hmac, hmac ? strlen(hmac) : 0);
4019 /* Set CMODE notify type to network */
4020 if (!server->standalone)
4021 silc_server_send_notify_cmode(server, server->router->connection,
4022 server->server_type == SILC_ROUTER ?
4023 TRUE : FALSE, channel,
4024 mode_mask, client->id, SILC_ID_CLIENT,
4027 /* Send command reply to sender */
4028 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4029 SILC_STATUS_OK, ident, 2,
4030 2, tmp_id, tmp_len2,
4032 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4033 packet->data, packet->len, FALSE);
4035 silc_buffer_free(packet);
4036 silc_free(channel_id);
4037 silc_buffer_free(cidp);
4040 silc_server_command_free(cmd);
4043 /* Server side of CUMODE command. Changes client's mode on a channel. */
4045 SILC_SERVER_CMD_FUNC(cumode)
4047 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4048 SilcServer server = cmd->server;
4049 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4050 SilcIDListData idata = (SilcIDListData)client;
4051 SilcChannelID *channel_id;
4052 SilcClientID *client_id;
4053 SilcChannelEntry channel;
4054 SilcClientEntry target_client;
4055 SilcChannelClientEntry chl;
4056 SilcBuffer packet, idp;
4057 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4058 uint32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4060 uint16 ident = silc_command_get_ident(cmd->payload);
4062 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4064 /* Get Channel ID */
4065 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4067 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4068 SILC_STATUS_ERR_NO_CHANNEL_ID);
4071 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
4073 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4074 SILC_STATUS_ERR_NO_CHANNEL_ID);
4078 /* Get channel entry */
4079 channel = silc_idlist_find_channel_by_id(server->local_list,
4082 channel = silc_idlist_find_channel_by_id(server->global_list,
4085 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4086 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4091 /* Check whether sender is on the channel */
4092 if (!silc_server_client_on_channel(client, channel)) {
4093 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4094 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4098 /* Check that client has rights to change other's rights */
4099 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4100 sender_mask = chl->mode;
4102 /* Get the target client's channel mode mask */
4103 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4105 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4106 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4109 SILC_GET32_MSB(target_mask, tmp_mask);
4111 /* Get target Client ID */
4112 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4114 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4115 SILC_STATUS_ERR_NO_CLIENT_ID);
4118 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
4120 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4121 SILC_STATUS_ERR_NO_CLIENT_ID);
4125 /* Get target client's entry */
4126 target_client = silc_idlist_find_client_by_id(server->local_list,
4127 client_id, TRUE, NULL);
4128 if (!target_client) {
4129 target_client = silc_idlist_find_client_by_id(server->global_list,
4130 client_id, TRUE, NULL);
4133 if (target_client != client &&
4134 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4135 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4136 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4137 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4141 /* Check whether target client is on the channel */
4142 if (target_client != client) {
4143 if (!silc_server_client_on_channel(target_client, channel)) {
4144 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4145 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4149 /* Get entry to the channel user list */
4150 silc_hash_table_find(channel->user_list, target_client, NULL,
4158 /* If the target client is founder, no one else can change their mode
4160 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
4161 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4162 SILC_STATUS_ERR_NOT_YOU);
4166 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4167 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4168 /* The client tries to claim the founder rights. */
4169 unsigned char *tmp_auth;
4170 uint32 tmp_auth_len, auth_len;
4173 if (target_client != client) {
4174 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4175 SILC_STATUS_ERR_NOT_YOU);
4179 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4180 !channel->founder_key || !idata->public_key ||
4181 !silc_pkcs_public_key_compare(channel->founder_key,
4182 idata->public_key)) {
4183 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4184 SILC_STATUS_ERR_NOT_YOU);
4188 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4190 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4191 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4195 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4196 (void *)channel->founder_passwd : (void *)channel->founder_key);
4197 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4198 channel->founder_passwd_len : 0);
4200 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4201 channel->founder_method, auth, auth_len,
4202 idata->hash, client->id, SILC_ID_CLIENT)) {
4203 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4204 SILC_STATUS_ERR_AUTH_FAILED);
4208 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4212 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4213 if (target_client == client) {
4214 /* Remove channel founder rights from itself */
4215 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4218 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4219 SILC_STATUS_ERR_NOT_YOU);
4225 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4226 /* Promote to operator */
4227 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4228 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4229 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4230 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4231 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4235 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4239 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4240 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4241 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4242 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4243 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4247 /* Demote to normal user */
4248 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4253 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4254 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4256 /* Send notify to channel, notify only if mode was actually changed. */
4258 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4259 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4260 idp->data, idp->len,
4264 /* Set CUMODE notify type to network */
4265 if (!server->standalone)
4266 silc_server_send_notify_cumode(server, server->router->connection,
4267 server->server_type == SILC_ROUTER ?
4268 TRUE : FALSE, channel,
4269 target_mask, client->id,
4274 /* Send command reply to sender */
4275 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4276 SILC_STATUS_OK, ident, 3,
4278 3, tmp_ch_id, tmp_ch_len,
4279 4, tmp_id, tmp_len);
4280 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4281 packet->data, packet->len, FALSE);
4283 silc_buffer_free(packet);
4284 silc_free(channel_id);
4285 silc_free(client_id);
4286 silc_buffer_free(idp);
4289 silc_server_command_free(cmd);
4292 /* Server side of KICK command. Kicks client out of channel. */
4294 SILC_SERVER_CMD_FUNC(kick)
4296 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4297 SilcServer server = cmd->server;
4298 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4299 SilcClientEntry target_client;
4300 SilcChannelID *channel_id;
4301 SilcClientID *client_id;
4302 SilcChannelEntry channel;
4303 SilcChannelClientEntry chl;
4305 uint32 tmp_len, target_idp_len;
4306 unsigned char *tmp, *comment, *target_idp;
4308 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4310 /* Get Channel ID */
4311 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4313 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4314 SILC_STATUS_ERR_NO_CHANNEL_ID);
4317 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
4319 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4320 SILC_STATUS_ERR_NO_CHANNEL_ID);
4324 /* Get channel entry */
4325 channel = silc_idlist_find_channel_by_id(server->local_list,
4328 channel = silc_idlist_find_channel_by_id(server->local_list,
4331 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4332 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4337 /* Check whether sender is on the channel */
4338 if (!silc_server_client_on_channel(client, channel)) {
4339 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4340 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4344 /* Check that the kicker is channel operator or channel founder */
4345 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4346 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4347 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4348 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4352 /* Get target Client ID */
4353 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4355 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4356 SILC_STATUS_ERR_NO_CLIENT_ID);
4359 client_id = silc_id_payload_parse_id(target_idp, target_idp_len);
4361 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4362 SILC_STATUS_ERR_NO_CLIENT_ID);
4366 /* Get target client's entry */
4367 target_client = silc_idlist_find_client_by_id(server->local_list,
4368 client_id, TRUE, NULL);
4369 if (!target_client) {
4370 target_client = silc_idlist_find_client_by_id(server->global_list,
4371 client_id, TRUE, NULL);
4374 /* Check that the target client is not channel founder. Channel founder
4375 cannot be kicked from the channel. */
4376 silc_hash_table_find(channel->user_list, target_client, NULL, (void *)&chl);
4377 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4378 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4379 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4383 /* Check whether target client is on the channel */
4384 if (!silc_server_client_on_channel(target_client, channel)) {
4385 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4386 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4392 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4396 /* Send command reply to sender */
4397 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4400 /* Send KICKED notify to local clients on the channel */
4401 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4402 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4403 SILC_NOTIFY_TYPE_KICKED, 3,
4404 target_idp, target_idp_len,
4405 comment, comment ? strlen(comment) : 0,
4406 idp->data, idp->len);
4407 silc_buffer_free(idp);
4409 /* Remove the client from the channel. If the channel does not exist
4410 after removing the client then the client kicked itself off the channel
4411 and we don't have to send anything after that. */
4412 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4413 target_client, FALSE))
4416 /* Send KICKED notify to primary route */
4417 if (!server->standalone)
4418 silc_server_send_notify_kicked(server, server->router->connection,
4419 server->server_type == SILC_ROUTER ?
4420 TRUE : FALSE, channel,
4421 target_client->id, comment);
4423 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4424 /* Re-generate channel key */
4425 if (!silc_server_create_channel_key(server, channel, 0))
4428 /* Send the channel key to the channel. The key of course is not sent
4429 to the client who was kicked off the channel. */
4430 silc_server_send_channel_key(server, target_client->connection, channel,
4431 server->server_type == SILC_ROUTER ?
4432 FALSE : !server->standalone);
4436 silc_server_command_free(cmd);
4439 /* Server side of OPER command. Client uses this comand to obtain server
4440 operator privileges to this server/router. */
4442 SILC_SERVER_CMD_FUNC(oper)
4444 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4445 SilcServer server = cmd->server;
4446 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4447 unsigned char *username, *auth;
4449 SilcServerConfigSectionAdminConnection *admin;
4450 SilcIDListData idata = (SilcIDListData)client;
4452 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4454 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4457 /* Get the username */
4458 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4460 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4461 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4465 /* Get the admin configuration */
4466 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4467 username, client->nickname);
4469 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4470 username, client->nickname);
4472 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4473 SILC_STATUS_ERR_AUTH_FAILED);
4478 /* Get the authentication payload */
4479 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4481 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4482 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4486 /* Verify the authentication data */
4487 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4488 admin->auth_data, admin->auth_data_len,
4489 idata->hash, client->id, SILC_ID_CLIENT)) {
4490 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4491 SILC_STATUS_ERR_AUTH_FAILED);
4495 /* Client is now server operator */
4496 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4498 /* Send UMODE change to primary router */
4499 if (!server->standalone)
4500 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4501 client->id, client->mode);
4503 /* Send reply to the sender */
4504 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4508 silc_server_command_free(cmd);
4511 /* Server side of SILCOPER command. Client uses this comand to obtain router
4512 operator privileges to this router. */
4514 SILC_SERVER_CMD_FUNC(silcoper)
4516 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4517 SilcServer server = cmd->server;
4518 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4519 unsigned char *username, *auth;
4521 SilcServerConfigSectionAdminConnection *admin;
4522 SilcIDListData idata = (SilcIDListData)client;
4524 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4526 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4529 if (server->server_type != SILC_ROUTER) {
4530 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4531 SILC_STATUS_ERR_AUTH_FAILED);
4535 /* Get the username */
4536 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4538 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4539 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4543 /* Get the admin configuration */
4544 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4545 username, client->nickname);
4547 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4548 username, client->nickname);
4550 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4551 SILC_STATUS_ERR_AUTH_FAILED);
4556 /* Get the authentication payload */
4557 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4559 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4560 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4564 /* Verify the authentication data */
4565 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4566 admin->auth_data, admin->auth_data_len,
4567 idata->hash, client->id, SILC_ID_CLIENT)) {
4568 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4569 SILC_STATUS_ERR_AUTH_FAILED);
4573 /* Client is now router operator */
4574 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4576 /* Send UMODE change to primary router */
4577 if (!server->standalone)
4578 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4579 client->id, client->mode);
4581 /* Send reply to the sender */
4582 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4586 silc_server_command_free(cmd);
4589 /* Server side command of CONNECT. Connects us to the specified remote
4590 server or router. */
4592 SILC_SERVER_CMD_FUNC(connect)
4594 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4595 SilcServer server = cmd->server;
4596 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4597 unsigned char *tmp, *host;
4599 uint32 port = SILC_PORT;
4601 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CONNECT, cmd, 1, 2);
4603 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4606 /* Check whether client has the permissions. */
4607 if (client->mode == SILC_UMODE_NONE) {
4608 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4609 SILC_STATUS_ERR_NO_SERVER_PRIV);
4613 if (server->server_type == SILC_ROUTER &&
4614 client->mode & SILC_UMODE_SERVER_OPERATOR) {
4615 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4616 SILC_STATUS_ERR_NO_ROUTER_PRIV);
4620 /* Get the remote server */
4621 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4623 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4624 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4629 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4631 SILC_GET32_MSB(port, tmp);
4633 /* Create the connection. It is done with timeout and is async. */
4634 silc_server_create_connection(server, host, port);
4636 /* Send reply to the sender */
4637 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4641 silc_server_command_free(cmd);
4644 /* Server side of command BAN. This is used to manage the ban list of the
4645 channel. To add clients and remove clients from the ban list. */
4647 SILC_SERVER_CMD_FUNC(ban)
4649 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4650 SilcServer server = cmd->server;
4651 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4653 SilcChannelEntry channel;
4654 SilcChannelClientEntry chl;
4655 SilcChannelID *channel_id = NULL;
4656 unsigned char *id, *add, *del;
4657 uint32 id_len, tmp_len;
4658 uint16 ident = silc_command_get_ident(cmd->payload);
4660 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4663 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4665 /* Get Channel ID */
4666 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4668 channel_id = silc_id_payload_parse_id(id, id_len);
4670 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4671 SILC_STATUS_ERR_NO_CHANNEL_ID);
4676 /* Get channel entry. The server must know about the channel since the
4677 client is expected to be on the channel. */
4678 channel = silc_idlist_find_channel_by_id(server->local_list,
4681 channel = silc_idlist_find_channel_by_id(server->global_list,
4684 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4685 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4690 /* Check whether this client is on the channel */
4691 if (!silc_server_client_on_channel(client, channel)) {
4692 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4693 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4697 /* Get entry to the channel user list */
4698 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4700 /* The client must be at least channel operator. */
4701 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4702 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4703 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4707 /* Get the new ban and add it to the ban list */
4708 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4710 if (!channel->ban_list)
4711 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4713 channel->ban_list = silc_realloc(channel->ban_list,
4714 sizeof(*channel->ban_list) *
4716 strlen(channel->ban_list) + 2));
4717 if (add[tmp_len - 1] == ',')
4718 add[tmp_len - 1] = '\0';
4720 strncat(channel->ban_list, add, tmp_len);
4721 strncat(channel->ban_list, ",", 1);
4724 /* Get the ban to be removed and remove it from the list */
4725 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4726 if (del && channel->ban_list) {
4727 char *start, *end, *n;
4729 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4730 silc_free(channel->ban_list);
4731 channel->ban_list = NULL;
4733 start = strstr(channel->ban_list, del);
4734 if (start && strlen(start) >= tmp_len) {
4735 end = start + tmp_len;
4736 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4737 strncat(n, channel->ban_list, start - channel->ban_list);
4738 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4740 silc_free(channel->ban_list);
4741 channel->ban_list = n;
4746 /* Send the BAN notify type to our primary router. */
4747 if (!server->standalone && (add || del))
4748 silc_server_send_notify_ban(server, server->router->connection,
4749 server->server_type == SILC_ROUTER ?
4750 TRUE : FALSE, channel, add, del);
4752 /* Send the reply back to the client */
4754 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4755 SILC_STATUS_OK, ident, 2,
4757 3, channel->ban_list,
4759 strlen(channel->ban_list) - 1 : 0);
4760 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4761 packet->data, packet->len, FALSE);
4763 silc_buffer_free(packet);
4766 silc_free(channel_id);
4767 silc_server_command_free(cmd);
4770 /* Server side command of CLOSE. Closes connection to a specified server. */
4772 SILC_SERVER_CMD_FUNC(close)
4774 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4775 SilcServer server = cmd->server;
4776 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4777 SilcServerEntry server_entry;
4778 SilcSocketConnection sock;
4781 unsigned char *name;
4782 uint32 port = SILC_PORT;
4784 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CLOSE, cmd, 1, 2);
4786 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4789 /* Check whether client has the permissions. */
4790 if (client->mode == SILC_UMODE_NONE) {
4791 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4792 SILC_STATUS_ERR_NO_SERVER_PRIV);
4796 /* Get the remote server */
4797 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4799 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4800 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4805 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4807 SILC_GET32_MSB(port, tmp);
4809 server_entry = silc_idlist_find_server_by_conn(server->local_list,
4810 name, port, FALSE, NULL);
4812 server_entry = silc_idlist_find_server_by_conn(server->global_list,
4813 name, port, FALSE, NULL);
4814 if (!server_entry) {
4815 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4816 SILC_STATUS_ERR_NO_SERVER_ID);
4820 /* Send reply to the sender */
4821 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4824 /* Close the connection to the server */
4825 sock = (SilcSocketConnection)server_entry->connection;
4827 /* If we shutdown primary router connection manually then don't trigger
4828 any reconnect or backup router connections, by setting the router
4830 if (server->router == server_entry) {
4831 server->id_entry->router = NULL;
4832 server->router = NULL;
4833 server->standalone = TRUE;
4835 silc_server_free_sock_user_data(server, sock);
4836 silc_server_close_connection(server, sock);
4839 silc_server_command_free(cmd);
4842 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4843 active connections. */
4845 SILC_SERVER_CMD_FUNC(shutdown)
4847 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4848 SilcServer server = cmd->server;
4849 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4851 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4853 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4856 /* Check whether client has the permission. */
4857 if (client->mode == SILC_UMODE_NONE) {
4858 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4859 SILC_STATUS_ERR_NO_SERVER_PRIV);
4863 /* Send reply to the sender */
4864 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4867 /* Then, gracefully, or not, bring the server down. */
4868 silc_server_stop(server);
4872 silc_server_command_free(cmd);
4875 /* Server side command of LEAVE. Removes client from a channel. */
4877 SILC_SERVER_CMD_FUNC(leave)
4879 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4880 SilcServer server = cmd->server;
4881 SilcSocketConnection sock = cmd->sock;
4882 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4883 SilcChannelID *id = NULL;
4884 SilcChannelEntry channel;
4888 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4890 /* Get Channel ID */
4891 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4893 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4894 SILC_STATUS_ERR_NO_CHANNEL_ID);
4897 id = silc_id_payload_parse_id(tmp, len);
4899 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4900 SILC_STATUS_ERR_NO_CHANNEL_ID);
4904 /* Get channel entry */
4905 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4907 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4909 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4910 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4915 /* Check whether this client is on the channel */
4916 if (!silc_server_client_on_channel(id_entry, channel)) {
4917 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4918 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4922 /* Notify routers that they should remove this client from their list
4923 of clients on the channel. Send LEAVE notify type. */
4924 if (!server->standalone)
4925 silc_server_send_notify_leave(server, server->router->connection,
4926 server->server_type == SILC_ROUTER ?
4927 TRUE : FALSE, channel, id_entry->id);
4929 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4932 /* Remove client from channel */
4933 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4935 /* If the channel does not exist anymore we won't send anything */
4938 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4939 /* Re-generate channel key */
4940 if (!silc_server_create_channel_key(server, channel, 0))
4943 /* Send the channel key */
4944 silc_server_send_channel_key(server, NULL, channel,
4945 server->server_type == SILC_ROUTER ?
4946 FALSE : !server->standalone);
4951 silc_server_command_free(cmd);
4954 /* Server side of command USERS. Resolves clients and their USERS currently
4955 joined on the requested channel. The list of Client ID's and their modes
4956 on the channel is sent back. */
4958 SILC_SERVER_CMD_FUNC(users)
4960 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4961 SilcServer server = cmd->server;
4962 SilcChannelEntry channel;
4963 SilcChannelID *id = NULL;
4964 SilcBuffer packet, idp;
4965 unsigned char *channel_id;
4966 uint32 channel_id_len;
4967 SilcBuffer client_id_list;
4968 SilcBuffer client_mode_list;
4969 unsigned char lc[4];
4970 uint32 list_count = 0;
4971 uint16 ident = silc_command_get_ident(cmd->payload);
4974 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
4976 /* Get Channel ID */
4977 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4979 /* Get channel name */
4980 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
4982 if (!channel_id && !channel_name) {
4983 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4984 SILC_STATUS_ERR_NO_CHANNEL_ID);
4989 id = silc_id_payload_parse_id(channel_id, channel_id_len);
4991 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4992 SILC_STATUS_ERR_NO_CHANNEL_ID);
4997 /* If we are server and we don't know about this channel we will send
4998 the command to our router. If we know about the channel then we also
4999 have the list of users already. */
5001 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5003 channel = silc_idlist_find_channel_by_name(server->local_list,
5004 channel_name, NULL);
5006 if (!channel || channel->disabled) {
5007 if (server->server_type != SILC_ROUTER && !server->standalone &&
5011 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5012 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5014 /* Send USERS command */
5015 silc_server_packet_send(server, server->router->connection,
5016 SILC_PACKET_COMMAND, cmd->packet->flags,
5017 tmpbuf->data, tmpbuf->len, TRUE);
5019 /* Reprocess this packet after received reply */
5020 silc_server_command_pending(server, SILC_COMMAND_USERS,
5021 silc_command_get_ident(cmd->payload),
5022 silc_server_command_destructor,
5023 silc_server_command_users,
5024 silc_server_command_dup(cmd));
5025 cmd->pending = TRUE;
5026 silc_command_set_ident(cmd->payload, ident);
5028 silc_buffer_free(tmpbuf);
5033 /* Check the global list as well. */
5035 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5037 channel = silc_idlist_find_channel_by_name(server->global_list,
5038 channel_name, NULL);
5040 /* Channel really does not exist */
5041 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5042 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5047 /* If the channel is private or secret do not send anything, unless the
5048 user requesting this command is on the channel. */
5049 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5050 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5051 && !silc_server_client_on_channel(cmd->sock->user_data, channel)) {
5052 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5053 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5058 (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
5059 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5060 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5065 /* Get the users list */
5066 silc_server_get_users_on_channel(server, channel, &client_id_list,
5067 &client_mode_list, &list_count);
5070 SILC_PUT32_MSB(list_count, lc);
5073 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5074 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5075 SILC_STATUS_OK, ident, 4,
5076 2, idp->data, idp->len,
5078 4, client_id_list->data,
5079 client_id_list->len,
5080 5, client_mode_list->data,
5081 client_mode_list->len);
5082 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5083 packet->data, packet->len, FALSE);
5085 silc_buffer_free(idp);
5086 silc_buffer_free(packet);
5087 silc_buffer_free(client_id_list);
5088 silc_buffer_free(client_mode_list);
5092 silc_server_command_free(cmd);
5095 /* Server side of command GETKEY. This fetches the client's public key
5096 from the server where to the client is connected. */
5098 SILC_SERVER_CMD_FUNC(getkey)
5100 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5101 SilcServer server = cmd->server;
5103 SilcClientEntry client;
5104 SilcServerEntry server_entry;
5105 SilcClientID *client_id = NULL;
5106 SilcServerID *server_id = NULL;
5107 SilcIDPayload idp = NULL;
5108 uint16 ident = silc_command_get_ident(cmd->payload);
5109 unsigned char *tmp, *pkdata;
5110 uint32 tmp_len, pklen;
5111 SilcBuffer pk = NULL;
5114 SILC_LOG_DEBUG(("Start"));
5116 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5118 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5119 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5122 idp = silc_id_payload_parse(tmp, tmp_len);
5124 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5125 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5129 id_type = silc_id_payload_get_type(idp);
5130 if (id_type == SILC_ID_CLIENT) {
5131 client_id = silc_id_payload_get_id(idp);
5133 /* If the client is not found from local list there is no chance it
5134 would be locally connected client so send the command further. */
5135 client = silc_idlist_find_client_by_id(server->local_list,
5136 client_id, TRUE, NULL);
5138 client = silc_idlist_find_client_by_id(server->global_list,
5139 client_id, TRUE, NULL);
5141 if ((!client && !cmd->pending && !server->standalone) ||
5142 (client && !client->connection && !cmd->pending) ||
5143 (client && !client->data.public_key && !cmd->pending)) {
5146 SilcSocketConnection dest_sock;
5148 dest_sock = silc_server_get_client_route(server, NULL, 0,
5153 old_ident = silc_command_get_ident(cmd->payload);
5154 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5155 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5157 silc_server_packet_send(server, dest_sock,
5158 SILC_PACKET_COMMAND, cmd->packet->flags,
5159 tmpbuf->data, tmpbuf->len, TRUE);
5161 /* Reprocess this packet after received reply from router */
5162 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5163 silc_command_get_ident(cmd->payload),
5164 silc_server_command_destructor,
5165 silc_server_command_getkey,
5166 silc_server_command_dup(cmd));
5167 cmd->pending = TRUE;
5169 silc_command_set_ident(cmd->payload, old_ident);
5170 silc_buffer_free(tmpbuf);
5175 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5176 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5180 /* The client is locally connected, just get the public key and
5181 send it back. If they key does not exist then do not send it,
5182 send just OK reply */
5183 if (!client->data.public_key) {
5187 tmp = silc_pkcs_public_key_encode(client->data.public_key, &tmp_len);
5188 pk = silc_buffer_alloc(4 + tmp_len);
5189 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5190 silc_buffer_format(pk,
5191 SILC_STR_UI_SHORT(tmp_len),
5192 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5193 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5199 } else if (id_type == SILC_ID_SERVER) {
5200 server_id = silc_id_payload_get_id(idp);
5202 /* If the server is not found from local list there is no chance it
5203 would be locally connected server so send the command further. */
5204 server_entry = silc_idlist_find_server_by_id(server->local_list,
5205 server_id, TRUE, NULL);
5207 server_entry = silc_idlist_find_server_by_id(server->global_list,
5208 server_id, TRUE, NULL);
5210 if (server_entry != server->id_entry &&
5211 ((!server_entry && !cmd->pending && !server->standalone) ||
5212 (server_entry && !server_entry->connection && !cmd->pending &&
5213 !server->standalone) ||
5214 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5215 !server->standalone))) {
5219 old_ident = silc_command_get_ident(cmd->payload);
5220 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5221 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5223 silc_server_packet_send(server, server->router->connection,
5224 SILC_PACKET_COMMAND, cmd->packet->flags,
5225 tmpbuf->data, tmpbuf->len, TRUE);
5227 /* Reprocess this packet after received reply from router */
5228 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5229 silc_command_get_ident(cmd->payload),
5230 silc_server_command_destructor,
5231 silc_server_command_getkey,
5232 silc_server_command_dup(cmd));
5233 cmd->pending = TRUE;
5235 silc_command_set_ident(cmd->payload, old_ident);
5236 silc_buffer_free(tmpbuf);
5240 if (!server_entry) {
5241 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5242 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5246 /* If they key does not exist then do not send it, send just OK reply */
5247 if (!server_entry->data.public_key) {
5251 tmp = silc_pkcs_public_key_encode(server_entry->data.public_key,
5253 pk = silc_buffer_alloc(4 + tmp_len);
5254 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5255 silc_buffer_format(pk,
5256 SILC_STR_UI_SHORT(tmp_len),
5257 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5258 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5268 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5269 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5270 SILC_STATUS_OK, ident,
5274 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5275 packet->data, packet->len, FALSE);
5276 silc_buffer_free(packet);
5279 silc_buffer_free(pk);
5283 silc_id_payload_free(idp);
5284 silc_free(client_id);
5285 silc_free(server_id);
5286 silc_server_command_free(cmd);