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 /* Parse the whois request */
829 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
830 &nick, &server_name, &count,
834 /* Send the WHOIS request to the router only if it included nickname.
835 Since nicknames can be expanded into many clients we need to send it
836 to router. If the WHOIS included only client ID's we will check them
837 first locally since we just might have them. */
838 if (nick && !client_id_count &&
839 cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
840 server->server_type == SILC_SERVER && !cmd->pending &&
841 !server->standalone) {
845 old_ident = silc_command_get_ident(cmd->payload);
846 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
847 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
849 /* Send WHOIS command to our router */
850 silc_server_packet_send(server, (SilcSocketConnection)
851 server->router->connection,
852 SILC_PACKET_COMMAND, cmd->packet->flags,
853 tmpbuf->data, tmpbuf->len, TRUE);
855 /* Reprocess this packet after received reply from router */
856 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
857 silc_command_get_ident(cmd->payload),
858 silc_server_command_destructor,
859 silc_server_command_whois,
860 silc_server_command_dup(cmd));
863 silc_command_set_ident(cmd->payload, old_ident);
865 silc_buffer_free(tmpbuf);
870 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
872 else if (server->server_type != SILC_SERVER)
875 /* Get all clients matching that ID or nickname from local list */
876 if (client_id_count) {
877 /* Check all Client ID's received in the command packet */
878 for (i = 0; i < client_id_count; i++) {
879 entry = silc_idlist_find_client_by_id(server->local_list,
880 client_id[i], TRUE, NULL);
881 if (!entry && check_global)
882 entry = silc_idlist_find_client_by_id(server->global_list,
883 client_id[i], TRUE, NULL);
885 clients = silc_realloc(clients, sizeof(*clients) *
886 (clients_count + 1));
887 clients[clients_count++] = entry;
891 if (!silc_idlist_get_clients_by_hash(server->local_list,
892 nick, server->md5hash,
893 &clients, &clients_count))
894 silc_idlist_get_clients_by_nickname(server->local_list,
896 &clients, &clients_count);
898 if (!silc_idlist_get_clients_by_hash(server->global_list,
899 nick, server->md5hash,
900 &clients, &clients_count))
901 silc_idlist_get_clients_by_nickname(server->global_list,
903 &clients, &clients_count);
908 /* Such client(s) really does not exist in the SILC network. */
909 if (!client_id_count) {
910 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
911 SILC_STATUS_ERR_NO_SUCH_NICK,
912 3, nick, strlen(nick));
914 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
915 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
916 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
917 2, idp->data, idp->len);
918 silc_buffer_free(idp);
923 /* Router always finds the client entry if it exists in the SILC network.
924 However, it might be incomplete entry and does not include all the
925 mandatory fields that WHOIS command reply requires. Check for these and
926 make query from the server who owns the client if some fields are
928 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
933 /* Send the command reply */
934 silc_server_command_whois_send_reply(cmd, clients, clients_count,
938 if (client_id_count) {
939 for (i = 0; i < client_id_count; i++)
940 silc_free(client_id[i]);
941 silc_free(client_id);
945 silc_free(server_name);
950 /* Server side of command WHOIS. Processes user's query and sends found
951 results as command replies back to the client. */
953 SILC_SERVER_CMD_FUNC(whois)
955 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
958 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 3328);
960 ret = silc_server_command_whois_process(cmd);
963 silc_server_command_free(cmd);
966 /******************************************************************************
970 ******************************************************************************/
973 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
981 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
983 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
984 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
988 /* Get the nickname@server string and parse it. */
989 silc_parse_userfqdn(tmp, nickname, server_name);
991 /* Get the max count of reply messages allowed */
992 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1002 silc_server_command_whowas_check(SilcServerCommandContext cmd,
1003 SilcClientEntry *clients,
1004 uint32 clients_count)
1006 SilcServer server = cmd->server;
1008 SilcClientEntry entry;
1010 for (i = 0; i < clients_count; i++) {
1013 if (!entry->nickname || !entry->username) {
1020 old_ident = silc_command_get_ident(cmd->payload);
1021 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1022 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1024 /* Send WHOWAS command */
1025 silc_server_packet_send(server, entry->router->connection,
1026 SILC_PACKET_COMMAND, cmd->packet->flags,
1027 tmpbuf->data, tmpbuf->len, TRUE);
1029 /* Reprocess this packet after received reply */
1030 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1031 silc_command_get_ident(cmd->payload),
1032 silc_server_command_destructor,
1033 silc_server_command_whowas,
1034 silc_server_command_dup(cmd));
1035 cmd->pending = TRUE;
1037 silc_command_set_ident(cmd->payload, old_ident);
1039 silc_buffer_free(tmpbuf);
1048 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1049 SilcClientEntry *clients,
1050 uint32 clients_count)
1052 SilcServer server = cmd->server;
1054 int i, count = 0, len;
1055 SilcBuffer packet, idp;
1056 SilcClientEntry entry = NULL;
1057 SilcCommandStatus status;
1058 uint16 ident = silc_command_get_ident(cmd->payload);
1060 char nh[256], uh[256];
1062 status = SILC_STATUS_OK;
1063 if (clients_count > 1)
1064 status = SILC_STATUS_LIST_START;
1066 for (i = 0; i < clients_count; i++) {
1069 /* We will take only clients that are not valid anymore. They are the
1070 ones that are not registered anymore but still have a ID. They
1071 have disconnected us, and thus valid for WHOWAS. */
1072 if (entry->data.status & SILC_IDLIST_STATUS_REGISTERED)
1074 if (entry->id == NULL)
1077 if (count && i - 1 == count)
1082 if (clients_count > 2)
1083 status = SILC_STATUS_LIST_ITEM;
1085 if (clients_count > 1 && i == clients_count - 1)
1086 status = SILC_STATUS_LIST_END;
1088 /* Sanity check, however these should never fail. However, as
1089 this sanity check has been added here they have failed. */
1090 if (!entry->nickname || !entry->username)
1093 /* Send WHOWAS reply */
1094 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1095 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1097 memset(uh, 0, sizeof(uh));
1098 memset(nh, 0, sizeof(nh));
1100 strncat(nh, entry->nickname, strlen(entry->nickname));
1101 if (!strchr(entry->nickname, '@')) {
1102 strncat(nh, "@", 1);
1103 if (entry->servername) {
1104 strncat(nh, entry->servername, strlen(entry->servername));
1106 len = entry->router ? strlen(entry->router->server_name) :
1107 strlen(server->server_name);
1108 strncat(nh, entry->router ? entry->router->server_name :
1109 server->server_name, len);
1113 strncat(uh, entry->username, strlen(entry->username));
1114 if (!strchr(entry->username, '@')) {
1115 strncat(uh, "@", 1);
1116 strcat(uh, "*private*");
1120 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1122 2, idp->data, idp->len,
1127 strlen(entry->userinfo) : 0);
1128 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1129 0, packet->data, packet->len, FALSE);
1131 silc_buffer_free(packet);
1132 silc_buffer_free(idp);
1135 if (found == FALSE && entry)
1136 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1137 SILC_STATUS_ERR_NO_SUCH_NICK,
1139 strlen(entry->nickname));
1143 silc_server_command_whowas_process(SilcServerCommandContext cmd)
1145 SilcServer server = cmd->server;
1146 char *nick = NULL, *server_name = NULL;
1148 SilcClientEntry *clients = NULL;
1149 uint32 clients_count = 0;
1151 bool check_global = FALSE;
1153 /* Protocol dictates that we must always send the received WHOWAS request
1154 to our router if we are normal server, so let's do it now unless we
1155 are standalone. We will not send any replies to the client until we
1156 have received reply from the router. */
1157 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1158 server->server_type == SILC_SERVER && !cmd->pending &&
1159 !server->standalone) {
1163 old_ident = silc_command_get_ident(cmd->payload);
1164 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1165 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1167 /* Send WHOWAS command to our router */
1168 silc_server_packet_send(server, (SilcSocketConnection)
1169 server->router->connection,
1170 SILC_PACKET_COMMAND, cmd->packet->flags,
1171 tmpbuf->data, tmpbuf->len, TRUE);
1173 /* Reprocess this packet after received reply from router */
1174 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1175 silc_command_get_ident(cmd->payload),
1176 silc_server_command_destructor,
1177 silc_server_command_whowas,
1178 silc_server_command_dup(cmd));
1179 cmd->pending = TRUE;
1181 silc_command_set_ident(cmd->payload, old_ident);
1183 silc_buffer_free(tmpbuf);
1188 /* We are ready to process the command request. Let's search for the
1189 requested client and send reply to the requesting client. */
1191 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1192 check_global = TRUE;
1193 else if (server->server_type != SILC_SERVER)
1194 check_global = TRUE;
1196 /* Parse the whowas request */
1197 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1200 /* Get all clients matching that nickname from local list */
1201 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1203 &clients, &clients_count))
1204 silc_idlist_get_clients_by_hash(server->local_list,
1205 nick, server->md5hash,
1206 &clients, &clients_count);
1208 /* Check global list as well */
1210 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1212 &clients, &clients_count))
1213 silc_idlist_get_clients_by_hash(server->global_list,
1214 nick, server->md5hash,
1215 &clients, &clients_count);
1219 /* Such a client really does not exist in the SILC network. */
1220 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1221 SILC_STATUS_ERR_NO_SUCH_NICK,
1222 3, nick, strlen(nick));
1226 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1231 /* Send the command reply to the client */
1232 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1237 silc_free(server_name);
1242 /* Server side of command WHOWAS. */
1244 SILC_SERVER_CMD_FUNC(whowas)
1246 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1249 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1251 ret = silc_server_command_whowas_process(cmd);
1254 silc_server_command_free(cmd);
1257 /******************************************************************************
1261 ******************************************************************************/
1264 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1265 SilcClientEntry **clients,
1266 uint32 *clients_count,
1267 SilcServerEntry **servers,
1268 uint32 *servers_count,
1269 SilcChannelEntry **channels,
1270 uint32 *channels_count,
1274 SilcServer server = cmd->server;
1277 uint32 argc = silc_argument_get_arg_num(cmd->args);
1279 bool check_global = FALSE;
1284 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1285 check_global = TRUE;
1286 else if (server->server_type != SILC_SERVER)
1287 check_global = TRUE;
1289 /* If ID Payload is in the command it must be used instead of names */
1290 tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1292 /* 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;
1829 /* Parse the IDENTIFY request */
1830 if (!silc_server_command_identify_parse(cmd,
1831 &clients, &clients_count,
1832 &servers, &servers_count,
1833 &channels, &channels_count,
1837 /* Send the IDENTIFY request to the router only if it included nickname.
1838 Since nicknames can be expanded into many clients we need to send it
1839 to router. If the IDENTIFY included only client ID's we will check them
1840 first locally since we just might have them. */
1841 if (names && cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1842 server->server_type == SILC_SERVER && !cmd->pending &&
1843 !server->standalone) {
1847 old_ident = silc_command_get_ident(cmd->payload);
1848 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1849 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1851 /* Send IDENTIFY command to our router */
1852 silc_server_packet_send(server, (SilcSocketConnection)
1853 server->router->connection,
1854 SILC_PACKET_COMMAND, cmd->packet->flags,
1855 tmpbuf->data, tmpbuf->len, TRUE);
1857 /* Reprocess this packet after received reply from router */
1858 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1859 silc_command_get_ident(cmd->payload),
1860 silc_server_command_destructor,
1861 silc_server_command_identify,
1862 silc_server_command_dup(cmd));
1863 cmd->pending = TRUE;
1865 silc_command_set_ident(cmd->payload, old_ident);
1867 silc_buffer_free(tmpbuf);
1872 /* Check that all mandatory fields are present and request those data
1873 from the server who owns the client if necessary. */
1874 if (clients && !silc_server_command_identify_check_client(cmd, clients,
1880 /* Send the command reply to the client */
1881 silc_server_command_identify_send_reply(cmd,
1882 clients, clients_count,
1883 servers, servers_count,
1884 channels, channels_count,
1890 silc_free(channels);
1895 SILC_SERVER_CMD_FUNC(identify)
1897 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1900 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1902 ret = silc_server_command_identify_process(cmd);
1905 silc_server_command_free(cmd);
1908 /* Checks string for bad characters and returns TRUE if they are found. */
1910 static int silc_server_command_bad_chars(char *nick)
1914 for (i = 0; i < strlen(nick); i++) {
1915 if (!isascii(nick[i]))
1917 if (nick[i] <= 32) return TRUE;
1918 if (nick[i] == ' ') return TRUE;
1919 if (nick[i] == '*') return TRUE;
1920 if (nick[i] == '?') return TRUE;
1921 if (nick[i] == ',') return TRUE;
1927 /* Server side of command NICK. Sets nickname for user. Setting
1928 nickname causes generation of a new client ID for the client. The
1929 new client ID is sent to the client after changing the nickname. */
1931 SILC_SERVER_CMD_FUNC(nick)
1933 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1934 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1935 SilcServer server = cmd->server;
1936 SilcBuffer packet, nidp, oidp = NULL;
1937 SilcClientID *new_id;
1939 uint16 ident = silc_command_get_ident(cmd->payload);
1942 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1945 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
1947 /* Check nickname */
1948 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1949 if (silc_server_command_bad_chars(nick) == TRUE) {
1950 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1951 SILC_STATUS_ERR_BAD_NICKNAME);
1955 if (strlen(nick) > 128)
1958 /* Check for same nickname */
1959 if (!strcmp(client->nickname, nick)) {
1960 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1964 /* Create new Client ID */
1965 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
1967 cmd->server->md5hash, nick,
1970 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
1973 /* Send notify about nickname change to our router. We send the new
1974 ID and ask to replace it with the old one. If we are router the
1975 packet is broadcasted. Send NICK_CHANGE notify. */
1976 if (!server->standalone)
1977 silc_server_send_notify_nick_change(server, server->router->connection,
1978 server->server_type == SILC_SERVER ?
1979 FALSE : TRUE, client->id,
1982 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1984 /* Remove old cache entry */
1985 silc_idcache_del_by_context(server->local_list->clients, client);
1988 silc_free(client->id);
1990 /* Save the nickname as this client is our local client */
1991 silc_free(client->nickname);
1993 client->nickname = strdup(nick);
1994 client->id = new_id;
1996 /* Update client cache */
1997 silc_idcache_add(server->local_list->clients, client->nickname,
1998 client->id, (void *)client, FALSE);
2000 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2002 /* Send NICK_CHANGE notify to the client's channels */
2003 silc_server_send_notify_on_channels(server, NULL, client,
2004 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
2005 oidp->data, oidp->len,
2006 nidp->data, nidp->len);
2009 /* Send the new Client ID as reply command back to client */
2010 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
2011 SILC_STATUS_OK, ident, 1,
2012 2, nidp->data, nidp->len);
2013 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2014 0, packet->data, packet->len, FALSE);
2016 silc_buffer_free(packet);
2017 silc_buffer_free(nidp);
2019 silc_buffer_free(oidp);
2022 silc_server_command_free(cmd);
2025 /* Sends the LIST command reply */
2028 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2029 SilcChannelEntry *lch,
2031 SilcChannelEntry *gch,
2035 SilcBuffer packet, idp;
2036 SilcChannelEntry entry;
2037 SilcCommandStatus status;
2038 uint16 ident = silc_command_get_ident(cmd->payload);
2040 unsigned char usercount[4];
2043 for (i = 0; i < lch_count; i++)
2044 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2046 for (i = 0; i < gch_count; i++)
2047 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2050 status = SILC_STATUS_OK;
2051 if ((lch_count + gch_count) > 1)
2052 status = SILC_STATUS_LIST_START;
2055 for (i = 0; i < lch_count; i++) {
2061 status = SILC_STATUS_LIST_ITEM;
2062 if (i >= 1 && i == lch_count - 1 && !gch_count)
2063 status = SILC_STATUS_LIST_END;
2065 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2067 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2068 topic = "*private*";
2069 memset(usercount, 0, sizeof(usercount));
2071 topic = entry->topic;
2072 users = silc_hash_table_count(entry->user_list);
2073 SILC_PUT32_MSB(users, usercount);
2076 /* Send the reply */
2078 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2080 2, idp->data, idp->len,
2081 3, entry->channel_name,
2082 strlen(entry->channel_name),
2083 4, topic, topic ? strlen(topic) : 0,
2085 silc_server_packet_send(cmd->server, cmd->sock,
2086 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2087 packet->len, FALSE);
2088 silc_buffer_free(packet);
2089 silc_buffer_free(idp);
2093 for (i = 0; i < gch_count; i++) {
2099 status = SILC_STATUS_LIST_ITEM;
2100 if (i >= 1 && i == gch_count - 1)
2101 status = SILC_STATUS_LIST_END;
2103 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2105 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2106 topic = "*private*";
2107 memset(usercount, 0, sizeof(usercount));
2109 topic = entry->topic;
2110 users = silc_hash_table_count(entry->user_list);
2111 SILC_PUT32_MSB(users, usercount);
2114 /* Send the reply */
2116 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2118 2, idp->data, idp->len,
2119 3, entry->channel_name,
2120 strlen(entry->channel_name),
2121 4, topic, topic ? strlen(topic) : 0,
2123 silc_server_packet_send(cmd->server, cmd->sock,
2124 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2125 packet->len, FALSE);
2126 silc_buffer_free(packet);
2127 silc_buffer_free(idp);
2131 /* Server side of LIST command. This lists the channel of the requested
2132 server. Secret channels are not listed. */
2134 SILC_SERVER_CMD_FUNC(list)
2136 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2137 SilcServer server = cmd->server;
2138 SilcChannelID *channel_id = NULL;
2141 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2142 uint32 lch_count = 0, gch_count = 0;
2144 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2146 /* If we are normal server, send the command to router, since we
2147 want to know all channels in the network. */
2148 if (!cmd->pending && server->server_type == SILC_SERVER &&
2149 !server->standalone) {
2153 old_ident = silc_command_get_ident(cmd->payload);
2154 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2155 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2156 silc_server_packet_send(server, server->router->connection,
2157 SILC_PACKET_COMMAND, cmd->packet->flags,
2158 tmpbuf->data, tmpbuf->len, TRUE);
2160 /* Reprocess this packet after received reply from router */
2161 silc_server_command_pending(server, SILC_COMMAND_LIST,
2162 silc_command_get_ident(cmd->payload),
2163 silc_server_command_destructor,
2164 silc_server_command_list,
2165 silc_server_command_dup(cmd));
2166 cmd->pending = TRUE;
2167 silc_command_set_ident(cmd->payload, old_ident);
2168 silc_buffer_free(tmpbuf);
2172 /* Get Channel ID */
2173 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2175 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2177 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2178 SILC_STATUS_ERR_NO_CHANNEL_ID);
2183 /* Get the channels from local list */
2184 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2187 /* Get the channels from global list */
2188 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2191 /* Send the reply */
2192 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2193 gchannels, gch_count);
2195 silc_free(lchannels);
2196 silc_free(gchannels);
2199 silc_server_command_free(cmd);
2202 /* Server side of TOPIC command. Sets topic for channel and/or returns
2203 current topic to client. */
2205 SILC_SERVER_CMD_FUNC(topic)
2207 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2208 SilcServer server = cmd->server;
2209 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2210 SilcChannelID *channel_id;
2211 SilcChannelEntry channel;
2212 SilcChannelClientEntry chl;
2213 SilcBuffer packet, idp;
2215 uint32 argc, tmp_len;
2216 uint16 ident = silc_command_get_ident(cmd->payload);
2218 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2220 argc = silc_argument_get_arg_num(cmd->args);
2222 /* Get Channel ID */
2223 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2225 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2226 SILC_STATUS_ERR_NO_CHANNEL_ID);
2229 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2231 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2232 SILC_STATUS_ERR_NO_CHANNEL_ID);
2236 /* Check whether the channel exists */
2237 channel = silc_idlist_find_channel_by_id(server->local_list,
2240 channel = silc_idlist_find_channel_by_id(server->global_list,
2243 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2244 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2251 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2253 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2254 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2258 if (strlen(tmp) > 256) {
2259 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2260 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2264 /* See whether the client is on channel and has rights to change topic */
2265 if (!silc_hash_table_find(channel->user_list, client, NULL,
2267 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2268 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2272 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2273 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2274 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2275 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2280 /* Set the topic for channel */
2281 silc_free(channel->topic);
2282 channel->topic = strdup(tmp);
2284 /* Send TOPIC_SET notify type to the network */
2285 if (!server->standalone)
2286 silc_server_send_notify_topic_set(server, server->router->connection,
2287 server->server_type == SILC_ROUTER ?
2288 TRUE : FALSE, channel,
2289 client->id, SILC_ID_CLIENT,
2292 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2294 /* Send notify about topic change to all clients on the channel */
2295 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2296 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2297 idp->data, idp->len,
2298 channel->topic, strlen(channel->topic));
2299 silc_buffer_free(idp);
2302 /* Send the topic to client as reply packet */
2303 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2304 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2305 SILC_STATUS_OK, ident, 2,
2306 2, idp->data, idp->len,
2309 strlen(channel->topic) : 0);
2310 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2311 0, packet->data, packet->len, FALSE);
2313 silc_buffer_free(packet);
2314 silc_buffer_free(idp);
2315 silc_free(channel_id);
2318 silc_server_command_free(cmd);
2321 /* Server side of INVITE command. Invites some client to join some channel.
2322 This command is also used to manage the invite list of the channel. */
2324 SILC_SERVER_CMD_FUNC(invite)
2326 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2327 SilcServer server = cmd->server;
2328 SilcSocketConnection sock = cmd->sock, dest_sock;
2329 SilcChannelClientEntry chl;
2330 SilcClientEntry sender, dest;
2331 SilcClientID *dest_id = NULL;
2332 SilcChannelEntry channel;
2333 SilcChannelID *channel_id = NULL;
2334 SilcIDListData idata;
2335 SilcBuffer idp, idp2, packet;
2336 unsigned char *tmp, *add, *del;
2338 uint16 ident = silc_command_get_ident(cmd->payload);
2340 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2342 /* Get Channel ID */
2343 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2345 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2346 SILC_STATUS_ERR_NO_CHANNEL_ID);
2349 channel_id = silc_id_payload_parse_id(tmp, len);
2351 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2352 SILC_STATUS_ERR_NO_CHANNEL_ID);
2356 /* Get the channel entry */
2357 channel = silc_idlist_find_channel_by_id(server->local_list,
2360 channel = silc_idlist_find_channel_by_id(server->global_list,
2363 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2364 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2369 /* Check whether the sender of this command is on the channel. */
2370 sender = (SilcClientEntry)sock->user_data;
2371 if (!silc_server_client_on_channel(sender, channel)) {
2372 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2373 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2377 /* Check whether the channel is invite-only channel. If yes then the
2378 sender of this command must be at least channel operator. */
2379 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2380 silc_hash_table_find(channel->user_list, sender, NULL, (void *)&chl);
2381 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2382 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2383 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2388 /* Get destination client ID */
2389 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2393 dest_id = silc_id_payload_parse_id(tmp, len);
2395 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2396 SILC_STATUS_ERR_NO_CLIENT_ID);
2400 /* Get the client entry */
2401 dest = silc_server_get_client_resolve(server, dest_id);
2403 if (server->server_type != SILC_SERVER) {
2404 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2405 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2409 /* The client info is being resolved. Reprocess this packet after
2410 receiving the reply to the query. */
2411 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2413 silc_server_command_destructor,
2414 silc_server_command_invite,
2415 silc_server_command_dup(cmd));
2416 cmd->pending = TRUE;
2417 silc_free(channel_id);
2422 /* Check whether the requested client is already on the channel. */
2423 if (silc_server_client_on_channel(dest, channel)) {
2424 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2425 SILC_STATUS_ERR_USER_ON_CHANNEL);
2429 /* Get route to the client */
2430 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2432 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2433 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2437 memset(invite, 0, sizeof(invite));
2438 strncat(invite, dest->nickname, strlen(dest->nickname));
2439 strncat(invite, "!", 1);
2440 strncat(invite, dest->username, strlen(dest->username));
2441 if (!strchr(dest->username, '@')) {
2442 strncat(invite, "@", 1);
2443 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2446 len = strlen(invite);
2447 if (!channel->invite_list)
2448 channel->invite_list = silc_calloc(len + 2,
2449 sizeof(*channel->invite_list));
2451 channel->invite_list = silc_realloc(channel->invite_list,
2452 sizeof(*channel->invite_list) *
2454 strlen(channel->invite_list) + 2));
2455 strncat(channel->invite_list, invite, len);
2456 strncat(channel->invite_list, ",", 1);
2458 /* Send notify to the client that is invited to the channel */
2459 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2460 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2461 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2463 SILC_NOTIFY_TYPE_INVITE, 3,
2464 idp->data, idp->len,
2465 channel->channel_name,
2466 strlen(channel->channel_name),
2467 idp2->data, idp2->len);
2468 silc_buffer_free(idp);
2469 silc_buffer_free(idp2);
2472 /* Add the client to the invite list of the channel */
2473 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2475 if (!channel->invite_list)
2476 channel->invite_list = silc_calloc(len + 2,
2477 sizeof(*channel->invite_list));
2479 channel->invite_list = silc_realloc(channel->invite_list,
2480 sizeof(*channel->invite_list) *
2482 strlen(channel->invite_list) + 2));
2483 if (add[len - 1] == ',')
2484 add[len - 1] = '\0';
2486 strncat(channel->invite_list, add, len);
2487 strncat(channel->invite_list, ",", 1);
2490 /* Get the invite to be removed and remove it from the list */
2491 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2492 if (del && channel->invite_list) {
2493 char *start, *end, *n;
2495 if (!strncmp(channel->invite_list, del,
2496 strlen(channel->invite_list) - 1)) {
2497 silc_free(channel->invite_list);
2498 channel->invite_list = NULL;
2500 start = strstr(channel->invite_list, del);
2501 if (start && strlen(start) >= len) {
2503 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2504 strncat(n, channel->invite_list, start - channel->invite_list);
2505 strncat(n, end + 1, ((channel->invite_list +
2506 strlen(channel->invite_list)) - end) - 1);
2507 silc_free(channel->invite_list);
2508 channel->invite_list = n;
2513 /* Send notify to the primary router */
2514 if (!server->standalone)
2515 silc_server_send_notify_invite(server, server->router->connection,
2516 server->server_type == SILC_ROUTER ?
2517 TRUE : FALSE, channel,
2518 sender->id, add, del);
2520 /* Send command reply */
2521 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2525 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2526 SILC_STATUS_OK, ident, 2,
2528 3, channel->invite_list,
2529 channel->invite_list ?
2530 strlen(channel->invite_list) : 0);
2533 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2534 SILC_STATUS_OK, ident, 1,
2536 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2537 packet->data, packet->len, FALSE);
2538 silc_buffer_free(packet);
2542 silc_free(channel_id);
2543 silc_server_command_free(cmd);
2548 SilcSocketConnection sock;
2552 /* Quits connection to client. This gets called if client won't
2553 close the connection even when it has issued QUIT command. */
2555 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2557 QuitInternal q = (QuitInternal)context;
2559 /* Free all client specific data, such as client entry and entires
2560 on channels this client may be on. */
2561 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2563 q->sock->user_data = NULL;
2565 /* Close the connection on our side */
2566 silc_server_close_connection(q->server, q->sock);
2568 silc_free(q->signoff);
2572 /* Quits SILC session. This is the normal way to disconnect client. */
2574 SILC_SERVER_CMD_FUNC(quit)
2576 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2577 SilcServer server = cmd->server;
2578 SilcSocketConnection sock = cmd->sock;
2580 unsigned char *tmp = NULL;
2583 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2585 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2588 /* Get destination ID */
2589 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2593 q = silc_calloc(1, sizeof(*q));
2596 q->signoff = tmp ? strdup(tmp) : NULL;
2598 /* We quit the connection with little timeout */
2599 silc_schedule_task_add(server->schedule, sock->sock,
2600 silc_server_command_quit_cb, (void *)q,
2601 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2604 silc_server_command_free(cmd);
2607 /* Server side of command KILL. This command is used by router operator
2608 to remove an client from the SILC Network temporarily. */
2610 SILC_SERVER_CMD_FUNC(kill)
2612 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2613 SilcServer server = cmd->server;
2614 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2615 SilcClientEntry remote_client;
2616 SilcClientID *client_id;
2617 unsigned char *tmp, *comment;
2618 uint32 tmp_len, tmp_len2;
2620 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2622 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2625 /* KILL command works only on router */
2626 if (server->server_type != SILC_ROUTER) {
2627 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2628 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2632 /* Check whether client has the permissions. */
2633 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2634 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2635 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2639 /* Get the client ID */
2640 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2642 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2643 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2646 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2648 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2649 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2653 /* Get the client entry */
2654 remote_client = silc_idlist_find_client_by_id(server->local_list,
2655 client_id, TRUE, NULL);
2656 if (!remote_client) {
2657 remote_client = silc_idlist_find_client_by_id(server->global_list,
2658 client_id, TRUE, NULL);
2659 if (!remote_client) {
2660 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2661 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2667 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2671 /* Send reply to the sender */
2672 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2675 /* Send the KILL notify packets. First send it to the channel, then
2676 to our primary router and then directly to the client who is being
2677 killed right now. */
2679 /* Send KILLED notify to the channels. It is not sent to the client
2680 as it will be sent differently destined directly to the client and not
2682 silc_server_send_notify_on_channels(server, remote_client,
2683 remote_client, SILC_NOTIFY_TYPE_KILLED,
2686 comment, comment ? tmp_len2 : 0);
2688 /* Send KILLED notify to primary route */
2689 if (!server->standalone)
2690 silc_server_send_notify_killed(server, server->router->connection, TRUE,
2691 remote_client->id, comment);
2693 /* Send KILLED notify to the client directly */
2694 silc_server_send_notify_killed(server, remote_client->connection ?
2695 remote_client->connection :
2696 remote_client->router->connection, FALSE,
2697 remote_client->id, comment);
2699 /* Remove the client from all channels. This generates new keys to the
2700 channels as well. */
2701 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2704 /* Remove the client entry, If it is locally connected then we will also
2705 disconnect the client here */
2706 if (remote_client->connection) {
2707 /* Remove locally conneted client */
2708 SilcSocketConnection sock = remote_client->connection;
2709 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2710 silc_server_close_connection(server, sock);
2712 /* Remove remote client */
2713 if (!silc_idlist_del_client(server->global_list, remote_client))
2714 silc_idlist_del_client(server->local_list, remote_client);
2718 silc_server_command_free(cmd);
2721 /* Server side of command INFO. This sends information about us to
2722 the client. If client requested specific server we will send the
2723 command to that server. */
2725 SILC_SERVER_CMD_FUNC(info)
2727 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2728 SilcServer server = cmd->server;
2729 SilcBuffer packet, idp;
2732 char *dest_server, *server_info = NULL, *server_name;
2733 uint16 ident = silc_command_get_ident(cmd->payload);
2734 SilcServerEntry entry = NULL;
2735 SilcServerID *server_id = NULL;
2737 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2739 /* Get server name */
2740 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2743 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2745 server_id = silc_id_payload_parse_id(tmp, tmp_len);
2747 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2748 SILC_STATUS_ERR_NO_SERVER_ID);
2754 /* Check whether we have this server cached */
2755 entry = silc_idlist_find_server_by_id(server->local_list,
2756 server_id, TRUE, NULL);
2758 entry = silc_idlist_find_server_by_id(server->global_list,
2759 server_id, TRUE, NULL);
2760 if (!entry && server->server_type != SILC_SERVER) {
2761 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2762 SILC_STATUS_ERR_NO_SUCH_SERVER);
2768 /* Some buggy servers has sent request to router about themselves. */
2769 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2772 if ((!dest_server && !server_id && !entry) || (entry &&
2773 entry == server->id_entry) ||
2774 (dest_server && !cmd->pending &&
2775 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2776 /* Send our reply */
2777 char info_string[256];
2779 memset(info_string, 0, sizeof(info_string));
2780 snprintf(info_string, sizeof(info_string),
2781 "location: %s server: %s admin: %s <%s>",
2782 server->config->admin_info->location,
2783 server->config->admin_info->server_type,
2784 server->config->admin_info->admin_name,
2785 server->config->admin_info->admin_email);
2787 server_info = info_string;
2788 entry = server->id_entry;
2790 /* Check whether we have this server cached */
2791 if (!entry && dest_server) {
2792 entry = silc_idlist_find_server_by_name(server->global_list,
2793 dest_server, TRUE, NULL);
2795 entry = silc_idlist_find_server_by_name(server->local_list,
2796 dest_server, TRUE, NULL);
2800 if (!cmd->pending &&
2801 server->server_type != SILC_SERVER && entry && !entry->server_info) {
2802 /* Send to the server */
2806 old_ident = silc_command_get_ident(cmd->payload);
2807 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2808 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2810 silc_server_packet_send(server, entry->connection,
2811 SILC_PACKET_COMMAND, cmd->packet->flags,
2812 tmpbuf->data, tmpbuf->len, TRUE);
2814 /* Reprocess this packet after received reply from router */
2815 silc_server_command_pending(server, SILC_COMMAND_INFO,
2816 silc_command_get_ident(cmd->payload),
2817 silc_server_command_destructor,
2818 silc_server_command_info,
2819 silc_server_command_dup(cmd));
2820 cmd->pending = TRUE;
2821 silc_command_set_ident(cmd->payload, old_ident);
2822 silc_buffer_free(tmpbuf);
2826 if (!entry && !cmd->pending && !server->standalone) {
2827 /* Send to the primary router */
2831 old_ident = silc_command_get_ident(cmd->payload);
2832 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2833 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2835 silc_server_packet_send(server, server->router->connection,
2836 SILC_PACKET_COMMAND, cmd->packet->flags,
2837 tmpbuf->data, tmpbuf->len, TRUE);
2839 /* Reprocess this packet after received reply from router */
2840 silc_server_command_pending(server, SILC_COMMAND_INFO,
2841 silc_command_get_ident(cmd->payload),
2842 silc_server_command_destructor,
2843 silc_server_command_info,
2844 silc_server_command_dup(cmd));
2845 cmd->pending = TRUE;
2846 silc_command_set_ident(cmd->payload, old_ident);
2847 silc_buffer_free(tmpbuf);
2852 silc_free(server_id);
2855 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2856 SILC_STATUS_ERR_NO_SUCH_SERVER);
2860 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2862 server_info = entry->server_info;
2863 server_name = entry->server_name;
2865 /* Send the reply */
2866 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2867 SILC_STATUS_OK, ident, 3,
2868 2, idp->data, idp->len,
2870 strlen(server_name),
2873 strlen(server_info) : 0);
2874 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2875 packet->data, packet->len, FALSE);
2877 silc_buffer_free(packet);
2878 silc_buffer_free(idp);
2881 silc_server_command_free(cmd);
2884 /* Server side of command PING. This just replies to the ping. */
2886 SILC_SERVER_CMD_FUNC(ping)
2888 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2889 SilcServer server = cmd->server;
2894 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
2897 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2899 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2900 SILC_STATUS_ERR_NO_SERVER_ID);
2903 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2907 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2908 /* Send our reply */
2909 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2912 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2913 SILC_STATUS_ERR_NO_SUCH_SERVER);
2920 silc_server_command_free(cmd);
2923 /* Internal routine to join channel. The channel sent to this function
2924 has been either created or resolved from ID lists. This joins the sent
2925 client to the channel. */
2927 static void silc_server_command_join_channel(SilcServer server,
2928 SilcServerCommandContext cmd,
2929 SilcChannelEntry channel,
2930 SilcClientID *client_id,
2934 const unsigned char *auth,
2937 SilcSocketConnection sock = cmd->sock;
2939 uint32 tmp_len, user_count;
2940 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
2941 SilcClientEntry client;
2942 SilcChannelClientEntry chl;
2943 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
2944 uint16 ident = silc_command_get_ident(cmd->payload);
2945 char check[512], check2[512];
2946 bool founder = FALSE;
2948 SILC_LOG_DEBUG(("Start"));
2953 /* Get the client entry */
2954 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2955 client = (SilcClientEntry)sock->user_data;
2957 client = silc_server_get_client_resolve(server, client_id);
2962 /* The client info is being resolved. Reprocess this packet after
2963 receiving the reply to the query. */
2964 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2965 server->cmd_ident, NULL,
2966 silc_server_command_join,
2967 silc_server_command_dup(cmd));
2968 cmd->pending = TRUE;
2972 cmd->pending = FALSE;
2976 * Check founder auth payload if provided. If client can gain founder
2977 * privileges it can override various conditions on joining the channel,
2978 * and can have directly the founder mode set on the channel.
2980 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
2981 SilcIDListData idata = (SilcIDListData)client;
2983 if (channel->founder_key && idata->public_key &&
2984 silc_pkcs_public_key_compare(channel->founder_key,
2985 idata->public_key)) {
2986 void *auth_data = (channel->founder_method == SILC_AUTH_PASSWORD ?
2987 (void *)channel->founder_passwd :
2988 (void *)channel->founder_key);
2989 uint32 auth_data_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
2990 channel->founder_passwd_len : 0);
2992 /* Check whether the client is to become founder */
2993 if (silc_auth_verify_data(auth, auth_len, channel->founder_method,
2994 auth_data, auth_data_len,
2995 idata->hash, client->id, SILC_ID_CLIENT)) {
2996 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3003 * Check channel modes
3007 memset(check, 0, sizeof(check));
3008 memset(check2, 0, sizeof(check2));
3009 strncat(check, client->nickname, strlen(client->nickname));
3010 strncat(check, "!", 1);
3011 strncat(check, client->username, strlen(client->username));
3012 if (!strchr(client->username, '@')) {
3013 strncat(check, "@", 1);
3014 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3017 strncat(check2, client->nickname, strlen(client->nickname));
3018 if (!strchr(client->nickname, '@')) {
3019 strncat(check2, "@", 1);
3020 strncat(check2, server->server_name, strlen(server->server_name));
3022 strncat(check2, "!", 1);
3023 strncat(check2, client->username, strlen(client->username));
3024 if (!strchr(client->username, '@')) {
3025 strncat(check2, "@", 1);
3026 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3029 /* Check invite list if channel is invite-only channel */
3030 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3031 if (!channel->invite_list ||
3032 (!silc_string_match(channel->invite_list, check) &&
3033 !silc_string_match(channel->invite_list, check2))) {
3034 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3035 SILC_STATUS_ERR_NOT_INVITED);
3040 /* Check ban list if it exists. If the client's nickname, server,
3041 username and/or hostname is in the ban list the access to the
3042 channel is denied. */
3043 if (channel->ban_list) {
3044 if (!channel->ban_list ||
3045 silc_string_match(channel->ban_list, check) ||
3046 silc_string_match(channel->ban_list, check2)) {
3047 silc_server_command_send_status_reply(
3048 cmd, SILC_COMMAND_JOIN,
3049 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
3054 /* Check user count limit if set. */
3055 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3056 if (silc_hash_table_count(channel->user_list) + 1 >
3057 channel->user_limit) {
3058 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3059 SILC_STATUS_ERR_CHANNEL_IS_FULL);
3065 /* Check the channel passphrase if set. */
3066 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3067 /* Get passphrase */
3068 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3070 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
3071 memcpy(passphrase, tmp, tmp_len);
3074 if (!passphrase || !channel->passphrase ||
3075 memcmp(channel->passphrase, passphrase,
3076 strlen(channel->passphrase))) {
3077 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3078 SILC_STATUS_ERR_BAD_PASSWORD);
3084 * Client is allowed to join to the channel. Make it happen.
3087 /* Check whether the client already is on the channel */
3088 if (silc_server_client_on_channel(client, channel)) {
3089 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3090 SILC_STATUS_ERR_USER_ON_CHANNEL);
3094 /* Generate new channel key as protocol dictates */
3096 if (!silc_server_create_channel_key(server, channel, 0))
3099 /* Send the channel key. This is broadcasted to the channel but is not
3100 sent to the client who is joining to the channel. */
3101 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3102 silc_server_send_channel_key(server, NULL, channel,
3103 server->server_type == SILC_ROUTER ?
3104 FALSE : !server->standalone);
3107 /* Join the client to the channel by adding it to channel's user list.
3108 Add also the channel to client entry's channels list for fast cross-
3110 chl = silc_calloc(1, sizeof(*chl));
3112 chl->client = client;
3113 chl->channel = channel;
3114 silc_hash_table_add(channel->user_list, client, chl);
3115 silc_hash_table_add(client->channels, channel, chl);
3117 /* Get users on the channel */
3118 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3121 /* Encode Client ID Payload of the original client who wants to join */
3122 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3124 /* Encode command reply packet */
3125 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3126 SILC_PUT32_MSB(channel->mode, mode);
3127 SILC_PUT32_MSB(created, tmp2);
3128 SILC_PUT32_MSB(user_count, tmp3);
3130 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3131 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3132 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
3133 strlen(channel->channel_key->
3135 channel->channel_key->cipher->name,
3136 channel->key_len / 8, channel->key);
3141 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3142 SILC_STATUS_OK, ident, 13,
3143 2, channel->channel_name,
3144 strlen(channel->channel_name),
3145 3, chidp->data, chidp->len,
3146 4, clidp->data, clidp->len,
3149 7, keyp ? keyp->data : NULL,
3150 keyp ? keyp->len : 0,
3151 8, channel->ban_list,
3153 strlen(channel->ban_list) : 0,
3154 9, channel->invite_list,
3155 channel->invite_list ?
3156 strlen(channel->invite_list) : 0,
3159 strlen(channel->topic) : 0,
3160 11, silc_hmac_get_name(channel->hmac),
3161 strlen(silc_hmac_get_name(channel->
3164 13, user_list->data, user_list->len,
3165 14, mode_list->data,
3168 /* Send command reply */
3169 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3170 reply->data, reply->len, FALSE);
3172 /* Send JOIN notify to locally connected clients on the channel. If
3173 we are normal server then router will send or have sent JOIN notify
3174 already. However since we've added the client already to our channel
3175 we'll ignore it (in packet_receive.c) so we must send it here. If
3176 we are router then this will send it to local clients and local
3178 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3179 SILC_NOTIFY_TYPE_JOIN, 2,
3180 clidp->data, clidp->len,
3181 chidp->data, chidp->len);
3183 if (!cmd->pending) {
3184 /* Send JOIN notify packet to our primary router */
3185 if (!server->standalone)
3186 silc_server_send_notify_join(server, server->router->connection,
3187 server->server_type == SILC_ROUTER ?
3188 TRUE : FALSE, channel, client->id);
3191 /* Distribute the channel key to all backup routers. */
3192 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3193 keyp->data, keyp->len, FALSE, TRUE);
3195 /* If client became founder by providing correct founder auth data
3196 notify the mode change to the channel. */
3198 SILC_PUT32_MSB(chl->mode, mode);
3199 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3200 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3201 clidp->data, clidp->len,
3202 mode, 4, clidp->data, clidp->len);
3204 /* Set CUMODE notify type to network */
3205 if (!server->standalone)
3206 silc_server_send_notify_cumode(server, server->router->connection,
3207 server->server_type == SILC_ROUTER ?
3208 TRUE : FALSE, channel,
3209 chl->mode, client->id, SILC_ID_CLIENT,
3214 silc_buffer_free(reply);
3215 silc_buffer_free(clidp);
3216 silc_buffer_free(chidp);
3217 silc_buffer_free(keyp);
3218 silc_buffer_free(user_list);
3219 silc_buffer_free(mode_list);
3222 silc_free(passphrase);
3225 /* Server side of command JOIN. Joins client into requested channel. If
3226 the channel does not exist it will be created. */
3228 SILC_SERVER_CMD_FUNC(join)
3230 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3231 SilcServer server = cmd->server;
3232 unsigned char *auth;
3233 uint32 tmp_len, auth_len;
3234 char *tmp, *channel_name = NULL, *cipher, *hmac;
3235 SilcChannelEntry channel;
3237 bool created = FALSE, create_key = TRUE;
3238 SilcClientID *client_id;
3240 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3242 /* Get channel name */
3243 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3245 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3246 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3251 if (strlen(channel_name) > 256)
3252 channel_name[255] = '\0';
3254 if (silc_server_command_bad_chars(channel_name) == TRUE) {
3255 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3256 SILC_STATUS_ERR_BAD_CHANNEL);
3260 /* Get Client ID of the client who is joining to the channel */
3261 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3263 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3264 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3267 client_id = silc_id_payload_parse_id(tmp, tmp_len);
3269 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3270 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3274 /* Get cipher, hmac name and auth payload */
3275 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3276 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3277 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3279 /* See if the channel exists */
3280 channel = silc_idlist_find_channel_by_name(server->local_list,
3281 channel_name, NULL);
3283 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3284 /* If this is coming from client the Client ID in the command packet must
3285 be same as the client's ID. */
3286 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3287 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3288 if (!SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
3289 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3290 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3295 if (!channel || channel->disabled) {
3296 /* Channel not found */
3298 /* If we are standalone server we don't have a router, we just create
3299 the channel by ourselves. */
3300 if (server->standalone) {
3301 channel = silc_server_create_new_channel(server, server->id, cipher,
3302 hmac, channel_name, TRUE);
3304 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3305 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3309 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3315 /* The channel does not exist on our server. If we are normal server
3316 we will send JOIN command to our router which will handle the
3317 joining procedure (either creates the channel if it doesn't exist
3318 or joins the client to it). */
3319 if (server->server_type != SILC_ROUTER) {
3323 /* If this is pending command callback then we've resolved
3324 it and it didn't work, return since we've notified the
3325 client already in the command reply callback. */
3329 old_ident = silc_command_get_ident(cmd->payload);
3330 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3331 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3333 /* Send JOIN command to our router */
3334 silc_server_packet_send(server, (SilcSocketConnection)
3335 server->router->connection,
3336 SILC_PACKET_COMMAND, cmd->packet->flags,
3337 tmpbuf->data, tmpbuf->len, TRUE);
3339 /* Reprocess this packet after received reply from router */
3340 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3341 silc_command_get_ident(cmd->payload),
3342 silc_server_command_destructor,
3343 silc_server_command_join,
3344 silc_server_command_dup(cmd));
3345 cmd->pending = TRUE;
3349 /* We are router and the channel does not seem exist so we will check
3350 our global list as well for the channel. */
3351 channel = silc_idlist_find_channel_by_name(server->global_list,
3352 channel_name, NULL);
3354 /* Channel really does not exist, create it */
3355 channel = silc_server_create_new_channel(server, server->id, cipher,
3356 hmac, channel_name, TRUE);
3358 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3359 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3363 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3371 /* Channel not found */
3373 /* If the command came from router and we are normal server then
3374 something went wrong with the joining as the channel was not found.
3375 We can't do anything else but ignore this. */
3376 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3377 server->server_type != SILC_ROUTER)
3380 /* We are router and the channel does not seem exist so we will check
3381 our global list as well for the channel. */
3382 channel = silc_idlist_find_channel_by_name(server->global_list,
3383 channel_name, NULL);
3385 /* Channel really does not exist, create it */
3386 channel = silc_server_create_new_channel(server, server->id, cipher,
3387 hmac, channel_name, TRUE);
3389 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3390 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3394 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3401 /* Check whether the channel was created by our router */
3402 if (cmd->pending && context2) {
3403 SilcServerCommandReplyContext reply =
3404 (SilcServerCommandReplyContext)context2;
3405 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3406 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3407 SILC_GET32_MSB(created, tmp);
3408 create_key = FALSE; /* Router returned the key already */
3412 /* If the channel does not have global users and is also empty the client
3413 will be the channel founder and operator. */
3414 if (!channel->global_users && !silc_hash_table_count(channel->user_list))
3415 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3417 /* Join to the channel */
3418 silc_server_command_join_channel(server, cmd, channel, client_id,
3419 created, create_key, umode,
3422 silc_free(client_id);
3425 silc_server_command_free(cmd);
3428 /* Server side of command MOTD. Sends server's current "message of the
3429 day" to the client. */
3431 SILC_SERVER_CMD_FUNC(motd)
3433 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3434 SilcServer server = cmd->server;
3435 SilcBuffer packet, idp;
3436 char *motd, *dest_server;
3438 uint16 ident = silc_command_get_ident(cmd->payload);
3440 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3442 /* Get server name */
3443 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3445 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3446 SILC_STATUS_ERR_NO_SUCH_SERVER);
3450 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3453 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3455 if (server->config && server->config->motd &&
3456 server->config->motd->motd_file) {
3458 motd = silc_file_readfile(server->config->motd->motd_file, &motd_len);
3463 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3464 SILC_STATUS_OK, ident, 2,
3469 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3470 SILC_STATUS_OK, ident, 1,
3474 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3475 packet->data, packet->len, FALSE);
3476 silc_buffer_free(packet);
3477 silc_buffer_free(idp);
3479 SilcServerEntry entry;
3481 /* Check whether we have this server cached */
3482 entry = silc_idlist_find_server_by_name(server->global_list,
3483 dest_server, TRUE, NULL);
3485 entry = silc_idlist_find_server_by_name(server->local_list,
3486 dest_server, TRUE, NULL);
3489 if (server->server_type != SILC_SERVER && !cmd->pending &&
3490 entry && !entry->motd) {
3491 /* Send to the server */
3495 old_ident = silc_command_get_ident(cmd->payload);
3496 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3497 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3499 silc_server_packet_send(server, entry->connection,
3500 SILC_PACKET_COMMAND, cmd->packet->flags,
3501 tmpbuf->data, tmpbuf->len, TRUE);
3503 /* Reprocess this packet after received reply from router */
3504 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3505 silc_command_get_ident(cmd->payload),
3506 silc_server_command_destructor,
3507 silc_server_command_motd,
3508 silc_server_command_dup(cmd));
3509 cmd->pending = TRUE;
3510 silc_command_set_ident(cmd->payload, old_ident);
3511 silc_buffer_free(tmpbuf);
3515 if (!entry && !cmd->pending && !server->standalone) {
3516 /* Send to the primary router */
3520 old_ident = silc_command_get_ident(cmd->payload);
3521 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3522 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3524 silc_server_packet_send(server, server->router->connection,
3525 SILC_PACKET_COMMAND, cmd->packet->flags,
3526 tmpbuf->data, tmpbuf->len, TRUE);
3528 /* Reprocess this packet after received reply from router */
3529 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3530 silc_command_get_ident(cmd->payload),
3531 silc_server_command_destructor,
3532 silc_server_command_motd,
3533 silc_server_command_dup(cmd));
3534 cmd->pending = TRUE;
3535 silc_command_set_ident(cmd->payload, old_ident);
3536 silc_buffer_free(tmpbuf);
3541 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3542 SILC_STATUS_ERR_NO_SUCH_SERVER);
3546 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3547 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3548 SILC_STATUS_OK, ident, 2,
3552 strlen(entry->motd) : 0);
3553 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3554 packet->data, packet->len, FALSE);
3555 silc_buffer_free(packet);
3556 silc_buffer_free(idp);
3560 silc_server_command_free(cmd);
3563 /* Server side of command UMODE. Client can use this command to set/unset
3564 user mode. Client actually cannot set itself to be as server/router
3565 operator so this can be used only to unset the modes. */
3567 SILC_SERVER_CMD_FUNC(umode)
3569 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3570 SilcServer server = cmd->server;
3571 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3573 unsigned char *tmp_mask;
3575 uint16 ident = silc_command_get_ident(cmd->payload);
3577 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3580 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 2, 2);
3582 /* Get the client's mode mask */
3583 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3585 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3586 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3589 SILC_GET32_MSB(mask, tmp_mask);
3595 if (mask & SILC_UMODE_SERVER_OPERATOR) {
3596 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR)) {
3597 /* Cannot operator mode */
3598 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3599 SILC_STATUS_ERR_PERM_DENIED);
3603 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
3604 /* Remove the server operator rights */
3605 client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3608 if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3609 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
3610 /* Cannot operator mode */
3611 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3612 SILC_STATUS_ERR_PERM_DENIED);
3616 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
3617 /* Remove the router operator rights */
3618 client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3621 if (mask & SILC_UMODE_GONE) {
3622 client->mode |= SILC_UMODE_GONE;
3624 if (client->mode & SILC_UMODE_GONE)
3625 /* Remove the gone status */
3626 client->mode &= ~SILC_UMODE_GONE;
3629 /* Send UMODE change to primary router */
3630 if (!server->standalone)
3631 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3632 client->id, client->mode);
3634 /* Send command reply to sender */
3635 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3636 SILC_STATUS_OK, ident, 1,
3638 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3639 packet->data, packet->len, FALSE);
3640 silc_buffer_free(packet);
3643 silc_server_command_free(cmd);
3646 /* Checks that client has rights to add or remove channel modes. If any
3647 of the checks fails FALSE is returned. */
3649 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3650 SilcChannelClientEntry client,
3653 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3654 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3656 /* Check whether has rights to change anything */
3657 if (!is_op && !is_fo)
3660 /* Check whether has rights to change everything */
3664 /* We know that client is channel operator, check that they are not
3665 changing anything that requires channel founder rights. Rest of the
3666 modes are available automatically for channel operator. */
3668 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3669 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3670 if (is_op && !is_fo)
3673 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3674 if (is_op && !is_fo)
3679 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3680 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE))
3681 if (is_op && !is_fo)
3684 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3685 if (is_op && !is_fo)
3690 if (mode & SILC_CHANNEL_MODE_CIPHER) {
3691 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER))
3692 if (is_op && !is_fo)
3695 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3696 if (is_op && !is_fo)
3701 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3702 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH))
3703 if (is_op && !is_fo)
3706 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3707 if (is_op && !is_fo)
3715 /* Server side command of CMODE. Changes channel mode */
3717 SILC_SERVER_CMD_FUNC(cmode)
3719 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3720 SilcServer server = cmd->server;
3721 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3722 SilcIDListData idata = (SilcIDListData)client;
3723 SilcChannelID *channel_id;
3724 SilcChannelEntry channel;
3725 SilcChannelClientEntry chl;
3726 SilcBuffer packet, cidp;
3727 unsigned char *tmp, *tmp_id, *tmp_mask;
3728 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3729 uint32 mode_mask, tmp_len, tmp_len2;
3730 uint16 ident = silc_command_get_ident(cmd->payload);
3732 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 2, 7);
3734 /* Get Channel ID */
3735 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3737 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3738 SILC_STATUS_ERR_NO_CHANNEL_ID);
3741 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3743 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3744 SILC_STATUS_ERR_NO_CHANNEL_ID);
3748 /* Get the channel mode mask */
3749 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3751 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3752 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3755 SILC_GET32_MSB(mode_mask, tmp_mask);
3757 /* Get channel entry */
3758 channel = silc_idlist_find_channel_by_id(server->local_list,
3761 channel = silc_idlist_find_channel_by_id(server->global_list,
3764 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3765 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3770 /* Check whether this client is on the channel */
3771 if (!silc_server_client_on_channel(client, channel)) {
3772 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3773 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3777 /* Get entry to the channel user list */
3778 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
3780 /* Check that client has rights to change any requested channel modes */
3781 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3782 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3783 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3788 * Check the modes. Modes that requires nothing special operation are
3792 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3793 /* Channel uses private keys to protect traffic. Client(s) has set the
3794 key locally they want to use, server does not know that key. */
3795 /* Nothing interesting to do here */
3797 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3798 /* The mode is removed and we need to generate and distribute
3799 new channel key. Clients are not using private channel keys
3800 anymore after this. */
3802 /* Re-generate channel key */
3803 if (!silc_server_create_channel_key(server, channel, 0))
3806 /* Send the channel key. This sends it to our local clients and if
3807 we are normal server to our router as well. */
3808 silc_server_send_channel_key(server, NULL, channel,
3809 server->server_type == SILC_ROUTER ?
3810 FALSE : !server->standalone);
3812 cipher = channel->channel_key->cipher->name;
3813 hmac = (char *)silc_hmac_get_name(channel->hmac);
3817 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3818 /* User limit is set on channel */
3821 /* Get user limit */
3822 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3824 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3825 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3826 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3830 SILC_GET32_MSB(user_limit, tmp);
3831 channel->user_limit = user_limit;
3834 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3835 /* User limit mode is unset. Remove user limit */
3836 channel->user_limit = 0;
3839 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3840 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3841 /* Passphrase has been set to channel */
3843 /* Get the passphrase */
3844 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3846 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3847 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3851 /* Save the passphrase */
3852 passphrase = channel->passphrase = strdup(tmp);
3855 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3856 /* Passphrase mode is unset. remove the passphrase */
3857 if (channel->passphrase) {
3858 silc_free(channel->passphrase);
3859 channel->passphrase = NULL;
3864 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3865 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3866 /* Cipher to use protect the traffic */
3867 SilcCipher newkey, oldkey;
3870 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3872 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3873 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3877 /* Delete old cipher and allocate the new one */
3878 if (!silc_cipher_alloc(cipher, &newkey)) {
3879 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3880 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3884 oldkey = channel->channel_key;
3885 channel->channel_key = newkey;
3887 /* Re-generate channel key */
3888 if (!silc_server_create_channel_key(server, channel, 0)) {
3889 /* We don't have new key, revert to old one */
3890 channel->channel_key = oldkey;
3894 /* Remove old channel key for good */
3895 silc_cipher_free(oldkey);
3897 /* Send the channel key. This sends it to our local clients and if
3898 we are normal server to our router as well. */
3899 silc_server_send_channel_key(server, NULL, channel,
3900 server->server_type == SILC_ROUTER ?
3901 FALSE : !server->standalone);
3904 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3905 /* Cipher mode is unset. Remove the cipher and revert back to
3907 SilcCipher newkey, oldkey;
3908 cipher = channel->cipher;
3910 /* Delete old cipher and allocate default one */
3911 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
3912 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3913 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3917 oldkey = channel->channel_key;
3918 channel->channel_key = newkey;
3920 /* Re-generate channel key */
3921 if (!silc_server_create_channel_key(server, channel, 0)) {
3922 /* We don't have new key, revert to old one */
3923 channel->channel_key = oldkey;
3927 /* Remove old channel key for good */
3928 silc_cipher_free(oldkey);
3930 /* Send the channel key. This sends it to our local clients and if
3931 we are normal server to our router as well. */
3932 silc_server_send_channel_key(server, NULL, channel,
3933 server->server_type == SILC_ROUTER ?
3934 FALSE : !server->standalone);
3938 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3939 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3940 /* HMAC to use protect the traffic */
3941 unsigned char hash[32];
3945 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3947 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3948 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3952 /* Delete old hmac and allocate the new one */
3953 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
3954 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3955 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3959 silc_hmac_free(channel->hmac);
3960 channel->hmac = newhmac;
3962 /* Set the HMAC key out of current channel key. The client must do
3964 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
3965 channel->key_len / 8, hash);
3966 silc_hmac_set_key(channel->hmac, hash,
3967 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3968 memset(hash, 0, sizeof(hash));
3971 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
3972 /* Hmac mode is unset. Remove the hmac and revert back to
3975 unsigned char hash[32];
3976 hmac = channel->hmac_name;
3978 /* Delete old hmac and allocate default one */
3979 silc_hmac_free(channel->hmac);
3980 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
3981 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3982 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3986 silc_hmac_free(channel->hmac);
3987 channel->hmac = newhmac;
3989 /* Set the HMAC key out of current channel key. The client must do
3991 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
3992 channel->key_len / 8,
3994 silc_hmac_set_key(channel->hmac, hash,
3995 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3996 memset(hash, 0, sizeof(hash));
4000 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4001 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4002 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4003 /* Set the founder authentication */
4004 SilcAuthPayload auth;
4006 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4008 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4009 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4013 auth = silc_auth_payload_parse(tmp, tmp_len);
4015 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4016 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4020 /* Save the public key */
4021 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
4022 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
4025 channel->founder_method = silc_auth_get_method(auth);
4027 if (channel->founder_method == SILC_AUTH_PASSWORD) {
4028 tmp = silc_auth_get_data(auth, &tmp_len);
4029 channel->founder_passwd =
4030 silc_calloc(tmp_len + 1, sizeof(*channel->founder_passwd));
4031 memcpy(channel->founder_passwd, tmp, tmp_len);
4032 channel->founder_passwd_len = tmp_len;
4034 /* Verify the payload before setting the mode */
4035 if (!silc_auth_verify(auth, channel->founder_method,
4036 channel->founder_key, 0, idata->hash,
4037 client->id, SILC_ID_CLIENT)) {
4038 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4039 SILC_STATUS_ERR_AUTH_FAILED);
4044 silc_auth_payload_free(auth);
4048 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4049 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4050 if (channel->founder_key)
4051 silc_pkcs_public_key_free(channel->founder_key);
4052 if (channel->founder_passwd) {
4053 silc_free(channel->founder_passwd);
4054 channel->founder_passwd = NULL;
4060 /* Finally, set the mode */
4061 channel->mode = mode_mask;
4063 /* Send CMODE_CHANGE notify. */
4064 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4065 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4066 SILC_NOTIFY_TYPE_CMODE_CHANGE, 5,
4067 cidp->data, cidp->len,
4069 cipher, cipher ? strlen(cipher) : 0,
4070 hmac, hmac ? strlen(hmac) : 0,
4071 passphrase, passphrase ?
4072 strlen(passphrase) : 0);
4074 /* Set CMODE notify type to network */
4075 if (!server->standalone)
4076 silc_server_send_notify_cmode(server, server->router->connection,
4077 server->server_type == SILC_ROUTER ?
4078 TRUE : FALSE, channel,
4079 mode_mask, client->id, SILC_ID_CLIENT,
4080 cipher, hmac, passphrase);
4082 /* Send command reply to sender */
4083 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4084 SILC_STATUS_OK, ident, 2,
4085 2, tmp_id, tmp_len2,
4087 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4088 packet->data, packet->len, FALSE);
4090 silc_buffer_free(packet);
4091 silc_free(channel_id);
4092 silc_buffer_free(cidp);
4095 silc_server_command_free(cmd);
4098 /* Server side of CUMODE command. Changes client's mode on a channel. */
4100 SILC_SERVER_CMD_FUNC(cumode)
4102 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4103 SilcServer server = cmd->server;
4104 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4105 SilcIDListData idata = (SilcIDListData)client;
4106 SilcChannelID *channel_id;
4107 SilcClientID *client_id;
4108 SilcChannelEntry channel;
4109 SilcClientEntry target_client;
4110 SilcChannelClientEntry chl;
4111 SilcBuffer packet, idp;
4112 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4113 uint32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4115 uint16 ident = silc_command_get_ident(cmd->payload);
4117 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4119 /* Get Channel ID */
4120 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4122 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4123 SILC_STATUS_ERR_NO_CHANNEL_ID);
4126 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
4128 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4129 SILC_STATUS_ERR_NO_CHANNEL_ID);
4133 /* Get channel entry */
4134 channel = silc_idlist_find_channel_by_id(server->local_list,
4137 channel = silc_idlist_find_channel_by_id(server->global_list,
4140 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4141 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4146 /* Check whether sender is on the channel */
4147 if (!silc_server_client_on_channel(client, channel)) {
4148 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4149 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4153 /* Check that client has rights to change other's rights */
4154 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4155 sender_mask = chl->mode;
4157 /* Get the target client's channel mode mask */
4158 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4160 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4161 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4164 SILC_GET32_MSB(target_mask, tmp_mask);
4166 /* Get target Client ID */
4167 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4169 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4170 SILC_STATUS_ERR_NO_CLIENT_ID);
4173 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
4175 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4176 SILC_STATUS_ERR_NO_CLIENT_ID);
4180 /* Get target client's entry */
4181 target_client = silc_idlist_find_client_by_id(server->local_list,
4182 client_id, TRUE, NULL);
4183 if (!target_client) {
4184 target_client = silc_idlist_find_client_by_id(server->global_list,
4185 client_id, TRUE, NULL);
4188 if (target_client != client &&
4189 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4190 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4191 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4192 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4196 /* Check whether target client is on the channel */
4197 if (target_client != client) {
4198 if (!silc_server_client_on_channel(target_client, channel)) {
4199 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4200 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4204 /* Get entry to the channel user list */
4205 silc_hash_table_find(channel->user_list, target_client, NULL,
4213 /* If the target client is founder, no one else can change their mode
4215 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
4216 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4217 SILC_STATUS_ERR_NOT_YOU);
4221 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4222 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4223 /* The client tries to claim the founder rights. */
4224 unsigned char *tmp_auth;
4225 uint32 tmp_auth_len, auth_len;
4228 if (target_client != client) {
4229 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4230 SILC_STATUS_ERR_NOT_YOU);
4234 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4235 !channel->founder_key || !idata->public_key ||
4236 !silc_pkcs_public_key_compare(channel->founder_key,
4237 idata->public_key)) {
4238 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4239 SILC_STATUS_ERR_NOT_YOU);
4243 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4245 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4246 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4250 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4251 (void *)channel->founder_passwd : (void *)channel->founder_key);
4252 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4253 channel->founder_passwd_len : 0);
4255 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4256 channel->founder_method, auth, auth_len,
4257 idata->hash, client->id, SILC_ID_CLIENT)) {
4258 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4259 SILC_STATUS_ERR_AUTH_FAILED);
4263 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4267 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4268 if (target_client == client) {
4269 /* Remove channel founder rights from itself */
4270 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4273 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4274 SILC_STATUS_ERR_NOT_YOU);
4280 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4281 /* Promote to operator */
4282 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4283 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4284 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4285 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4286 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4290 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4294 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4295 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4296 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4297 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4298 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4302 /* Demote to normal user */
4303 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4308 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4309 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4311 /* Send notify to channel, notify only if mode was actually changed. */
4313 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4314 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4315 idp->data, idp->len,
4319 /* Set CUMODE notify type to network */
4320 if (!server->standalone)
4321 silc_server_send_notify_cumode(server, server->router->connection,
4322 server->server_type == SILC_ROUTER ?
4323 TRUE : FALSE, channel,
4324 target_mask, client->id,
4329 /* Send command reply to sender */
4330 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4331 SILC_STATUS_OK, ident, 3,
4333 3, tmp_ch_id, tmp_ch_len,
4334 4, tmp_id, tmp_len);
4335 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4336 packet->data, packet->len, FALSE);
4338 silc_buffer_free(packet);
4339 silc_free(channel_id);
4340 silc_free(client_id);
4341 silc_buffer_free(idp);
4344 silc_server_command_free(cmd);
4347 /* Server side of KICK command. Kicks client out of channel. */
4349 SILC_SERVER_CMD_FUNC(kick)
4351 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4352 SilcServer server = cmd->server;
4353 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4354 SilcClientEntry target_client;
4355 SilcChannelID *channel_id;
4356 SilcClientID *client_id;
4357 SilcChannelEntry channel;
4358 SilcChannelClientEntry chl;
4360 uint32 tmp_len, target_idp_len;
4361 unsigned char *tmp, *comment, *target_idp;
4363 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4365 /* Get Channel ID */
4366 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4368 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4369 SILC_STATUS_ERR_NO_CHANNEL_ID);
4372 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
4374 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4375 SILC_STATUS_ERR_NO_CHANNEL_ID);
4379 /* Get channel entry */
4380 channel = silc_idlist_find_channel_by_id(server->local_list,
4383 channel = silc_idlist_find_channel_by_id(server->local_list,
4386 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4387 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4392 /* Check whether sender is on the channel */
4393 if (!silc_server_client_on_channel(client, channel)) {
4394 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4395 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4399 /* Check that the kicker is channel operator or channel founder */
4400 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4401 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4402 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4403 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4407 /* Get target Client ID */
4408 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4410 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4411 SILC_STATUS_ERR_NO_CLIENT_ID);
4414 client_id = silc_id_payload_parse_id(target_idp, target_idp_len);
4416 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4417 SILC_STATUS_ERR_NO_CLIENT_ID);
4421 /* Get target client's entry */
4422 target_client = silc_idlist_find_client_by_id(server->local_list,
4423 client_id, TRUE, NULL);
4424 if (!target_client) {
4425 target_client = silc_idlist_find_client_by_id(server->global_list,
4426 client_id, TRUE, NULL);
4429 /* Check that the target client is not channel founder. Channel founder
4430 cannot be kicked from the channel. */
4431 silc_hash_table_find(channel->user_list, target_client, NULL, (void *)&chl);
4432 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4433 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4434 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4438 /* Check whether target client is on the channel */
4439 if (!silc_server_client_on_channel(target_client, channel)) {
4440 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4441 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4447 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4451 /* Send command reply to sender */
4452 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4455 /* Send KICKED notify to local clients on the channel */
4456 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4457 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4458 SILC_NOTIFY_TYPE_KICKED, 3,
4459 target_idp, target_idp_len,
4460 comment, comment ? strlen(comment) : 0,
4461 idp->data, idp->len);
4462 silc_buffer_free(idp);
4464 /* Remove the client from the channel. If the channel does not exist
4465 after removing the client then the client kicked itself off the channel
4466 and we don't have to send anything after that. */
4467 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4468 target_client, FALSE))
4471 /* Send KICKED notify to primary route */
4472 if (!server->standalone)
4473 silc_server_send_notify_kicked(server, server->router->connection,
4474 server->server_type == SILC_ROUTER ?
4475 TRUE : FALSE, channel,
4476 target_client->id, comment);
4478 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4479 /* Re-generate channel key */
4480 if (!silc_server_create_channel_key(server, channel, 0))
4483 /* Send the channel key to the channel. The key of course is not sent
4484 to the client who was kicked off the channel. */
4485 silc_server_send_channel_key(server, target_client->connection, channel,
4486 server->server_type == SILC_ROUTER ?
4487 FALSE : !server->standalone);
4491 silc_server_command_free(cmd);
4494 /* Server side of OPER command. Client uses this comand to obtain server
4495 operator privileges to this server/router. */
4497 SILC_SERVER_CMD_FUNC(oper)
4499 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4500 SilcServer server = cmd->server;
4501 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4502 unsigned char *username, *auth;
4504 SilcServerConfigSectionAdminConnection *admin;
4505 SilcIDListData idata = (SilcIDListData)client;
4507 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4509 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4512 /* Get the username */
4513 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4515 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4516 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4520 /* Get the admin configuration */
4521 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4522 username, client->nickname);
4524 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4525 username, client->nickname);
4527 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4528 SILC_STATUS_ERR_AUTH_FAILED);
4533 /* Get the authentication payload */
4534 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4536 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4537 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4541 /* Verify the authentication data */
4542 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4543 admin->auth_data, admin->auth_data_len,
4544 idata->hash, client->id, SILC_ID_CLIENT)) {
4545 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4546 SILC_STATUS_ERR_AUTH_FAILED);
4550 /* Client is now server operator */
4551 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4553 /* Send UMODE change to primary router */
4554 if (!server->standalone)
4555 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4556 client->id, client->mode);
4558 /* Send reply to the sender */
4559 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4563 silc_server_command_free(cmd);
4566 /* Server side of SILCOPER command. Client uses this comand to obtain router
4567 operator privileges to this router. */
4569 SILC_SERVER_CMD_FUNC(silcoper)
4571 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4572 SilcServer server = cmd->server;
4573 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4574 unsigned char *username, *auth;
4576 SilcServerConfigSectionAdminConnection *admin;
4577 SilcIDListData idata = (SilcIDListData)client;
4579 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4581 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4584 if (server->server_type != SILC_ROUTER) {
4585 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4586 SILC_STATUS_ERR_AUTH_FAILED);
4590 /* Get the username */
4591 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4593 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4594 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4598 /* Get the admin configuration */
4599 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4600 username, client->nickname);
4602 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4603 username, client->nickname);
4605 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4606 SILC_STATUS_ERR_AUTH_FAILED);
4611 /* Get the authentication payload */
4612 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4614 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4615 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4619 /* Verify the authentication data */
4620 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4621 admin->auth_data, admin->auth_data_len,
4622 idata->hash, client->id, SILC_ID_CLIENT)) {
4623 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4624 SILC_STATUS_ERR_AUTH_FAILED);
4628 /* Client is now router operator */
4629 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4631 /* Send UMODE change to primary router */
4632 if (!server->standalone)
4633 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4634 client->id, client->mode);
4636 /* Send reply to the sender */
4637 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4641 silc_server_command_free(cmd);
4644 /* Server side command of CONNECT. Connects us to the specified remote
4645 server or router. */
4647 SILC_SERVER_CMD_FUNC(connect)
4649 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4650 SilcServer server = cmd->server;
4651 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4652 unsigned char *tmp, *host;
4654 uint32 port = SILC_PORT;
4656 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CONNECT, cmd, 1, 2);
4658 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4661 /* Check whether client has the permissions. */
4662 if (client->mode == SILC_UMODE_NONE) {
4663 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4664 SILC_STATUS_ERR_NO_SERVER_PRIV);
4668 if (server->server_type == SILC_ROUTER &&
4669 client->mode & SILC_UMODE_SERVER_OPERATOR) {
4670 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4671 SILC_STATUS_ERR_NO_ROUTER_PRIV);
4675 /* Get the remote server */
4676 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4678 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4679 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4684 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4686 SILC_GET32_MSB(port, tmp);
4688 /* Create the connection. It is done with timeout and is async. */
4689 silc_server_create_connection(server, host, port);
4691 /* Send reply to the sender */
4692 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4696 silc_server_command_free(cmd);
4699 /* Server side of command BAN. This is used to manage the ban list of the
4700 channel. To add clients and remove clients from the ban list. */
4702 SILC_SERVER_CMD_FUNC(ban)
4704 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4705 SilcServer server = cmd->server;
4706 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4708 SilcChannelEntry channel;
4709 SilcChannelClientEntry chl;
4710 SilcChannelID *channel_id = NULL;
4711 unsigned char *id, *add, *del;
4712 uint32 id_len, tmp_len;
4713 uint16 ident = silc_command_get_ident(cmd->payload);
4715 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4718 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4720 /* Get Channel ID */
4721 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4723 channel_id = silc_id_payload_parse_id(id, id_len);
4725 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4726 SILC_STATUS_ERR_NO_CHANNEL_ID);
4731 /* Get channel entry. The server must know about the channel since the
4732 client is expected to be on the channel. */
4733 channel = silc_idlist_find_channel_by_id(server->local_list,
4736 channel = silc_idlist_find_channel_by_id(server->global_list,
4739 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4740 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4745 /* Check whether this client is on the channel */
4746 if (!silc_server_client_on_channel(client, channel)) {
4747 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4748 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4752 /* Get entry to the channel user list */
4753 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4755 /* The client must be at least channel operator. */
4756 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4757 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4758 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4762 /* Get the new ban and add it to the ban list */
4763 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4765 if (!channel->ban_list)
4766 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4768 channel->ban_list = silc_realloc(channel->ban_list,
4769 sizeof(*channel->ban_list) *
4771 strlen(channel->ban_list) + 2));
4772 if (add[tmp_len - 1] == ',')
4773 add[tmp_len - 1] = '\0';
4775 strncat(channel->ban_list, add, tmp_len);
4776 strncat(channel->ban_list, ",", 1);
4779 /* Get the ban to be removed and remove it from the list */
4780 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4781 if (del && channel->ban_list) {
4782 char *start, *end, *n;
4784 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4785 silc_free(channel->ban_list);
4786 channel->ban_list = NULL;
4788 start = strstr(channel->ban_list, del);
4789 if (start && strlen(start) >= tmp_len) {
4790 end = start + tmp_len;
4791 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4792 strncat(n, channel->ban_list, start - channel->ban_list);
4793 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4795 silc_free(channel->ban_list);
4796 channel->ban_list = n;
4801 /* Send the BAN notify type to our primary router. */
4802 if (!server->standalone && (add || del))
4803 silc_server_send_notify_ban(server, server->router->connection,
4804 server->server_type == SILC_ROUTER ?
4805 TRUE : FALSE, channel, add, del);
4807 /* Send the reply back to the client */
4809 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4810 SILC_STATUS_OK, ident, 2,
4812 3, channel->ban_list,
4814 strlen(channel->ban_list) - 1 : 0);
4815 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4816 packet->data, packet->len, FALSE);
4818 silc_buffer_free(packet);
4821 silc_free(channel_id);
4822 silc_server_command_free(cmd);
4825 /* Server side command of CLOSE. Closes connection to a specified server. */
4827 SILC_SERVER_CMD_FUNC(close)
4829 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4830 SilcServer server = cmd->server;
4831 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4832 SilcServerEntry server_entry;
4833 SilcSocketConnection sock;
4836 unsigned char *name;
4837 uint32 port = SILC_PORT;
4839 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CLOSE, cmd, 1, 2);
4841 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4844 /* Check whether client has the permissions. */
4845 if (client->mode == SILC_UMODE_NONE) {
4846 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4847 SILC_STATUS_ERR_NO_SERVER_PRIV);
4851 /* Get the remote server */
4852 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4854 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4855 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4860 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4862 SILC_GET32_MSB(port, tmp);
4864 server_entry = silc_idlist_find_server_by_conn(server->local_list,
4865 name, port, FALSE, NULL);
4867 server_entry = silc_idlist_find_server_by_conn(server->global_list,
4868 name, port, FALSE, NULL);
4869 if (!server_entry) {
4870 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4871 SILC_STATUS_ERR_NO_SERVER_ID);
4875 /* Send reply to the sender */
4876 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4879 /* Close the connection to the server */
4880 sock = (SilcSocketConnection)server_entry->connection;
4882 /* If we shutdown primary router connection manually then don't trigger
4883 any reconnect or backup router connections, by setting the router
4885 if (server->router == server_entry) {
4886 server->id_entry->router = NULL;
4887 server->router = NULL;
4888 server->standalone = TRUE;
4890 silc_server_free_sock_user_data(server, sock);
4891 silc_server_close_connection(server, sock);
4894 silc_server_command_free(cmd);
4897 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4898 active connections. */
4900 SILC_SERVER_CMD_FUNC(shutdown)
4902 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4903 SilcServer server = cmd->server;
4904 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4906 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4908 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4911 /* Check whether client has the permission. */
4912 if (client->mode == SILC_UMODE_NONE) {
4913 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4914 SILC_STATUS_ERR_NO_SERVER_PRIV);
4918 /* Send reply to the sender */
4919 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4922 /* Then, gracefully, or not, bring the server down. */
4923 silc_server_stop(server);
4927 silc_server_command_free(cmd);
4930 /* Server side command of LEAVE. Removes client from a channel. */
4932 SILC_SERVER_CMD_FUNC(leave)
4934 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4935 SilcServer server = cmd->server;
4936 SilcSocketConnection sock = cmd->sock;
4937 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4938 SilcChannelID *id = NULL;
4939 SilcChannelEntry channel;
4943 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4945 /* Get Channel ID */
4946 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4948 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4949 SILC_STATUS_ERR_NO_CHANNEL_ID);
4952 id = silc_id_payload_parse_id(tmp, len);
4954 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4955 SILC_STATUS_ERR_NO_CHANNEL_ID);
4959 /* Get channel entry */
4960 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4962 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4964 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4965 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4970 /* Check whether this client is on the channel */
4971 if (!silc_server_client_on_channel(id_entry, channel)) {
4972 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4973 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4977 /* Notify routers that they should remove this client from their list
4978 of clients on the channel. Send LEAVE notify type. */
4979 if (!server->standalone)
4980 silc_server_send_notify_leave(server, server->router->connection,
4981 server->server_type == SILC_ROUTER ?
4982 TRUE : FALSE, channel, id_entry->id);
4984 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4987 /* Remove client from channel */
4988 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4990 /* If the channel does not exist anymore we won't send anything */
4993 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4994 /* Re-generate channel key */
4995 if (!silc_server_create_channel_key(server, channel, 0))
4998 /* Send the channel key */
4999 silc_server_send_channel_key(server, NULL, channel,
5000 server->server_type == SILC_ROUTER ?
5001 FALSE : !server->standalone);
5006 silc_server_command_free(cmd);
5009 /* Server side of command USERS. Resolves clients and their USERS currently
5010 joined on the requested channel. The list of Client ID's and their modes
5011 on the channel is sent back. */
5013 SILC_SERVER_CMD_FUNC(users)
5015 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5016 SilcServer server = cmd->server;
5017 SilcChannelEntry channel;
5018 SilcChannelID *id = NULL;
5019 SilcBuffer packet, idp;
5020 unsigned char *channel_id;
5021 uint32 channel_id_len;
5022 SilcBuffer client_id_list;
5023 SilcBuffer client_mode_list;
5024 unsigned char lc[4];
5025 uint32 list_count = 0;
5026 uint16 ident = silc_command_get_ident(cmd->payload);
5029 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5031 /* Get Channel ID */
5032 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5034 /* Get channel name */
5035 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5037 if (!channel_id && !channel_name) {
5038 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5039 SILC_STATUS_ERR_NO_CHANNEL_ID);
5044 id = silc_id_payload_parse_id(channel_id, channel_id_len);
5046 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5047 SILC_STATUS_ERR_NO_CHANNEL_ID);
5052 /* If we are server and we don't know about this channel we will send
5053 the command to our router. If we know about the channel then we also
5054 have the list of users already. */
5056 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5058 channel = silc_idlist_find_channel_by_name(server->local_list,
5059 channel_name, NULL);
5061 if (!channel || channel->disabled) {
5062 if (server->server_type != SILC_ROUTER && !server->standalone &&
5066 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5067 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5069 /* Send USERS command */
5070 silc_server_packet_send(server, server->router->connection,
5071 SILC_PACKET_COMMAND, cmd->packet->flags,
5072 tmpbuf->data, tmpbuf->len, TRUE);
5074 /* Reprocess this packet after received reply */
5075 silc_server_command_pending(server, SILC_COMMAND_USERS,
5076 silc_command_get_ident(cmd->payload),
5077 silc_server_command_destructor,
5078 silc_server_command_users,
5079 silc_server_command_dup(cmd));
5080 cmd->pending = TRUE;
5081 silc_command_set_ident(cmd->payload, ident);
5083 silc_buffer_free(tmpbuf);
5088 /* Check the global list as well. */
5090 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5092 channel = silc_idlist_find_channel_by_name(server->global_list,
5093 channel_name, NULL);
5095 /* Channel really does not exist */
5096 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5097 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5102 /* If the channel is private or secret do not send anything, unless the
5103 user requesting this command is on the channel. */
5104 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5105 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5106 && !silc_server_client_on_channel(cmd->sock->user_data, channel)) {
5107 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5108 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5113 (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
5114 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5115 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5120 /* Get the users list */
5121 silc_server_get_users_on_channel(server, channel, &client_id_list,
5122 &client_mode_list, &list_count);
5125 SILC_PUT32_MSB(list_count, lc);
5128 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5129 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5130 SILC_STATUS_OK, ident, 4,
5131 2, idp->data, idp->len,
5133 4, client_id_list->data,
5134 client_id_list->len,
5135 5, client_mode_list->data,
5136 client_mode_list->len);
5137 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5138 packet->data, packet->len, FALSE);
5140 silc_buffer_free(idp);
5141 silc_buffer_free(packet);
5142 silc_buffer_free(client_id_list);
5143 silc_buffer_free(client_mode_list);
5147 silc_server_command_free(cmd);
5150 /* Server side of command GETKEY. This fetches the client's public key
5151 from the server where to the client is connected. */
5153 SILC_SERVER_CMD_FUNC(getkey)
5155 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5156 SilcServer server = cmd->server;
5158 SilcClientEntry client;
5159 SilcServerEntry server_entry;
5160 SilcClientID *client_id = NULL;
5161 SilcServerID *server_id = NULL;
5162 SilcIDPayload idp = NULL;
5163 uint16 ident = silc_command_get_ident(cmd->payload);
5164 unsigned char *tmp, *pkdata;
5165 uint32 tmp_len, pklen;
5166 SilcBuffer pk = NULL;
5169 SILC_LOG_DEBUG(("Start"));
5171 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5173 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5174 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5177 idp = silc_id_payload_parse(tmp, tmp_len);
5179 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5180 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5184 id_type = silc_id_payload_get_type(idp);
5185 if (id_type == SILC_ID_CLIENT) {
5186 client_id = silc_id_payload_get_id(idp);
5188 /* If the client is not found from local list there is no chance it
5189 would be locally connected client so send the command further. */
5190 client = silc_idlist_find_client_by_id(server->local_list,
5191 client_id, TRUE, NULL);
5193 client = silc_idlist_find_client_by_id(server->global_list,
5194 client_id, TRUE, NULL);
5196 if ((!client && !cmd->pending && !server->standalone) ||
5197 (client && !client->connection && !cmd->pending) ||
5198 (client && !client->data.public_key && !cmd->pending)) {
5201 SilcSocketConnection dest_sock;
5203 dest_sock = silc_server_get_client_route(server, NULL, 0,
5208 old_ident = silc_command_get_ident(cmd->payload);
5209 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5210 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5212 silc_server_packet_send(server, dest_sock,
5213 SILC_PACKET_COMMAND, cmd->packet->flags,
5214 tmpbuf->data, tmpbuf->len, TRUE);
5216 /* Reprocess this packet after received reply from router */
5217 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5218 silc_command_get_ident(cmd->payload),
5219 silc_server_command_destructor,
5220 silc_server_command_getkey,
5221 silc_server_command_dup(cmd));
5222 cmd->pending = TRUE;
5224 silc_command_set_ident(cmd->payload, old_ident);
5225 silc_buffer_free(tmpbuf);
5230 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5231 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5235 /* The client is locally connected, just get the public key and
5236 send it back. If they key does not exist then do not send it,
5237 send just OK reply */
5238 if (!client->data.public_key) {
5242 tmp = silc_pkcs_public_key_encode(client->data.public_key, &tmp_len);
5243 pk = silc_buffer_alloc(4 + tmp_len);
5244 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5245 silc_buffer_format(pk,
5246 SILC_STR_UI_SHORT(tmp_len),
5247 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5248 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5254 } else if (id_type == SILC_ID_SERVER) {
5255 server_id = silc_id_payload_get_id(idp);
5257 /* If the server is not found from local list there is no chance it
5258 would be locally connected server so send the command further. */
5259 server_entry = silc_idlist_find_server_by_id(server->local_list,
5260 server_id, TRUE, NULL);
5262 server_entry = silc_idlist_find_server_by_id(server->global_list,
5263 server_id, TRUE, NULL);
5265 if (server_entry != server->id_entry &&
5266 ((!server_entry && !cmd->pending && !server->standalone) ||
5267 (server_entry && !server_entry->connection && !cmd->pending &&
5268 !server->standalone) ||
5269 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5270 !server->standalone))) {
5274 old_ident = silc_command_get_ident(cmd->payload);
5275 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5276 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5278 silc_server_packet_send(server, server->router->connection,
5279 SILC_PACKET_COMMAND, cmd->packet->flags,
5280 tmpbuf->data, tmpbuf->len, TRUE);
5282 /* Reprocess this packet after received reply from router */
5283 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5284 silc_command_get_ident(cmd->payload),
5285 silc_server_command_destructor,
5286 silc_server_command_getkey,
5287 silc_server_command_dup(cmd));
5288 cmd->pending = TRUE;
5290 silc_command_set_ident(cmd->payload, old_ident);
5291 silc_buffer_free(tmpbuf);
5295 if (!server_entry) {
5296 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5297 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5301 /* If they key does not exist then do not send it, send just OK reply */
5302 if (!server_entry->data.public_key) {
5306 tmp = silc_pkcs_public_key_encode(server_entry->data.public_key,
5308 pk = silc_buffer_alloc(4 + tmp_len);
5309 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5310 silc_buffer_format(pk,
5311 SILC_STR_UI_SHORT(tmp_len),
5312 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5313 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5323 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5324 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5325 SILC_STATUS_OK, ident,
5329 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5330 packet->data, packet->len, FALSE);
5331 silc_buffer_free(packet);
5334 silc_buffer_free(pk);
5338 silc_id_payload_free(idp);
5339 silc_free(client_id);
5340 silc_free(server_id);
5341 silc_server_command_free(cmd);