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,
38 const unsigned char *arg,
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'. If there already exists pending command for the
301 specified command, ident, callback and context this function has no
304 bool silc_server_command_pending(SilcServer server,
305 SilcCommand reply_cmd,
307 SilcCommandCb callback,
310 SilcServerCommandPending *reply;
312 /* Check whether identical pending already exists for same command,
313 ident, callback and callback context. If it does then it would be
314 error to register it again. */
315 silc_dlist_start(server->pending_commands);
316 while ((reply = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
317 if (reply->reply_cmd == reply_cmd && reply->ident == ident &&
318 reply->callback == callback && reply->context == context)
322 reply = silc_calloc(1, sizeof(*reply));
323 reply->reply_cmd = reply_cmd;
324 reply->ident = ident;
325 reply->context = context;
326 reply->callback = callback;
327 silc_dlist_add(server->pending_commands, reply);
332 /* Deletes pending command by reply command type. */
334 void silc_server_command_pending_del(SilcServer server,
335 SilcCommand reply_cmd,
338 SilcServerCommandPending *r;
340 silc_dlist_start(server->pending_commands);
341 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
342 if (r->reply_cmd == reply_cmd && r->ident == ident) {
343 silc_dlist_del(server->pending_commands, r);
349 /* Checks for pending commands and marks callbacks to be called from
350 the command reply function. Returns TRUE if there were pending command. */
352 SilcServerCommandPendingCallbacks
353 silc_server_command_pending_check(SilcServer server,
354 SilcServerCommandReplyContext ctx,
357 uint32 *callbacks_count)
359 SilcServerCommandPending *r;
360 SilcServerCommandPendingCallbacks callbacks = NULL;
363 silc_dlist_start(server->pending_commands);
364 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
365 if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE)
366 && r->ident == ident) {
367 callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
368 callbacks[i].context = r->context;
369 callbacks[i].callback = r->callback;
375 *callbacks_count = i;
379 /* Sends simple status message as command reply packet */
382 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
384 SilcCommandStatus status)
388 SILC_LOG_DEBUG(("Sending command status %d", status));
391 silc_command_reply_payload_encode_va(command, status,
392 silc_command_get_ident(cmd->payload),
394 silc_server_packet_send(cmd->server, cmd->sock,
395 SILC_PACKET_COMMAND_REPLY, 0,
396 buffer->data, buffer->len, FALSE);
397 silc_buffer_free(buffer);
400 /* Sends command status reply with one extra argument. The argument
401 type must be sent as argument. */
404 silc_server_command_send_status_data(SilcServerCommandContext cmd,
406 SilcCommandStatus status,
408 const unsigned char *arg,
413 SILC_LOG_DEBUG(("Sending command status %d", status));
416 silc_command_reply_payload_encode_va(command, status,
417 silc_command_get_ident(cmd->payload),
418 1, arg_type, arg, arg_len);
419 silc_server_packet_send(cmd->server, cmd->sock,
420 SILC_PACKET_COMMAND_REPLY, 0,
421 buffer->data, buffer->len, FALSE);
422 silc_buffer_free(buffer);
425 /* This function can be called to check whether in the command reply
426 an error occurred. This function has no effect if this is called
427 when the command function was not called as pending command callback.
428 This returns TRUE if error had occurred. */
431 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
432 SilcServerCommandReplyContext cmdr,
435 SilcCommandStatus status;
437 if (!cmd->pending || !cmdr)
440 SILC_GET16_MSB(status, silc_argument_get_arg_type(cmdr->args, 1, NULL));
441 if (status != SILC_STATUS_OK &&
442 status != SILC_STATUS_LIST_START &&
443 status != SILC_STATUS_LIST_ITEM &&
444 status != SILC_STATUS_LIST_END) {
447 /* Send the same command reply payload */
448 silc_command_set_ident(cmdr->payload,
449 silc_command_get_ident(cmd->payload));
450 buffer = silc_command_payload_encode_payload(cmdr->payload);
451 silc_server_packet_send(cmd->server, cmd->sock,
452 SILC_PACKET_COMMAND_REPLY, 0,
453 buffer->data, buffer->len, FALSE);
454 silc_buffer_free(buffer);
461 /******************************************************************************
465 ******************************************************************************/
468 silc_server_command_whois_parse(SilcServerCommandContext cmd,
469 SilcClientID ***client_id,
470 uint32 *client_id_count,
478 uint32 argc = silc_argument_get_arg_num(cmd->args);
481 /* If client ID is in the command it must be used instead of nickname */
482 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
484 /* No ID, get the nickname@server string and parse it. */
485 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
487 silc_parse_userfqdn(tmp, nickname, server_name);
489 silc_server_command_send_status_reply(cmd, command,
490 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
494 /* Command includes ID, we must use that. Also check whether the command
495 has more than one ID set - take them all. */
497 *client_id = silc_calloc(1, sizeof(**client_id));
498 (*client_id)[0] = silc_id_payload_parse_id(tmp, len);
499 if ((*client_id)[0] == NULL) {
500 silc_free(*client_id);
501 silc_server_command_send_status_reply(cmd, command,
502 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
505 *client_id_count = 1;
507 /* Take all ID's from the command packet */
509 for (k = 1, i = 1; i < argc; i++) {
510 tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
512 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
513 (*client_id_count + 1));
514 (*client_id)[k] = silc_id_payload_parse_id(tmp, len);
515 if ((*client_id)[k] == NULL) {
516 /* Cleanup all and fail */
517 for (i = 0; i < *client_id_count; i++)
518 silc_free((*client_id)[i]);
519 silc_free(*client_id);
520 silc_server_command_send_status_reply(
522 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
525 (*client_id_count)++;
532 /* Get the max count of reply messages allowed */
533 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
542 /* Resolve context used by both WHOIS and IDENTIFY commands */
544 SilcServerEntry router;
546 unsigned char **res_argv;
547 uint32 *res_argv_lens;
548 uint32 *res_argv_types;
550 } *SilcServerResolveContext;
553 silc_server_command_whois_check(SilcServerCommandContext cmd,
554 SilcClientEntry *clients,
555 uint32 clients_count)
557 SilcServer server = cmd->server;
558 SilcClientEntry entry;
559 SilcServerResolveContext resolve = NULL, r = NULL;
560 uint32 resolve_count = 0;
564 for (i = 0; i < clients_count; i++) {
569 if ((entry->nickname && entry->username && entry->userinfo) ||
570 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
574 /* If we are normal server, and we've not resolved this client from
575 router and it is global client, we'll check whether it is on some
576 channel. If not then we cannot be sure about its validity, and
577 we'll resolve it from router. */
578 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
579 entry->connection || silc_hash_table_count(entry->channels))
583 /* We need to resolve this entry since it is not complete */
585 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
586 /* The entry is being resolved (and we are not the resolver) so attach
587 to the command reply and we're done with this one. */
588 silc_server_command_pending(server, SILC_COMMAND_NONE,
589 entry->resolve_cmd_ident,
590 silc_server_command_whois,
591 silc_server_command_dup(cmd));
594 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
595 /* We've resolved this and it still is not ready. We'll return
596 and are that this will be handled again after it is resolved. */
597 for (i = 0; i < resolve_count; i++) {
598 for (k = 0; k < r->res_argc; k++)
599 silc_free(r->res_argv[k]);
600 silc_free(r->res_argv);
601 silc_free(r->res_argv_lens);
602 silc_free(r->res_argv_types);
607 /* We'll resolve this client */
611 for (k = 0; k < resolve_count; k++) {
612 if (resolve[k].router == entry->router) {
619 resolve = silc_realloc(resolve, sizeof(*resolve) *
620 (resolve_count + 1));
621 r = &resolve[resolve_count];
622 memset(r, 0, sizeof(*r));
623 r->router = entry->router;
624 r->ident = ++server->cmd_ident;
628 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
630 r->res_argv_lens = silc_realloc(r->res_argv_lens,
631 sizeof(*r->res_argv_lens) *
633 r->res_argv_types = silc_realloc(r->res_argv_types,
634 sizeof(*r->res_argv_types) *
636 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
637 r->res_argv[r->res_argc] = silc_calloc(idp->len,
638 sizeof(**r->res_argv));
639 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
640 r->res_argv_lens[r->res_argc] = idp->len;
641 r->res_argv_types[r->res_argc] = r->res_argc + 3;
643 silc_buffer_free(idp);
645 entry->resolve_cmd_ident = r->ident;
646 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
647 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
652 /* Do the resolving */
653 for (i = 0; i < resolve_count; i++) {
658 /* Send WHOIS request. We send WHOIS since we're doing the requesting
659 now anyway so make it a good one. */
660 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
661 r->res_argc, r->res_argv,
665 silc_server_packet_send(server, r->router->connection,
666 SILC_PACKET_COMMAND, cmd->packet->flags,
667 res_cmd->data, res_cmd->len, FALSE);
669 /* Reprocess this packet after received reply */
670 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
672 silc_server_command_whois,
673 silc_server_command_dup(cmd));
676 silc_buffer_free(res_cmd);
677 for (k = 0; k < r->res_argc; k++)
678 silc_free(r->res_argv[k]);
679 silc_free(r->res_argv);
680 silc_free(r->res_argv_lens);
681 silc_free(r->res_argv_types);
690 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
691 SilcClientEntry *clients,
692 uint32 clients_count,
694 const char *nickname,
695 SilcClientID **client_ids)
697 SilcServer server = cmd->server;
699 int i, k, len, valid_count;
700 SilcBuffer packet, idp, channels;
701 SilcClientEntry entry;
702 SilcCommandStatus status;
703 uint16 ident = silc_command_get_ident(cmd->payload);
704 char nh[256], uh[256];
705 unsigned char idle[4], mode[4];
706 unsigned char *fingerprint;
707 SilcSocketConnection hsock;
709 /* Process only valid clients and ignore those that are not registered. */
711 for (i = 0; i < clients_count; i++) {
712 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
719 /* No valid clients found, send error reply */
721 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
722 SILC_STATUS_ERR_NO_SUCH_NICK,
723 3, nickname, strlen(nickname));
724 } else if (client_ids && client_ids[0]) {
725 SilcBuffer idp = silc_id_payload_encode(client_ids[0], SILC_ID_CLIENT);
726 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
727 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
728 2, idp->data, idp->len);
729 silc_buffer_free(idp);
734 /* Start processing found clients. */
736 status = SILC_STATUS_LIST_START;
738 status = SILC_STATUS_OK;
740 for (i = 0, k = 0; i < clients_count; i++) {
746 status = SILC_STATUS_LIST_ITEM;
747 if (valid_count > 1 && k == valid_count - 1)
748 status = SILC_STATUS_LIST_END;
749 if (count && k - 1 == count)
750 status = SILC_STATUS_LIST_END;
752 /* Send WHOIS reply */
753 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
754 tmp = silc_argument_get_first_arg(cmd->args, NULL);
756 memset(uh, 0, sizeof(uh));
757 memset(nh, 0, sizeof(nh));
758 memset(idle, 0, sizeof(idle));
760 strncat(nh, entry->nickname, strlen(entry->nickname));
761 if (!strchr(entry->nickname, '@')) {
763 if (entry->servername) {
764 strncat(nh, entry->servername, strlen(entry->servername));
766 len = entry->router ? strlen(entry->router->server_name) :
767 strlen(server->server_name);
768 strncat(nh, entry->router ? entry->router->server_name :
769 server->server_name, len);
773 strncat(uh, entry->username, strlen(entry->username));
774 if (!strchr(entry->username, '@')) {
776 hsock = (SilcSocketConnection)entry->connection;
777 len = strlen(hsock->hostname);
778 strncat(uh, hsock->hostname, len);
781 channels = silc_server_get_client_channel_list(server, entry);
783 if (entry->data.fingerprint[0] != 0 && entry->data.fingerprint[1] != 0)
784 fingerprint = entry->data.fingerprint;
788 SILC_PUT32_MSB(entry->mode, mode);
790 if (entry->connection) {
791 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
795 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
797 2, idp->data, idp->len,
801 strlen(entry->userinfo),
802 6, channels ? channels->data : NULL,
803 channels ? channels->len : 0,
807 fingerprint ? 20 : 0);
809 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
810 0, packet->data, packet->len, FALSE);
812 silc_buffer_free(packet);
813 silc_buffer_free(idp);
815 silc_buffer_free(channels);
822 silc_server_command_whois_send_router(SilcServerCommandContext cmd)
824 SilcServer server = cmd->server;
828 old_ident = silc_command_get_ident(cmd->payload);
829 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
830 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
832 /* Send WHOIS command to our router */
833 silc_server_packet_send(server, (SilcSocketConnection)
834 server->router->connection,
835 SILC_PACKET_COMMAND, cmd->packet->flags,
836 tmpbuf->data, tmpbuf->len, TRUE);
838 /* Reprocess this packet after received reply from router */
839 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
840 silc_command_get_ident(cmd->payload),
841 silc_server_command_whois,
842 silc_server_command_dup(cmd));
844 silc_command_set_ident(cmd->payload, old_ident);
845 silc_buffer_free(tmpbuf);
849 silc_server_command_whois_process(SilcServerCommandContext cmd)
851 SilcServer server = cmd->server;
852 char *nick = NULL, *server_name = NULL;
854 SilcClientEntry *clients = NULL, entry;
855 SilcClientID **client_id = NULL;
856 uint32 client_id_count = 0, clients_count = 0;
858 bool check_global = FALSE;
860 /* Parse the whois request */
861 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
862 &nick, &server_name, &count,
866 /* Send the WHOIS request to the router only if it included nickname.
867 Since nicknames can be expanded into many clients we need to send it
868 to router. If the WHOIS included only client ID's we will check them
869 first locally since we just might have them. */
870 if (nick && !client_id_count && cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
871 server->server_type == SILC_SERVER && !cmd->pending &&
872 !server->standalone) {
873 silc_server_command_whois_send_router(cmd);
878 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
880 else if (server->server_type != SILC_SERVER)
883 /* Get all clients matching that ID or nickname from local list */
884 if (client_id_count) {
885 /* Check all Client ID's received in the command packet */
886 for (i = 0; i < client_id_count; i++) {
887 entry = silc_idlist_find_client_by_id(server->local_list,
888 client_id[i], TRUE, NULL);
889 if (!entry && check_global)
890 entry = silc_idlist_find_client_by_id(server->global_list,
891 client_id[i], TRUE, NULL);
893 clients = silc_realloc(clients, sizeof(*clients) *
894 (clients_count + 1));
895 clients[clients_count++] = entry;
897 /* If we are normal server and did not send the request first to router
898 do it now, since we do not have the Client ID information. */
899 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
900 server->server_type == SILC_SERVER && !cmd->pending &&
901 !server->standalone) {
902 silc_server_command_whois_send_router(cmd);
909 /* Find by nickname */
910 if (!silc_idlist_get_clients_by_hash(server->local_list,
911 nick, server->md5hash,
912 &clients, &clients_count))
913 silc_idlist_get_clients_by_nickname(server->local_list,
915 &clients, &clients_count);
917 if (!silc_idlist_get_clients_by_hash(server->global_list,
918 nick, server->md5hash,
919 &clients, &clients_count))
920 silc_idlist_get_clients_by_nickname(server->global_list,
922 &clients, &clients_count);
927 /* If we are normal server and did not send the request first to router
928 do it now, since we do not have the information. */
929 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
930 server->server_type == SILC_SERVER && !cmd->pending &&
931 !server->standalone) {
932 silc_server_command_whois_send_router(cmd);
937 /* Such client(s) really does not exist in the SILC network. */
938 if (!client_id_count) {
939 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
940 SILC_STATUS_ERR_NO_SUCH_NICK,
941 3, nick, strlen(nick));
943 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
944 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
945 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
946 2, idp->data, idp->len);
947 silc_buffer_free(idp);
952 /* Router always finds the client entry if it exists in the SILC network.
953 However, it might be incomplete entry and does not include all the
954 mandatory fields that WHOIS command reply requires. Check for these and
955 make query from the server who owns the client if some fields are
957 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
962 /* Send the command reply */
963 silc_server_command_whois_send_reply(cmd, clients, clients_count,
964 count, nick, client_id);
967 if (client_id_count) {
968 for (i = 0; i < client_id_count; i++)
969 silc_free(client_id[i]);
970 silc_free(client_id);
974 silc_free(server_name);
979 /* Server side of command WHOIS. Processes user's query and sends found
980 results as command replies back to the client. */
982 SILC_SERVER_CMD_FUNC(whois)
984 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
987 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 3328);
989 ret = silc_server_command_whois_process(cmd);
990 silc_server_command_free(cmd);
993 /******************************************************************************
997 ******************************************************************************/
1000 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
1008 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1010 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
1011 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1015 /* Get the nickname@server string and parse it. */
1016 silc_parse_userfqdn(tmp, nickname, server_name);
1018 /* Get the max count of reply messages allowed */
1019 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1029 silc_server_command_whowas_check(SilcServerCommandContext cmd,
1030 SilcClientEntry *clients,
1031 uint32 clients_count)
1033 SilcServer server = cmd->server;
1035 SilcClientEntry entry;
1037 for (i = 0; i < clients_count; i++) {
1040 if (!entry->nickname || !entry->username) {
1047 old_ident = silc_command_get_ident(cmd->payload);
1048 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1049 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1051 /* Send WHOWAS command */
1052 silc_server_packet_send(server, entry->router->connection,
1053 SILC_PACKET_COMMAND, cmd->packet->flags,
1054 tmpbuf->data, tmpbuf->len, TRUE);
1056 /* Reprocess this packet after received reply */
1057 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1058 silc_command_get_ident(cmd->payload),
1059 silc_server_command_whowas,
1060 silc_server_command_dup(cmd));
1061 cmd->pending = TRUE;
1063 silc_command_set_ident(cmd->payload, old_ident);
1065 silc_buffer_free(tmpbuf);
1074 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1075 SilcClientEntry *clients,
1076 uint32 clients_count)
1078 SilcServer server = cmd->server;
1080 int i, count = 0, len;
1081 SilcBuffer packet, idp;
1082 SilcClientEntry entry = NULL;
1083 SilcCommandStatus status;
1084 uint16 ident = silc_command_get_ident(cmd->payload);
1086 char nh[256], uh[256];
1088 status = SILC_STATUS_OK;
1089 if (clients_count > 1)
1090 status = SILC_STATUS_LIST_START;
1092 for (i = 0; i < clients_count; i++) {
1095 /* We will take only clients that are not valid anymore. They are the
1096 ones that are not registered anymore but still have a ID. They
1097 have disconnected us, and thus valid for WHOWAS. */
1098 if (entry->data.status & SILC_IDLIST_STATUS_REGISTERED || !entry->id)
1101 if (count && i - 1 == count)
1106 if (clients_count > 2)
1107 status = SILC_STATUS_LIST_ITEM;
1108 if (clients_count > 1 && i == clients_count - 1)
1109 status = SILC_STATUS_LIST_END;
1111 /* Send WHOWAS reply */
1112 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1113 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1114 memset(uh, 0, sizeof(uh));
1115 memset(nh, 0, sizeof(nh));
1117 strncat(nh, entry->nickname, strlen(entry->nickname));
1118 if (!strchr(entry->nickname, '@')) {
1119 strncat(nh, "@", 1);
1120 if (entry->servername) {
1121 strncat(nh, entry->servername, strlen(entry->servername));
1123 len = entry->router ? strlen(entry->router->server_name) :
1124 strlen(server->server_name);
1125 strncat(nh, entry->router ? entry->router->server_name :
1126 server->server_name, len);
1130 strncat(uh, entry->username, strlen(entry->username));
1131 if (!strchr(entry->username, '@')) {
1132 strncat(uh, "@", 1);
1133 strcat(uh, "*private*");
1137 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1139 2, idp->data, idp->len,
1144 strlen(entry->userinfo) : 0);
1145 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1146 0, packet->data, packet->len, FALSE);
1148 silc_buffer_free(packet);
1149 silc_buffer_free(idp);
1152 if (found == FALSE && entry)
1153 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1154 SILC_STATUS_ERR_NO_SUCH_NICK,
1156 strlen(entry->nickname));
1160 silc_server_command_whowas_process(SilcServerCommandContext cmd)
1162 SilcServer server = cmd->server;
1163 char *nick = NULL, *server_name = NULL;
1165 SilcClientEntry *clients = NULL;
1166 uint32 clients_count = 0;
1168 bool check_global = FALSE;
1170 /* Protocol dictates that we must always send the received WHOWAS request
1171 to our router if we are normal server, so let's do it now unless we
1172 are standalone. We will not send any replies to the client until we
1173 have received reply from the router. */
1174 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1175 server->server_type == SILC_SERVER && !cmd->pending &&
1176 !server->standalone) {
1180 old_ident = silc_command_get_ident(cmd->payload);
1181 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1182 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1184 /* Send WHOWAS command to our router */
1185 silc_server_packet_send(server, (SilcSocketConnection)
1186 server->router->connection,
1187 SILC_PACKET_COMMAND, cmd->packet->flags,
1188 tmpbuf->data, tmpbuf->len, TRUE);
1190 /* Reprocess this packet after received reply from router */
1191 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1192 silc_command_get_ident(cmd->payload),
1193 silc_server_command_whowas,
1194 silc_server_command_dup(cmd));
1195 cmd->pending = TRUE;
1197 silc_command_set_ident(cmd->payload, old_ident);
1199 silc_buffer_free(tmpbuf);
1204 /* We are ready to process the command request. Let's search for the
1205 requested client and send reply to the requesting client. */
1207 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1208 check_global = TRUE;
1209 else if (server->server_type != SILC_SERVER)
1210 check_global = TRUE;
1212 /* Parse the whowas request */
1213 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1216 /* Get all clients matching that nickname from local list */
1217 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1219 &clients, &clients_count))
1220 silc_idlist_get_clients_by_hash(server->local_list,
1221 nick, server->md5hash,
1222 &clients, &clients_count);
1224 /* Check global list as well */
1226 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1228 &clients, &clients_count))
1229 silc_idlist_get_clients_by_hash(server->global_list,
1230 nick, server->md5hash,
1231 &clients, &clients_count);
1235 /* Such a client really does not exist in the SILC network. */
1236 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1237 SILC_STATUS_ERR_NO_SUCH_NICK,
1238 3, nick, strlen(nick));
1242 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1247 /* Send the command reply to the client */
1248 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1253 silc_free(server_name);
1257 /* Server side of command WHOWAS. */
1259 SILC_SERVER_CMD_FUNC(whowas)
1261 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1264 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1266 ret = silc_server_command_whowas_process(cmd);
1267 silc_server_command_free(cmd);
1270 /******************************************************************************
1274 ******************************************************************************/
1277 silc_server_command_identify_send_router(SilcServerCommandContext cmd)
1279 SilcServer server = cmd->server;
1283 old_ident = silc_command_get_ident(cmd->payload);
1284 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1285 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1287 /* Send IDENTIFY command to our router */
1288 silc_server_packet_send(server, (SilcSocketConnection)
1289 server->router->connection,
1290 SILC_PACKET_COMMAND, cmd->packet->flags,
1291 tmpbuf->data, tmpbuf->len, TRUE);
1293 /* Reprocess this packet after received reply from router */
1294 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1295 silc_command_get_ident(cmd->payload),
1296 silc_server_command_identify,
1297 silc_server_command_dup(cmd));
1298 cmd->pending = TRUE;
1299 silc_command_set_ident(cmd->payload, old_ident);
1300 silc_buffer_free(tmpbuf);
1304 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1305 SilcClientEntry **clients,
1306 uint32 *clients_count,
1307 SilcServerEntry **servers,
1308 uint32 *servers_count,
1309 SilcChannelEntry **channels,
1310 uint32 *channels_count,
1313 SilcServer server = cmd->server;
1316 uint32 argc = silc_argument_get_arg_num(cmd->args);
1318 bool check_global = FALSE;
1323 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1324 check_global = TRUE;
1325 else if (server->server_type != SILC_SERVER)
1326 check_global = TRUE;
1328 /* If ID Payload is in the command it must be used instead of names */
1329 tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1331 /* No ID, get the names. */
1333 /* If we are normal server and have not resolved information from
1334 router yet, do so now. */
1335 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1336 server->server_type == SILC_SERVER && !cmd->pending &&
1337 !server->standalone) {
1338 silc_server_command_identify_send_router(cmd);
1342 /* Try to get nickname@server. */
1343 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1346 char *nick_server = NULL;
1348 silc_parse_userfqdn(tmp, &nick, &nick_server);
1350 if (!silc_idlist_get_clients_by_hash(server->local_list,
1351 nick, server->md5hash,
1352 clients, clients_count))
1353 silc_idlist_get_clients_by_nickname(server->local_list,
1355 clients, clients_count);
1357 if (!silc_idlist_get_clients_by_hash(server->global_list,
1358 nick, server->md5hash,
1359 clients, clients_count))
1360 silc_idlist_get_clients_by_nickname(server->global_list,
1362 clients, clients_count);
1366 silc_free(nick_server);
1369 /* the nickname does not exist, send error reply */
1370 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1371 SILC_STATUS_ERR_NO_SUCH_NICK,
1372 3, tmp, strlen(tmp));
1377 /* Try to get server name */
1378 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1380 entry = silc_idlist_find_server_by_name(server->local_list,
1382 if (!entry && check_global)
1383 entry = silc_idlist_find_server_by_name(server->global_list,
1386 *servers = silc_realloc(*servers, sizeof(**servers) *
1387 (*servers_count + 1));
1388 (*servers)[(*servers_count)++] = entry;
1392 /* the server does not exist, send error reply */
1393 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1394 SILC_STATUS_ERR_NO_SUCH_SERVER,
1395 3, tmp, strlen(tmp));
1400 /* Try to get channel name */
1401 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1403 entry = silc_idlist_find_channel_by_name(server->local_list,
1405 if (!entry && check_global)
1406 entry = silc_idlist_find_channel_by_name(server->global_list,
1409 *channels = silc_realloc(*channels, sizeof(**channels) *
1410 (*channels_count + 1));
1411 (*channels)[(*channels_count)++] = entry;
1415 /* The channel does not exist, send error reply */
1416 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1417 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1418 3, tmp, strlen(tmp));
1423 if (!(*clients) && !(*servers) && !(*channels)) {
1424 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1425 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1429 /* Command includes ID, we must use that. Also check whether the command
1430 has more than one ID set - take them all. */
1432 /* Take all ID's from the command packet */
1433 for (i = 0; i < argc; i++) {
1436 tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
1440 idp = silc_id_payload_parse(tmp, len);
1442 silc_free(*clients);
1443 silc_free(*servers);
1444 silc_free(*channels);
1445 silc_server_command_send_status_reply(
1446 cmd, SILC_COMMAND_IDENTIFY,
1447 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1451 id = silc_id_payload_get_id(idp);
1453 switch (silc_id_payload_get_type(idp)) {
1455 case SILC_ID_CLIENT:
1456 entry = (void *)silc_idlist_find_client_by_id(server->local_list,
1458 if (!entry && check_global)
1459 entry = (void *)silc_idlist_find_client_by_id(server->global_list,
1462 *clients = silc_realloc(*clients, sizeof(**clients) *
1463 (*clients_count + 1));
1464 (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
1466 /* If we are normal server and have not resolved information from
1467 router yet, do so now. */
1468 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1469 server->server_type == SILC_SERVER && !cmd->pending &&
1470 !server->standalone) {
1471 silc_server_command_identify_send_router(cmd);
1472 silc_free(*clients);
1473 silc_free(*servers);
1474 silc_free(*channels);
1477 silc_server_command_send_status_data(
1478 cmd, SILC_COMMAND_IDENTIFY,
1479 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1487 case SILC_ID_SERVER:
1488 entry = (void *)silc_idlist_find_server_by_id(server->local_list,
1490 if (!entry && check_global)
1491 entry = (void *)silc_idlist_find_server_by_id(server->global_list,
1494 *servers = silc_realloc(*servers, sizeof(**servers) *
1495 (*servers_count + 1));
1496 (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
1498 /* If we are normal server and have not resolved information from
1499 router yet, do so now. */
1500 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1501 server->server_type == SILC_SERVER && !cmd->pending &&
1502 !server->standalone) {
1503 silc_server_command_identify_send_router(cmd);
1504 silc_free(*clients);
1505 silc_free(*servers);
1506 silc_free(*channels);
1509 silc_server_command_send_status_data(
1510 cmd, SILC_COMMAND_IDENTIFY,
1511 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
1518 case SILC_ID_CHANNEL:
1519 entry = (void *)silc_idlist_find_channel_by_id(server->local_list,
1521 if (!entry && check_global)
1522 entry = (void *)silc_idlist_find_channel_by_id(server->global_list,
1525 *channels = silc_realloc(*channels, sizeof(**channels) *
1526 (*channels_count + 1));
1527 (*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
1529 /* If we are normal server and have not resolved information from
1530 router yet, do so now. */
1531 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1532 server->server_type == SILC_SERVER && !cmd->pending &&
1533 !server->standalone) {
1534 silc_server_command_identify_send_router(cmd);
1535 silc_free(*clients);
1536 silc_free(*servers);
1537 silc_free(*channels);
1540 silc_server_command_send_status_data(
1541 cmd, SILC_COMMAND_IDENTIFY,
1542 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
1555 silc_free(*clients);
1556 silc_free(*servers);
1557 silc_free(*channels);
1561 /* Get the max count of reply messages allowed */
1562 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1571 /* Checks that all mandatory fields in client entry are present. If not
1572 then send WHOIS request to the server who owns the client. We use
1573 WHOIS because we want to get as much information as possible at once. */
1576 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1577 SilcClientEntry *clients,
1578 uint32 clients_count)
1580 SilcServer server = cmd->server;
1581 SilcClientEntry entry;
1582 SilcServerResolveContext resolve = NULL, r = NULL;
1583 uint32 resolve_count = 0;
1587 for (i = 0; i < clients_count; i++) {
1592 if (entry->nickname ||
1593 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1597 /* If we are normal server, and we've not resolved this client from
1598 router and it is global client, we'll check whether it is on some
1599 channel. If not then we cannot be sure about its validity, and
1600 we'll resolve it from router. */
1601 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
1602 entry->connection || silc_hash_table_count(entry->channels))
1606 /* We need to resolve this entry since it is not complete */
1608 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1609 /* The entry is being resolved (and we are not the resolver) so attach
1610 to the command reply and we're done with this one. */
1611 silc_server_command_pending(server, SILC_COMMAND_NONE,
1612 entry->resolve_cmd_ident,
1613 silc_server_command_identify,
1614 silc_server_command_dup(cmd));
1617 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1618 /* We've resolved this and it still is not ready. We'll return
1619 and are that this will be handled again after it is resolved. */
1620 for (i = 0; i < resolve_count; i++) {
1621 for (k = 0; k < r->res_argc; k++)
1622 silc_free(r->res_argv[k]);
1623 silc_free(r->res_argv);
1624 silc_free(r->res_argv_lens);
1625 silc_free(r->res_argv_types);
1630 /* We'll resolve this client */
1634 for (k = 0; k < resolve_count; k++) {
1635 if (resolve[k].router == entry->router) {
1642 resolve = silc_realloc(resolve, sizeof(*resolve) *
1643 (resolve_count + 1));
1644 r = &resolve[resolve_count];
1645 memset(r, 0, sizeof(*r));
1646 r->router = entry->router;
1647 r->ident = ++server->cmd_ident;
1651 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1653 r->res_argv_lens = silc_realloc(r->res_argv_lens,
1654 sizeof(*r->res_argv_lens) *
1656 r->res_argv_types = silc_realloc(r->res_argv_types,
1657 sizeof(*r->res_argv_types) *
1659 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1660 r->res_argv[r->res_argc] = silc_calloc(idp->len,
1661 sizeof(**r->res_argv));
1662 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1663 r->res_argv_lens[r->res_argc] = idp->len;
1664 r->res_argv_types[r->res_argc] = r->res_argc + 3;
1666 silc_buffer_free(idp);
1668 entry->resolve_cmd_ident = r->ident;
1669 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1670 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1675 /* Do the resolving */
1676 for (i = 0; i < resolve_count; i++) {
1681 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1682 now anyway so make it a good one. */
1683 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1684 r->res_argc, r->res_argv,
1688 silc_server_packet_send(server, r->router->connection,
1689 SILC_PACKET_COMMAND, cmd->packet->flags,
1690 res_cmd->data, res_cmd->len, FALSE);
1692 /* Reprocess this packet after received reply */
1693 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1695 silc_server_command_identify,
1696 silc_server_command_dup(cmd));
1697 cmd->pending = TRUE;
1699 silc_buffer_free(res_cmd);
1700 for (k = 0; k < r->res_argc; k++)
1701 silc_free(r->res_argv[k]);
1702 silc_free(r->res_argv);
1703 silc_free(r->res_argv_lens);
1704 silc_free(r->res_argv_types);
1713 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1714 SilcClientEntry *clients,
1715 uint32 clients_count,
1716 SilcServerEntry *servers,
1717 uint32 servers_count,
1718 SilcChannelEntry *channels,
1719 uint32 channels_count,
1722 SilcServer server = cmd->server;
1723 int i, k, len, valid_count;
1724 SilcBuffer packet, idp;
1725 SilcCommandStatus status;
1726 uint16 ident = silc_command_get_ident(cmd->payload);
1727 char nh[256], uh[256];
1728 SilcSocketConnection hsock;
1730 status = SILC_STATUS_OK;
1733 SilcClientEntry entry;
1735 /* Process only valid entries. */
1737 for (i = 0; i < clients_count; i++) {
1738 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1745 /* No valid entries found at all, just send error */
1748 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1750 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1751 SILC_STATUS_ERR_NO_SUCH_NICK,
1752 3, tmp, strlen(tmp));
1754 tmp = silc_argument_get_arg_type(cmd->args, 5, (uint32 *)&len);
1755 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1756 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1762 /* Process all valid client entries and send command replies */
1764 if (valid_count > 1)
1765 status = SILC_STATUS_LIST_START;
1767 for (i = 0, k = 0; i < clients_count; i++) {
1773 status = SILC_STATUS_LIST_ITEM;
1774 if (valid_count > 1 && k == valid_count - 1
1775 && !servers_count && !channels_count)
1776 status = SILC_STATUS_LIST_END;
1777 if (count && k - 1 == count)
1778 status = SILC_STATUS_LIST_END;
1779 if (count && k - 1 > count)
1782 /* Send IDENTIFY reply */
1784 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1785 memset(uh, 0, sizeof(uh));
1786 memset(nh, 0, sizeof(nh));
1787 strncat(nh, entry->nickname, strlen(entry->nickname));
1788 if (!strchr(entry->nickname, '@')) {
1789 strncat(nh, "@", 1);
1790 if (entry->servername) {
1791 strncat(nh, entry->servername, strlen(entry->servername));
1793 len = entry->router ? strlen(entry->router->server_name) :
1794 strlen(server->server_name);
1795 strncat(nh, entry->router ? entry->router->server_name :
1796 server->server_name, len);
1800 if (!entry->username) {
1801 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1803 2, idp->data, idp->len,
1806 strncat(uh, entry->username, strlen(entry->username));
1807 if (!strchr(entry->username, '@')) {
1808 strncat(uh, "@", 1);
1809 hsock = (SilcSocketConnection)entry->connection;
1810 len = strlen(hsock->hostname);
1811 strncat(uh, hsock->hostname, len);
1814 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1816 2, idp->data, idp->len,
1821 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1822 0, packet->data, packet->len, FALSE);
1824 silc_buffer_free(packet);
1825 silc_buffer_free(idp);
1832 SilcServerEntry entry;
1834 if (status == SILC_STATUS_OK && servers_count > 1)
1835 status = SILC_STATUS_LIST_START;
1837 for (i = 0, k = 0; i < servers_count; i++) {
1841 status = SILC_STATUS_LIST_ITEM;
1842 if (servers_count > 1 && k == servers_count - 1 && !channels_count)
1843 status = SILC_STATUS_LIST_END;
1844 if (count && k - 1 == count)
1845 status = SILC_STATUS_LIST_END;
1846 if (count && k - 1 > count)
1849 /* Send IDENTIFY reply */
1850 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1852 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1854 2, idp->data, idp->len,
1855 3, entry->server_name,
1856 entry->server_name ?
1857 strlen(entry->server_name) : 0);
1858 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1859 0, packet->data, packet->len, FALSE);
1861 silc_buffer_free(packet);
1862 silc_buffer_free(idp);
1869 SilcChannelEntry entry;
1871 if (status == SILC_STATUS_OK && channels_count > 1)
1872 status = SILC_STATUS_LIST_START;
1874 for (i = 0, k = 0; i < channels_count; i++) {
1875 entry = channels[i];
1878 status = SILC_STATUS_LIST_ITEM;
1879 if (channels_count > 1 && k == channels_count - 1)
1880 status = SILC_STATUS_LIST_END;
1881 if (count && k - 1 == count)
1882 status = SILC_STATUS_LIST_END;
1883 if (count && k - 1 > count)
1886 /* Send IDENTIFY reply */
1887 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1889 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1891 2, idp->data, idp->len,
1892 3, entry->channel_name,
1893 entry->channel_name ?
1894 strlen(entry->channel_name): 0);
1895 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1896 0, packet->data, packet->len, FALSE);
1898 silc_buffer_free(packet);
1899 silc_buffer_free(idp);
1907 silc_server_command_identify_process(SilcServerCommandContext cmd)
1911 SilcClientEntry *clients = NULL;
1912 SilcServerEntry *servers = NULL;
1913 SilcChannelEntry *channels = NULL;
1914 uint32 clients_count = 0, servers_count = 0, channels_count = 0;
1916 /* Parse the IDENTIFY request */
1917 ret = silc_server_command_identify_parse(cmd,
1918 &clients, &clients_count,
1919 &servers, &servers_count,
1920 &channels, &channels_count,
1926 /* Check that all mandatory fields are present and request those data
1927 from the server who owns the client if necessary. */
1928 if (clients && !silc_server_command_identify_check_client(cmd, clients,
1934 /* Send the command reply to the client */
1935 silc_server_command_identify_send_reply(cmd,
1936 clients, clients_count,
1937 servers, servers_count,
1938 channels, channels_count,
1944 silc_free(channels);
1948 SILC_SERVER_CMD_FUNC(identify)
1950 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1953 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1955 ret = silc_server_command_identify_process(cmd);
1956 silc_server_command_free(cmd);
1959 /* Server side of command NICK. Sets nickname for user. Setting
1960 nickname causes generation of a new client ID for the client. The
1961 new client ID is sent to the client after changing the nickname. */
1963 SILC_SERVER_CMD_FUNC(nick)
1965 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1966 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1967 SilcServer server = cmd->server;
1968 SilcBuffer packet, nidp, oidp = NULL;
1969 SilcClientID *new_id;
1972 uint16 ident = silc_command_get_ident(cmd->payload);
1975 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1978 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
1980 /* Check nickname */
1981 nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
1984 if (silc_server_name_bad_chars(nick, nick_len) == TRUE) {
1985 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1986 SILC_STATUS_ERR_BAD_NICKNAME);
1990 /* Check for same nickname */
1991 if (!strcmp(client->nickname, nick)) {
1992 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1996 /* Create new Client ID */
1997 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
1999 cmd->server->md5hash, nick,
2002 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2005 /* Send notify about nickname change to our router. We send the new
2006 ID and ask to replace it with the old one. If we are router the
2007 packet is broadcasted. Send NICK_CHANGE notify. */
2008 if (!server->standalone)
2009 silc_server_send_notify_nick_change(server, server->router->connection,
2010 server->server_type == SILC_SERVER ?
2011 FALSE : TRUE, client->id,
2014 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2016 /* Remove old cache entry */
2017 silc_idcache_del_by_context(server->local_list->clients, client);
2020 silc_free(client->id);
2022 /* Save the nickname as this client is our local client */
2023 silc_free(client->nickname);
2025 client->nickname = strdup(nick);
2026 client->id = new_id;
2028 /* Update client cache */
2029 silc_idcache_add(server->local_list->clients, client->nickname,
2030 client->id, (void *)client, 0, NULL);
2032 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2034 /* Send NICK_CHANGE notify to the client's channels */
2035 silc_server_send_notify_on_channels(server, NULL, client,
2036 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
2037 oidp->data, oidp->len,
2038 nidp->data, nidp->len);
2041 /* Send the new Client ID as reply command back to client */
2042 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
2043 SILC_STATUS_OK, ident, 1,
2044 2, nidp->data, nidp->len);
2045 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2046 0, packet->data, packet->len, FALSE);
2048 silc_buffer_free(packet);
2049 silc_buffer_free(nidp);
2051 silc_buffer_free(oidp);
2054 silc_server_command_free(cmd);
2057 /* Sends the LIST command reply */
2060 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2061 SilcChannelEntry *lch,
2063 SilcChannelEntry *gch,
2067 SilcBuffer packet, idp;
2068 SilcChannelEntry entry;
2069 SilcCommandStatus status;
2070 uint16 ident = silc_command_get_ident(cmd->payload);
2072 unsigned char usercount[4];
2074 int valid_lcount = 0, valid_rcount = 0;
2076 for (i = 0; i < lch_count; i++) {
2077 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2082 for (i = 0; i < gch_count; i++) {
2083 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2089 status = SILC_STATUS_OK;
2090 if ((lch_count + gch_count) > 1)
2091 status = SILC_STATUS_LIST_START;
2094 for (i = 0, k = 0; i < lch_count; i++) {
2100 status = SILC_STATUS_LIST_ITEM;
2101 if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
2102 status = SILC_STATUS_LIST_END;
2104 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2106 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2107 topic = "*private*";
2108 memset(usercount, 0, sizeof(usercount));
2110 topic = entry->topic;
2111 users = silc_hash_table_count(entry->user_list);
2112 SILC_PUT32_MSB(users, usercount);
2115 /* Send the reply */
2117 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2119 2, idp->data, idp->len,
2120 3, entry->channel_name,
2121 strlen(entry->channel_name),
2122 4, topic, topic ? strlen(topic) : 0,
2124 silc_server_packet_send(cmd->server, cmd->sock,
2125 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2126 packet->len, FALSE);
2127 silc_buffer_free(packet);
2128 silc_buffer_free(idp);
2133 for (i = 0, k = 0; i < gch_count; i++) {
2139 status = SILC_STATUS_LIST_ITEM;
2140 if (valid_rcount > 1 && k == valid_rcount - 1)
2141 status = SILC_STATUS_LIST_END;
2143 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2145 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2146 topic = "*private*";
2147 memset(usercount, 0, sizeof(usercount));
2149 topic = entry->topic;
2150 users = silc_hash_table_count(entry->user_list);
2151 SILC_PUT32_MSB(users, usercount);
2154 /* Send the reply */
2156 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2158 2, idp->data, idp->len,
2159 3, entry->channel_name,
2160 strlen(entry->channel_name),
2161 4, topic, topic ? strlen(topic) : 0,
2163 silc_server_packet_send(cmd->server, cmd->sock,
2164 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2165 packet->len, FALSE);
2166 silc_buffer_free(packet);
2167 silc_buffer_free(idp);
2172 /* Server side of LIST command. This lists the channel of the requested
2173 server. Secret channels are not listed. */
2175 SILC_SERVER_CMD_FUNC(list)
2177 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2178 SilcServer server = cmd->server;
2179 SilcChannelID *channel_id = NULL;
2182 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2183 uint32 lch_count = 0, gch_count = 0;
2185 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2187 /* If we are normal server, send the command to router, since we
2188 want to know all channels in the network. */
2189 if (!cmd->pending && server->server_type == SILC_SERVER &&
2190 !server->standalone) {
2194 old_ident = silc_command_get_ident(cmd->payload);
2195 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2196 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2197 silc_server_packet_send(server, server->router->connection,
2198 SILC_PACKET_COMMAND, cmd->packet->flags,
2199 tmpbuf->data, tmpbuf->len, TRUE);
2201 /* Reprocess this packet after received reply from router */
2202 silc_server_command_pending(server, SILC_COMMAND_LIST,
2203 silc_command_get_ident(cmd->payload),
2204 silc_server_command_list,
2205 silc_server_command_dup(cmd));
2206 cmd->pending = TRUE;
2207 silc_command_set_ident(cmd->payload, old_ident);
2208 silc_buffer_free(tmpbuf);
2212 /* Get Channel ID */
2213 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2215 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2217 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2218 SILC_STATUS_ERR_NO_CHANNEL_ID);
2223 /* Get the channels from local list */
2224 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2227 /* Get the channels from global list */
2228 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2231 /* Send the reply */
2232 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2233 gchannels, gch_count);
2235 silc_free(lchannels);
2236 silc_free(gchannels);
2239 silc_server_command_free(cmd);
2242 /* Server side of TOPIC command. Sets topic for channel and/or returns
2243 current topic to client. */
2245 SILC_SERVER_CMD_FUNC(topic)
2247 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2248 SilcServer server = cmd->server;
2249 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2250 SilcChannelID *channel_id;
2251 SilcChannelEntry channel;
2252 SilcChannelClientEntry chl;
2253 SilcBuffer packet, idp;
2255 uint32 argc, tmp_len;
2256 uint16 ident = silc_command_get_ident(cmd->payload);
2258 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2260 argc = silc_argument_get_arg_num(cmd->args);
2262 /* Get Channel ID */
2263 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2265 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2266 SILC_STATUS_ERR_NO_CHANNEL_ID);
2269 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2271 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2272 SILC_STATUS_ERR_NO_CHANNEL_ID);
2276 /* Check whether the channel exists */
2277 channel = silc_idlist_find_channel_by_id(server->local_list,
2280 channel = silc_idlist_find_channel_by_id(server->global_list,
2283 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2284 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2291 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2293 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2294 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2298 if (strlen(tmp) > 256) {
2299 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2300 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2304 /* See whether the client is on channel and has rights to change topic */
2305 if (!silc_hash_table_find(channel->user_list, client, NULL,
2307 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2308 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2312 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2313 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2314 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2315 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2320 /* Set the topic for channel */
2321 silc_free(channel->topic);
2322 channel->topic = strdup(tmp);
2324 /* Send TOPIC_SET notify type to the network */
2325 if (!server->standalone)
2326 silc_server_send_notify_topic_set(server, server->router->connection,
2327 server->server_type == SILC_ROUTER ?
2328 TRUE : FALSE, channel,
2329 client->id, SILC_ID_CLIENT,
2332 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2334 /* Send notify about topic change to all clients on the channel */
2335 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2336 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2337 idp->data, idp->len,
2338 channel->topic, strlen(channel->topic));
2339 silc_buffer_free(idp);
2342 /* Send the topic to client as reply packet */
2343 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2344 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2345 SILC_STATUS_OK, ident, 2,
2346 2, idp->data, idp->len,
2349 strlen(channel->topic) : 0);
2350 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2351 0, packet->data, packet->len, FALSE);
2353 silc_buffer_free(packet);
2354 silc_buffer_free(idp);
2355 silc_free(channel_id);
2358 silc_server_command_free(cmd);
2361 /* Server side of INVITE command. Invites some client to join some channel.
2362 This command is also used to manage the invite list of the channel. */
2364 SILC_SERVER_CMD_FUNC(invite)
2366 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2367 SilcServer server = cmd->server;
2368 SilcSocketConnection sock = cmd->sock, dest_sock;
2369 SilcChannelClientEntry chl;
2370 SilcClientEntry sender, dest;
2371 SilcClientID *dest_id = NULL;
2372 SilcChannelEntry channel;
2373 SilcChannelID *channel_id = NULL;
2374 SilcIDListData idata;
2375 SilcBuffer idp, idp2, packet;
2376 unsigned char *tmp, *add, *del;
2378 uint16 ident = silc_command_get_ident(cmd->payload);
2380 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2382 /* Get Channel ID */
2383 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2385 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2386 SILC_STATUS_ERR_NO_CHANNEL_ID);
2389 channel_id = silc_id_payload_parse_id(tmp, len);
2391 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2392 SILC_STATUS_ERR_NO_CHANNEL_ID);
2396 /* Get the channel entry */
2397 channel = silc_idlist_find_channel_by_id(server->local_list,
2400 channel = silc_idlist_find_channel_by_id(server->global_list,
2403 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2404 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2409 /* Check whether the sender of this command is on the channel. */
2410 sender = (SilcClientEntry)sock->user_data;
2411 if (!silc_server_client_on_channel(sender, channel)) {
2412 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2413 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2417 /* Check whether the channel is invite-only channel. If yes then the
2418 sender of this command must be at least channel operator. */
2419 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2420 silc_hash_table_find(channel->user_list, sender, NULL, (void *)&chl);
2421 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2422 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2423 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2428 /* Get destination client ID */
2429 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2433 dest_id = silc_id_payload_parse_id(tmp, len);
2435 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2436 SILC_STATUS_ERR_NO_CLIENT_ID);
2440 /* Get the client entry */
2441 dest = silc_server_get_client_resolve(server, dest_id);
2443 if (server->server_type != SILC_SERVER) {
2444 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2445 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2449 /* The client info is being resolved. Reprocess this packet after
2450 receiving the reply to the query. */
2451 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2453 silc_server_command_invite,
2454 silc_server_command_dup(cmd));
2455 cmd->pending = TRUE;
2456 silc_free(channel_id);
2461 /* Check whether the requested client is already on the channel. */
2462 if (silc_server_client_on_channel(dest, channel)) {
2463 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2464 SILC_STATUS_ERR_USER_ON_CHANNEL);
2468 /* Get route to the client */
2469 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2471 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2472 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2476 memset(invite, 0, sizeof(invite));
2477 strncat(invite, dest->nickname, strlen(dest->nickname));
2478 strncat(invite, "!", 1);
2479 strncat(invite, dest->username, strlen(dest->username));
2480 if (!strchr(dest->username, '@')) {
2481 strncat(invite, "@", 1);
2482 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2485 len = strlen(invite);
2486 if (!channel->invite_list)
2487 channel->invite_list = silc_calloc(len + 2,
2488 sizeof(*channel->invite_list));
2490 channel->invite_list = silc_realloc(channel->invite_list,
2491 sizeof(*channel->invite_list) *
2493 strlen(channel->invite_list) + 2));
2494 strncat(channel->invite_list, invite, len);
2495 strncat(channel->invite_list, ",", 1);
2497 /* Send notify to the client that is invited to the channel */
2498 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2499 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2500 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2502 SILC_NOTIFY_TYPE_INVITE, 3,
2503 idp->data, idp->len,
2504 channel->channel_name,
2505 strlen(channel->channel_name),
2506 idp2->data, idp2->len);
2507 silc_buffer_free(idp);
2508 silc_buffer_free(idp2);
2511 /* Add the client to the invite list of the channel */
2512 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2514 if (!channel->invite_list)
2515 channel->invite_list = silc_calloc(len + 2,
2516 sizeof(*channel->invite_list));
2518 channel->invite_list = silc_realloc(channel->invite_list,
2519 sizeof(*channel->invite_list) *
2521 strlen(channel->invite_list) + 2));
2522 if (add[len - 1] == ',')
2523 add[len - 1] = '\0';
2525 strncat(channel->invite_list, add, len);
2526 strncat(channel->invite_list, ",", 1);
2529 /* Get the invite to be removed and remove it from the list */
2530 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2531 if (del && channel->invite_list) {
2532 char *start, *end, *n;
2534 if (!strncmp(channel->invite_list, del,
2535 strlen(channel->invite_list) - 1)) {
2536 silc_free(channel->invite_list);
2537 channel->invite_list = NULL;
2539 start = strstr(channel->invite_list, del);
2540 if (start && strlen(start) >= len) {
2542 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2543 strncat(n, channel->invite_list, start - channel->invite_list);
2544 strncat(n, end + 1, ((channel->invite_list +
2545 strlen(channel->invite_list)) - end) - 1);
2546 silc_free(channel->invite_list);
2547 channel->invite_list = n;
2552 /* Send notify to the primary router */
2553 if (!server->standalone)
2554 silc_server_send_notify_invite(server, server->router->connection,
2555 server->server_type == SILC_ROUTER ?
2556 TRUE : FALSE, channel,
2557 sender->id, add, del);
2559 /* Send command reply */
2560 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2564 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2565 SILC_STATUS_OK, ident, 2,
2567 3, channel->invite_list,
2568 channel->invite_list ?
2569 strlen(channel->invite_list) : 0);
2572 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2573 SILC_STATUS_OK, ident, 1,
2575 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2576 packet->data, packet->len, FALSE);
2577 silc_buffer_free(packet);
2581 silc_free(channel_id);
2582 silc_server_command_free(cmd);
2587 SilcSocketConnection sock;
2591 /* Quits connection to client. This gets called if client won't
2592 close the connection even when it has issued QUIT command. */
2594 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2596 QuitInternal q = (QuitInternal)context;
2598 /* Free all client specific data, such as client entry and entires
2599 on channels this client may be on. */
2600 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2602 q->sock->user_data = NULL;
2604 /* Close the connection on our side */
2605 silc_server_close_connection(q->server, q->sock);
2607 silc_free(q->signoff);
2611 /* Quits SILC session. This is the normal way to disconnect client. */
2613 SILC_SERVER_CMD_FUNC(quit)
2615 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2616 SilcServer server = cmd->server;
2617 SilcSocketConnection sock = cmd->sock;
2619 unsigned char *tmp = NULL;
2622 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2624 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2627 /* Get destination ID */
2628 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2632 q = silc_calloc(1, sizeof(*q));
2635 q->signoff = tmp ? strdup(tmp) : NULL;
2637 /* We quit the connection with little timeout */
2638 silc_schedule_task_add(server->schedule, sock->sock,
2639 silc_server_command_quit_cb, (void *)q,
2640 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2643 silc_server_command_free(cmd);
2646 /* Server side of command KILL. This command is used by router operator
2647 to remove an client from the SILC Network temporarily. */
2649 SILC_SERVER_CMD_FUNC(kill)
2651 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2652 SilcServer server = cmd->server;
2653 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2654 SilcClientEntry remote_client;
2655 SilcClientID *client_id;
2656 unsigned char *tmp, *comment;
2657 uint32 tmp_len, tmp_len2;
2659 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2661 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2664 /* KILL command works only on router */
2665 if (server->server_type != SILC_ROUTER) {
2666 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2667 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2671 /* Check whether client has the permissions. */
2672 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2673 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2674 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2678 /* Get the client ID */
2679 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2681 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2682 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2685 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2687 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2688 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2692 /* Get the client entry */
2693 remote_client = silc_idlist_find_client_by_id(server->local_list,
2694 client_id, TRUE, NULL);
2695 if (!remote_client) {
2696 remote_client = silc_idlist_find_client_by_id(server->global_list,
2697 client_id, TRUE, NULL);
2698 if (!remote_client) {
2699 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2700 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2706 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2710 /* Send reply to the sender */
2711 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2714 /* Send the KILL notify packets. First send it to the channel, then
2715 to our primary router and then directly to the client who is being
2716 killed right now. */
2718 /* Send KILLED notify to the channels. It is not sent to the client
2719 as it will be sent differently destined directly to the client and not
2721 silc_server_send_notify_on_channels(server, remote_client,
2722 remote_client, SILC_NOTIFY_TYPE_KILLED,
2725 comment, comment ? tmp_len2 : 0);
2727 /* Send KILLED notify to primary route */
2728 if (!server->standalone)
2729 silc_server_send_notify_killed(server, server->router->connection, TRUE,
2730 remote_client->id, comment);
2732 /* Send KILLED notify to the client directly */
2733 silc_server_send_notify_killed(server, remote_client->connection ?
2734 remote_client->connection :
2735 remote_client->router->connection, FALSE,
2736 remote_client->id, comment);
2738 /* Remove the client from all channels. This generates new keys to the
2739 channels as well. */
2740 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2743 /* Remove the client entry, If it is locally connected then we will also
2744 disconnect the client here */
2745 if (remote_client->connection) {
2746 /* Remove locally conneted client */
2747 SilcSocketConnection sock = remote_client->connection;
2748 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2749 silc_server_close_connection(server, sock);
2751 /* Remove remote client */
2752 if (!silc_idlist_del_client(server->global_list, remote_client))
2753 silc_idlist_del_client(server->local_list, remote_client);
2757 silc_server_command_free(cmd);
2760 /* Server side of command INFO. This sends information about us to
2761 the client. If client requested specific server we will send the
2762 command to that server. */
2764 SILC_SERVER_CMD_FUNC(info)
2766 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2767 SilcServer server = cmd->server;
2768 SilcBuffer packet, idp;
2771 char *dest_server, *server_info = NULL, *server_name;
2772 uint16 ident = silc_command_get_ident(cmd->payload);
2773 SilcServerEntry entry = NULL;
2774 SilcServerID *server_id = NULL;
2776 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2778 /* Get server name */
2779 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2782 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2784 server_id = silc_id_payload_parse_id(tmp, tmp_len);
2786 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2787 SILC_STATUS_ERR_NO_SERVER_ID);
2793 /* Check whether we have this server cached */
2794 entry = silc_idlist_find_server_by_id(server->local_list,
2795 server_id, TRUE, NULL);
2797 entry = silc_idlist_find_server_by_id(server->global_list,
2798 server_id, TRUE, NULL);
2799 if (!entry && server->server_type != SILC_SERVER) {
2800 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2801 SILC_STATUS_ERR_NO_SUCH_SERVER);
2807 /* Some buggy servers has sent request to router about themselves. */
2808 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2811 if ((!dest_server && !server_id && !entry) || (entry &&
2812 entry == server->id_entry) ||
2813 (dest_server && !cmd->pending &&
2814 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2815 /* Send our reply */
2816 char info_string[256];
2818 memset(info_string, 0, sizeof(info_string));
2819 snprintf(info_string, sizeof(info_string),
2820 "location: %s server: %s admin: %s <%s>",
2821 server->config->admin_info->location,
2822 server->config->admin_info->server_type,
2823 server->config->admin_info->admin_name,
2824 server->config->admin_info->admin_email);
2826 server_info = info_string;
2827 entry = server->id_entry;
2829 /* Check whether we have this server cached */
2830 if (!entry && dest_server) {
2831 entry = silc_idlist_find_server_by_name(server->global_list,
2832 dest_server, TRUE, NULL);
2834 entry = silc_idlist_find_server_by_name(server->local_list,
2835 dest_server, TRUE, NULL);
2839 if (!cmd->pending &&
2840 server->server_type != SILC_SERVER && entry && !entry->server_info) {
2841 /* Send to the server */
2845 old_ident = silc_command_get_ident(cmd->payload);
2846 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2847 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2849 silc_server_packet_send(server, entry->connection,
2850 SILC_PACKET_COMMAND, cmd->packet->flags,
2851 tmpbuf->data, tmpbuf->len, TRUE);
2853 /* Reprocess this packet after received reply from router */
2854 silc_server_command_pending(server, SILC_COMMAND_INFO,
2855 silc_command_get_ident(cmd->payload),
2856 silc_server_command_info,
2857 silc_server_command_dup(cmd));
2858 cmd->pending = TRUE;
2859 silc_command_set_ident(cmd->payload, old_ident);
2860 silc_buffer_free(tmpbuf);
2864 if (!entry && !cmd->pending && !server->standalone) {
2865 /* Send to the primary router */
2869 old_ident = silc_command_get_ident(cmd->payload);
2870 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2871 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2873 silc_server_packet_send(server, server->router->connection,
2874 SILC_PACKET_COMMAND, cmd->packet->flags,
2875 tmpbuf->data, tmpbuf->len, TRUE);
2877 /* Reprocess this packet after received reply from router */
2878 silc_server_command_pending(server, SILC_COMMAND_INFO,
2879 silc_command_get_ident(cmd->payload),
2880 silc_server_command_info,
2881 silc_server_command_dup(cmd));
2882 cmd->pending = TRUE;
2883 silc_command_set_ident(cmd->payload, old_ident);
2884 silc_buffer_free(tmpbuf);
2889 silc_free(server_id);
2892 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2893 SILC_STATUS_ERR_NO_SUCH_SERVER);
2897 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2899 server_info = entry->server_info;
2900 server_name = entry->server_name;
2902 /* Send the reply */
2903 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2904 SILC_STATUS_OK, ident, 3,
2905 2, idp->data, idp->len,
2907 strlen(server_name),
2910 strlen(server_info) : 0);
2911 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2912 packet->data, packet->len, FALSE);
2914 silc_buffer_free(packet);
2915 silc_buffer_free(idp);
2918 silc_server_command_free(cmd);
2921 /* Server side of command PING. This just replies to the ping. */
2923 SILC_SERVER_CMD_FUNC(ping)
2925 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2926 SilcServer server = cmd->server;
2931 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
2934 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2936 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2937 SILC_STATUS_ERR_NO_SERVER_ID);
2940 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2944 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2945 /* Send our reply */
2946 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2949 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2950 SILC_STATUS_ERR_NO_SUCH_SERVER);
2957 silc_server_command_free(cmd);
2960 /* Internal routine to join channel. The channel sent to this function
2961 has been either created or resolved from ID lists. This joins the sent
2962 client to the channel. */
2964 static void silc_server_command_join_channel(SilcServer server,
2965 SilcServerCommandContext cmd,
2966 SilcChannelEntry channel,
2967 SilcClientID *client_id,
2971 const unsigned char *auth,
2974 SilcSocketConnection sock = cmd->sock;
2976 uint32 tmp_len, user_count;
2977 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
2978 SilcClientEntry client;
2979 SilcChannelClientEntry chl;
2980 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
2981 uint16 ident = silc_command_get_ident(cmd->payload);
2982 char check[512], check2[512];
2983 bool founder = FALSE;
2985 SILC_LOG_DEBUG(("Start"));
2990 /* Get the client entry */
2991 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2992 client = (SilcClientEntry)sock->user_data;
2994 client = silc_server_get_client_resolve(server, client_id);
2999 /* The client info is being resolved. Reprocess this packet after
3000 receiving the reply to the query. */
3001 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
3003 silc_server_command_join,
3004 silc_server_command_dup(cmd));
3005 cmd->pending = TRUE;
3009 cmd->pending = FALSE;
3013 * Check founder auth payload if provided. If client can gain founder
3014 * privileges it can override various conditions on joining the channel,
3015 * and can have directly the founder mode set on the channel.
3017 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3018 SilcIDListData idata = (SilcIDListData)client;
3020 if (channel->founder_key && idata->public_key &&
3021 silc_pkcs_public_key_compare(channel->founder_key,
3022 idata->public_key)) {
3023 void *auth_data = (channel->founder_method == SILC_AUTH_PASSWORD ?
3024 (void *)channel->founder_passwd :
3025 (void *)channel->founder_key);
3026 uint32 auth_data_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
3027 channel->founder_passwd_len : 0);
3029 /* Check whether the client is to become founder */
3030 if (silc_auth_verify_data(auth, auth_len, channel->founder_method,
3031 auth_data, auth_data_len,
3032 idata->hash, client->id, SILC_ID_CLIENT)) {
3033 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3040 * Check channel modes
3044 memset(check, 0, sizeof(check));
3045 memset(check2, 0, sizeof(check2));
3046 strncat(check, client->nickname, strlen(client->nickname));
3047 strncat(check, "!", 1);
3048 strncat(check, client->username, strlen(client->username));
3049 if (!strchr(client->username, '@')) {
3050 strncat(check, "@", 1);
3051 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3054 strncat(check2, client->nickname, strlen(client->nickname));
3055 if (!strchr(client->nickname, '@')) {
3056 strncat(check2, "@", 1);
3057 strncat(check2, server->server_name, strlen(server->server_name));
3059 strncat(check2, "!", 1);
3060 strncat(check2, client->username, strlen(client->username));
3061 if (!strchr(client->username, '@')) {
3062 strncat(check2, "@", 1);
3063 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3066 /* Check invite list if channel is invite-only channel */
3067 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3068 if (!channel->invite_list ||
3069 (!silc_string_match(channel->invite_list, check) &&
3070 !silc_string_match(channel->invite_list, check2))) {
3071 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3072 SILC_STATUS_ERR_NOT_INVITED);
3077 /* Check ban list if it exists. If the client's nickname, server,
3078 username and/or hostname is in the ban list the access to the
3079 channel is denied. */
3080 if (channel->ban_list) {
3081 if (silc_string_match(channel->ban_list, check) ||
3082 silc_string_match(channel->ban_list, check2)) {
3083 silc_server_command_send_status_reply(
3084 cmd, SILC_COMMAND_JOIN,
3085 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
3090 /* Check user count limit if set. */
3091 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3092 if (silc_hash_table_count(channel->user_list) + 1 >
3093 channel->user_limit) {
3094 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3095 SILC_STATUS_ERR_CHANNEL_IS_FULL);
3101 /* Check the channel passphrase if set. */
3102 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3103 /* Get passphrase */
3104 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3106 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
3107 memcpy(passphrase, tmp, tmp_len);
3110 if (!passphrase || !channel->passphrase ||
3111 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3112 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3113 SILC_STATUS_ERR_BAD_PASSWORD);
3119 * Client is allowed to join to the channel. Make it happen.
3122 /* Check whether the client already is on the channel */
3123 if (silc_server_client_on_channel(client, channel)) {
3124 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3125 SILC_STATUS_ERR_USER_ON_CHANNEL);
3129 /* Generate new channel key as protocol dictates */
3131 if (!silc_server_create_channel_key(server, channel, 0))
3134 /* Send the channel key. This is broadcasted to the channel but is not
3135 sent to the client who is joining to the channel. */
3136 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3137 silc_server_send_channel_key(server, NULL, channel,
3138 server->server_type == SILC_ROUTER ?
3139 FALSE : !server->standalone);
3142 /* Join the client to the channel by adding it to channel's user list.
3143 Add also the channel to client entry's channels list for fast cross-
3145 chl = silc_calloc(1, sizeof(*chl));
3147 chl->client = client;
3148 chl->channel = channel;
3149 silc_hash_table_add(channel->user_list, client, chl);
3150 silc_hash_table_add(client->channels, channel, chl);
3152 /* Get users on the channel */
3153 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3156 /* Encode Client ID Payload of the original client who wants to join */
3157 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3159 /* Encode command reply packet */
3160 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3161 SILC_PUT32_MSB(channel->mode, mode);
3162 SILC_PUT32_MSB(created, tmp2);
3163 SILC_PUT32_MSB(user_count, tmp3);
3165 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3166 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3167 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
3168 strlen(channel->channel_key->
3170 channel->channel_key->cipher->name,
3171 channel->key_len / 8, channel->key);
3176 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3177 SILC_STATUS_OK, ident, 13,
3178 2, channel->channel_name,
3179 strlen(channel->channel_name),
3180 3, chidp->data, chidp->len,
3181 4, clidp->data, clidp->len,
3184 7, keyp ? keyp->data : NULL,
3185 keyp ? keyp->len : 0,
3186 8, channel->ban_list,
3188 strlen(channel->ban_list) : 0,
3189 9, channel->invite_list,
3190 channel->invite_list ?
3191 strlen(channel->invite_list) : 0,
3194 strlen(channel->topic) : 0,
3195 11, silc_hmac_get_name(channel->hmac),
3196 strlen(silc_hmac_get_name(channel->
3199 13, user_list->data, user_list->len,
3200 14, mode_list->data,
3203 /* Send command reply */
3204 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3205 reply->data, reply->len, FALSE);
3207 /* Send JOIN notify to locally connected clients on the channel. If
3208 we are normal server then router will send or have sent JOIN notify
3209 already. However since we've added the client already to our channel
3210 we'll ignore it (in packet_receive.c) so we must send it here. If
3211 we are router then this will send it to local clients and local
3213 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3214 SILC_NOTIFY_TYPE_JOIN, 2,
3215 clidp->data, clidp->len,
3216 chidp->data, chidp->len);
3218 if (!cmd->pending) {
3219 /* Send JOIN notify packet to our primary router */
3220 if (!server->standalone)
3221 silc_server_send_notify_join(server, server->router->connection,
3222 server->server_type == SILC_ROUTER ?
3223 TRUE : FALSE, channel, client->id);
3226 /* Distribute the channel key to all backup routers. */
3227 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3228 keyp->data, keyp->len, FALSE, TRUE);
3230 /* If client became founder by providing correct founder auth data
3231 notify the mode change to the channel. */
3233 SILC_PUT32_MSB(chl->mode, mode);
3234 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3235 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3236 clidp->data, clidp->len,
3237 mode, 4, clidp->data, clidp->len);
3239 /* Set CUMODE notify type to network */
3240 if (!server->standalone)
3241 silc_server_send_notify_cumode(server, server->router->connection,
3242 server->server_type == SILC_ROUTER ?
3243 TRUE : FALSE, channel,
3244 chl->mode, client->id, SILC_ID_CLIENT,
3249 silc_buffer_free(reply);
3250 silc_buffer_free(clidp);
3251 silc_buffer_free(chidp);
3252 silc_buffer_free(keyp);
3253 silc_buffer_free(user_list);
3254 silc_buffer_free(mode_list);
3257 silc_free(passphrase);
3260 /* Server side of command JOIN. Joins client into requested channel. If
3261 the channel does not exist it will be created. */
3263 SILC_SERVER_CMD_FUNC(join)
3265 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3266 SilcServer server = cmd->server;
3267 unsigned char *auth;
3268 uint32 tmp_len, auth_len;
3269 char *tmp, *channel_name = NULL, *cipher, *hmac;
3270 SilcChannelEntry channel;
3272 bool created = FALSE, create_key = TRUE;
3273 SilcClientID *client_id;
3275 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3277 /* Get channel name */
3278 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3280 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3281 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3287 channel_name[255] = '\0';
3289 if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
3290 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3291 SILC_STATUS_ERR_BAD_CHANNEL);
3295 /* Get Client ID of the client who is joining to the channel */
3296 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3298 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3299 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3302 client_id = silc_id_payload_parse_id(tmp, tmp_len);
3304 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3305 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3309 /* Get cipher, hmac name and auth payload */
3310 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3311 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3312 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3314 /* See if the channel exists */
3315 channel = silc_idlist_find_channel_by_name(server->local_list,
3316 channel_name, NULL);
3318 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3319 /* If this is coming from client the Client ID in the command packet must
3320 be same as the client's ID. */
3321 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3322 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3323 if (!SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
3324 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3325 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3330 if (!channel || channel->disabled) {
3331 /* Channel not found */
3333 /* If we are standalone server we don't have a router, we just create
3334 the channel by ourselves. */
3335 if (server->standalone) {
3336 channel = silc_server_create_new_channel(server, server->id, cipher,
3337 hmac, channel_name, TRUE);
3339 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3340 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3344 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3350 /* The channel does not exist on our server. If we are normal server
3351 we will send JOIN command to our router which will handle the
3352 joining procedure (either creates the channel if it doesn't exist
3353 or joins the client to it). */
3354 if (server->server_type != SILC_ROUTER) {
3358 /* If this is pending command callback then we've resolved
3359 it and it didn't work, return since we've notified the
3360 client already in the command reply callback. */
3364 old_ident = silc_command_get_ident(cmd->payload);
3365 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3366 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3368 /* Send JOIN command to our router */
3369 silc_server_packet_send(server, (SilcSocketConnection)
3370 server->router->connection,
3371 SILC_PACKET_COMMAND, cmd->packet->flags,
3372 tmpbuf->data, tmpbuf->len, TRUE);
3374 /* Reprocess this packet after received reply from router */
3375 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3376 silc_command_get_ident(cmd->payload),
3377 silc_server_command_join,
3378 silc_server_command_dup(cmd));
3379 cmd->pending = TRUE;
3383 /* We are router and the channel does not seem exist so we will check
3384 our global list as well for the channel. */
3385 channel = silc_idlist_find_channel_by_name(server->global_list,
3386 channel_name, NULL);
3388 /* Channel really does not exist, create it */
3389 channel = silc_server_create_new_channel(server, server->id, cipher,
3390 hmac, channel_name, TRUE);
3392 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3393 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3397 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3405 /* Channel not found */
3407 /* If the command came from router and we are normal server then
3408 something went wrong with the joining as the channel was not found.
3409 We can't do anything else but ignore this. */
3410 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3411 server->server_type != SILC_ROUTER)
3414 /* We are router and the channel does not seem exist so we will check
3415 our global list as well for the channel. */
3416 channel = silc_idlist_find_channel_by_name(server->global_list,
3417 channel_name, NULL);
3419 /* Channel really does not exist, create it */
3420 channel = silc_server_create_new_channel(server, server->id, cipher,
3421 hmac, channel_name, TRUE);
3423 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3424 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3428 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3435 /* Check whether the channel was created by our router */
3436 if (cmd->pending && context2) {
3437 SilcServerCommandReplyContext reply =
3438 (SilcServerCommandReplyContext)context2;
3440 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3441 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3442 SILC_GET32_MSB(created, tmp);
3443 create_key = FALSE; /* Router returned the key already */
3446 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS)
3450 /* If the channel does not have global users and is also empty the client
3451 will be the channel founder and operator. */
3452 if (!channel->global_users && !silc_hash_table_count(channel->user_list))
3453 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3455 /* Join to the channel */
3456 silc_server_command_join_channel(server, cmd, channel, client_id,
3457 created, create_key, umode,
3460 silc_free(client_id);
3463 silc_server_command_free(cmd);
3466 /* Server side of command MOTD. Sends server's current "message of the
3467 day" to the client. */
3469 SILC_SERVER_CMD_FUNC(motd)
3471 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3472 SilcServer server = cmd->server;
3473 SilcBuffer packet, idp;
3474 char *motd, *dest_server;
3476 uint16 ident = silc_command_get_ident(cmd->payload);
3478 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3480 /* Get server name */
3481 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3483 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3484 SILC_STATUS_ERR_NO_SUCH_SERVER);
3488 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3491 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3493 if (server->config && server->config->motd &&
3494 server->config->motd->motd_file) {
3496 motd = silc_file_readfile(server->config->motd->motd_file, &motd_len);
3501 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3502 SILC_STATUS_OK, ident, 2,
3507 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3508 SILC_STATUS_OK, ident, 1,
3512 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3513 packet->data, packet->len, FALSE);
3514 silc_buffer_free(packet);
3515 silc_buffer_free(idp);
3517 SilcServerEntry entry;
3519 /* Check whether we have this server cached */
3520 entry = silc_idlist_find_server_by_name(server->global_list,
3521 dest_server, TRUE, NULL);
3523 entry = silc_idlist_find_server_by_name(server->local_list,
3524 dest_server, TRUE, NULL);
3527 if (server->server_type != SILC_SERVER && !cmd->pending &&
3528 entry && !entry->motd) {
3529 /* Send to the server */
3533 old_ident = silc_command_get_ident(cmd->payload);
3534 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3535 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3537 silc_server_packet_send(server, entry->connection,
3538 SILC_PACKET_COMMAND, cmd->packet->flags,
3539 tmpbuf->data, tmpbuf->len, TRUE);
3541 /* Reprocess this packet after received reply from router */
3542 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3543 silc_command_get_ident(cmd->payload),
3544 silc_server_command_motd,
3545 silc_server_command_dup(cmd));
3546 cmd->pending = TRUE;
3547 silc_command_set_ident(cmd->payload, old_ident);
3548 silc_buffer_free(tmpbuf);
3552 if (!entry && !cmd->pending && !server->standalone) {
3553 /* Send to the primary router */
3557 old_ident = silc_command_get_ident(cmd->payload);
3558 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3559 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3561 silc_server_packet_send(server, server->router->connection,
3562 SILC_PACKET_COMMAND, cmd->packet->flags,
3563 tmpbuf->data, tmpbuf->len, TRUE);
3565 /* Reprocess this packet after received reply from router */
3566 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3567 silc_command_get_ident(cmd->payload),
3568 silc_server_command_motd,
3569 silc_server_command_dup(cmd));
3570 cmd->pending = TRUE;
3571 silc_command_set_ident(cmd->payload, old_ident);
3572 silc_buffer_free(tmpbuf);
3577 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3578 SILC_STATUS_ERR_NO_SUCH_SERVER);
3582 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3583 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3584 SILC_STATUS_OK, ident, 2,
3588 strlen(entry->motd) : 0);
3589 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3590 packet->data, packet->len, FALSE);
3591 silc_buffer_free(packet);
3592 silc_buffer_free(idp);
3596 silc_server_command_free(cmd);
3599 /* Server side of command UMODE. Client can use this command to set/unset
3600 user mode. Client actually cannot set itself to be as server/router
3601 operator so this can be used only to unset the modes. */
3603 SILC_SERVER_CMD_FUNC(umode)
3605 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3606 SilcServer server = cmd->server;
3607 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3609 unsigned char *tmp_mask;
3611 uint16 ident = silc_command_get_ident(cmd->payload);
3613 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3616 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 2, 2);
3618 /* Get the client's mode mask */
3619 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3621 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3622 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3625 SILC_GET32_MSB(mask, tmp_mask);
3631 if (mask & SILC_UMODE_SERVER_OPERATOR) {
3632 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR)) {
3633 /* Cannot operator mode */
3634 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3635 SILC_STATUS_ERR_PERM_DENIED);
3639 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
3640 /* Remove the server operator rights */
3641 client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3644 if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3645 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
3646 /* Cannot operator mode */
3647 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3648 SILC_STATUS_ERR_PERM_DENIED);
3652 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
3653 /* Remove the router operator rights */
3654 client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3657 if (mask & SILC_UMODE_GONE) {
3658 client->mode |= SILC_UMODE_GONE;
3660 if (client->mode & SILC_UMODE_GONE)
3661 /* Remove the gone status */
3662 client->mode &= ~SILC_UMODE_GONE;
3665 /* Send UMODE change to primary router */
3666 if (!server->standalone)
3667 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3668 client->id, client->mode);
3670 /* Send command reply to sender */
3671 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3672 SILC_STATUS_OK, ident, 1,
3674 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3675 packet->data, packet->len, FALSE);
3676 silc_buffer_free(packet);
3679 silc_server_command_free(cmd);
3682 /* Checks that client has rights to add or remove channel modes. If any
3683 of the checks fails FALSE is returned. */
3685 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3686 SilcChannelClientEntry client,
3689 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3690 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3692 /* Check whether has rights to change anything */
3693 if (!is_op && !is_fo)
3696 /* Check whether has rights to change everything */
3700 /* We know that client is channel operator, check that they are not
3701 changing anything that requires channel founder rights. Rest of the
3702 modes are available automatically for channel operator. */
3704 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3705 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3706 if (is_op && !is_fo)
3709 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3710 if (is_op && !is_fo)
3715 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3716 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE))
3717 if (is_op && !is_fo)
3720 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3721 if (is_op && !is_fo)
3726 if (mode & SILC_CHANNEL_MODE_CIPHER) {
3727 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER))
3728 if (is_op && !is_fo)
3731 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3732 if (is_op && !is_fo)
3737 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3738 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH))
3739 if (is_op && !is_fo)
3742 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3743 if (is_op && !is_fo)
3751 /* Server side command of CMODE. Changes channel mode */
3753 SILC_SERVER_CMD_FUNC(cmode)
3755 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3756 SilcServer server = cmd->server;
3757 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3758 SilcIDListData idata = (SilcIDListData)client;
3759 SilcChannelID *channel_id;
3760 SilcChannelEntry channel;
3761 SilcChannelClientEntry chl;
3762 SilcBuffer packet, cidp;
3763 unsigned char *tmp, *tmp_id, *tmp_mask;
3764 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3765 uint32 mode_mask, tmp_len, tmp_len2;
3766 uint16 ident = silc_command_get_ident(cmd->payload);
3768 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 2, 7);
3770 /* Get Channel ID */
3771 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3773 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3774 SILC_STATUS_ERR_NO_CHANNEL_ID);
3777 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3779 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3780 SILC_STATUS_ERR_NO_CHANNEL_ID);
3784 /* Get the channel mode mask */
3785 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3787 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3788 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3791 SILC_GET32_MSB(mode_mask, tmp_mask);
3793 /* Get channel entry */
3794 channel = silc_idlist_find_channel_by_id(server->local_list,
3797 channel = silc_idlist_find_channel_by_id(server->global_list,
3800 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3801 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3806 /* Check whether this client is on the channel */
3807 if (!silc_server_client_on_channel(client, channel)) {
3808 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3809 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3813 /* Get entry to the channel user list */
3814 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
3816 /* Check that client has rights to change any requested channel modes */
3817 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3818 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3819 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3824 * Check the modes. Modes that requires nothing special operation are
3828 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3829 /* Channel uses private keys to protect traffic. Client(s) has set the
3830 key locally they want to use, server does not know that key. */
3831 /* Nothing interesting to do here */
3833 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3834 /* The mode is removed and we need to generate and distribute
3835 new channel key. Clients are not using private channel keys
3836 anymore after this. */
3838 /* Re-generate channel key */
3839 if (!silc_server_create_channel_key(server, channel, 0))
3842 /* Send the channel key. This sends it to our local clients and if
3843 we are normal server to our router as well. */
3844 silc_server_send_channel_key(server, NULL, channel,
3845 server->server_type == SILC_ROUTER ?
3846 FALSE : !server->standalone);
3848 cipher = channel->channel_key->cipher->name;
3849 hmac = (char *)silc_hmac_get_name(channel->hmac);
3853 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3854 /* User limit is set on channel */
3857 /* Get user limit */
3858 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3860 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3861 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3862 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3866 SILC_GET32_MSB(user_limit, tmp);
3867 channel->user_limit = user_limit;
3870 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3871 /* User limit mode is unset. Remove user limit */
3872 channel->user_limit = 0;
3875 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3876 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3877 /* Passphrase has been set to channel */
3879 /* Get the passphrase */
3880 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3882 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3883 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3887 /* Save the passphrase */
3888 passphrase = channel->passphrase = strdup(tmp);
3891 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3892 /* Passphrase mode is unset. remove the passphrase */
3893 if (channel->passphrase) {
3894 silc_free(channel->passphrase);
3895 channel->passphrase = NULL;
3900 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3901 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3902 /* Cipher to use protect the traffic */
3903 SilcCipher newkey, oldkey;
3906 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3908 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3909 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3913 /* Delete old cipher and allocate the new one */
3914 if (!silc_cipher_alloc(cipher, &newkey)) {
3915 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3916 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3920 oldkey = channel->channel_key;
3921 channel->channel_key = newkey;
3923 /* Re-generate channel key */
3924 if (!silc_server_create_channel_key(server, channel, 0)) {
3925 /* We don't have new key, revert to old one */
3926 channel->channel_key = oldkey;
3930 /* Remove old channel key for good */
3931 silc_cipher_free(oldkey);
3933 /* Send the channel key. This sends it to our local clients and if
3934 we are normal server to our router as well. */
3935 silc_server_send_channel_key(server, NULL, channel,
3936 server->server_type == SILC_ROUTER ?
3937 FALSE : !server->standalone);
3940 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3941 /* Cipher mode is unset. Remove the cipher and revert back to
3943 SilcCipher newkey, oldkey;
3944 cipher = channel->cipher;
3946 /* Delete old cipher and allocate default one */
3947 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
3948 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3949 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3953 oldkey = channel->channel_key;
3954 channel->channel_key = newkey;
3956 /* Re-generate channel key */
3957 if (!silc_server_create_channel_key(server, channel, 0)) {
3958 /* We don't have new key, revert to old one */
3959 channel->channel_key = oldkey;
3963 /* Remove old channel key for good */
3964 silc_cipher_free(oldkey);
3966 /* Send the channel key. This sends it to our local clients and if
3967 we are normal server to our router as well. */
3968 silc_server_send_channel_key(server, NULL, channel,
3969 server->server_type == SILC_ROUTER ?
3970 FALSE : !server->standalone);
3974 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3975 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3976 /* HMAC to use protect the traffic */
3977 unsigned char hash[32];
3981 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3983 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3984 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3988 /* Delete old hmac and allocate the new one */
3989 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
3990 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3991 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3995 silc_hmac_free(channel->hmac);
3996 channel->hmac = newhmac;
3998 /* Set the HMAC key out of current channel key. The client must do
4000 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4001 channel->key_len / 8, hash);
4002 silc_hmac_set_key(channel->hmac, hash,
4003 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4004 memset(hash, 0, sizeof(hash));
4007 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4008 /* Hmac mode is unset. Remove the hmac and revert back to
4011 unsigned char hash[32];
4012 hmac = channel->hmac_name;
4014 /* Delete old hmac and allocate default one */
4015 silc_hmac_free(channel->hmac);
4016 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4017 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4018 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4022 silc_hmac_free(channel->hmac);
4023 channel->hmac = newhmac;
4025 /* Set the HMAC key out of current channel key. The client must do
4027 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4028 channel->key_len / 8,
4030 silc_hmac_set_key(channel->hmac, hash,
4031 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4032 memset(hash, 0, sizeof(hash));
4036 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4037 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4038 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4039 /* Set the founder authentication */
4040 SilcAuthPayload auth;
4042 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4044 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4045 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4049 auth = silc_auth_payload_parse(tmp, tmp_len);
4051 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4052 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4056 /* Save the public key */
4057 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
4058 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
4061 channel->founder_method = silc_auth_get_method(auth);
4063 if (channel->founder_method == SILC_AUTH_PASSWORD) {
4064 tmp = silc_auth_get_data(auth, &tmp_len);
4065 channel->founder_passwd =
4066 silc_calloc(tmp_len + 1, sizeof(*channel->founder_passwd));
4067 memcpy(channel->founder_passwd, tmp, tmp_len);
4068 channel->founder_passwd_len = tmp_len;
4070 /* Verify the payload before setting the mode */
4071 if (!silc_auth_verify(auth, channel->founder_method,
4072 channel->founder_key, 0, idata->hash,
4073 client->id, SILC_ID_CLIENT)) {
4074 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4075 SILC_STATUS_ERR_AUTH_FAILED);
4080 silc_auth_payload_free(auth);
4084 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4085 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4086 if (channel->founder_key)
4087 silc_pkcs_public_key_free(channel->founder_key);
4088 if (channel->founder_passwd) {
4089 silc_free(channel->founder_passwd);
4090 channel->founder_passwd = NULL;
4096 /* Finally, set the mode */
4097 channel->mode = mode_mask;
4099 /* Send CMODE_CHANGE notify. */
4100 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4101 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4102 SILC_NOTIFY_TYPE_CMODE_CHANGE, 5,
4103 cidp->data, cidp->len,
4105 cipher, cipher ? strlen(cipher) : 0,
4106 hmac, hmac ? strlen(hmac) : 0,
4107 passphrase, passphrase ?
4108 strlen(passphrase) : 0);
4110 /* Set CMODE notify type to network */
4111 if (!server->standalone)
4112 silc_server_send_notify_cmode(server, server->router->connection,
4113 server->server_type == SILC_ROUTER ?
4114 TRUE : FALSE, channel,
4115 mode_mask, client->id, SILC_ID_CLIENT,
4116 cipher, hmac, passphrase);
4118 /* Send command reply to sender */
4119 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4120 SILC_STATUS_OK, ident, 2,
4121 2, tmp_id, tmp_len2,
4123 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4124 packet->data, packet->len, FALSE);
4126 silc_buffer_free(packet);
4127 silc_free(channel_id);
4128 silc_buffer_free(cidp);
4131 silc_server_command_free(cmd);
4134 /* Server side of CUMODE command. Changes client's mode on a channel. */
4136 SILC_SERVER_CMD_FUNC(cumode)
4138 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4139 SilcServer server = cmd->server;
4140 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4141 SilcIDListData idata = (SilcIDListData)client;
4142 SilcChannelID *channel_id;
4143 SilcClientID *client_id;
4144 SilcChannelEntry channel;
4145 SilcClientEntry target_client;
4146 SilcChannelClientEntry chl;
4147 SilcBuffer packet, idp;
4148 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4149 uint32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4151 uint16 ident = silc_command_get_ident(cmd->payload);
4153 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4155 /* Get Channel ID */
4156 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4158 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4159 SILC_STATUS_ERR_NO_CHANNEL_ID);
4162 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
4164 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4165 SILC_STATUS_ERR_NO_CHANNEL_ID);
4169 /* Get channel entry */
4170 channel = silc_idlist_find_channel_by_id(server->local_list,
4173 channel = silc_idlist_find_channel_by_id(server->global_list,
4176 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4177 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4182 /* Check whether sender is on the channel */
4183 if (!silc_server_client_on_channel(client, channel)) {
4184 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4185 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4189 /* Check that client has rights to change other's rights */
4190 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4191 sender_mask = chl->mode;
4193 /* Get the target client's channel mode mask */
4194 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4196 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4197 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4200 SILC_GET32_MSB(target_mask, tmp_mask);
4202 /* Get target Client ID */
4203 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4205 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4206 SILC_STATUS_ERR_NO_CLIENT_ID);
4209 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
4211 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4212 SILC_STATUS_ERR_NO_CLIENT_ID);
4216 /* Get target client's entry */
4217 target_client = silc_idlist_find_client_by_id(server->local_list,
4218 client_id, TRUE, NULL);
4219 if (!target_client) {
4220 target_client = silc_idlist_find_client_by_id(server->global_list,
4221 client_id, TRUE, NULL);
4224 if (target_client != client &&
4225 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4226 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4227 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4228 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4232 /* Check whether target client is on the channel */
4233 if (target_client != client) {
4234 if (!silc_server_client_on_channel(target_client, channel)) {
4235 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4236 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4240 /* Get entry to the channel user list */
4241 silc_hash_table_find(channel->user_list, target_client, NULL,
4249 /* If the target client is founder, no one else can change their mode
4251 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
4252 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4253 SILC_STATUS_ERR_NOT_YOU);
4257 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4258 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4259 /* The client tries to claim the founder rights. */
4260 unsigned char *tmp_auth;
4261 uint32 tmp_auth_len, auth_len;
4264 if (target_client != client) {
4265 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4266 SILC_STATUS_ERR_NOT_YOU);
4270 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4271 !channel->founder_key || !idata->public_key ||
4272 !silc_pkcs_public_key_compare(channel->founder_key,
4273 idata->public_key)) {
4274 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4275 SILC_STATUS_ERR_NOT_YOU);
4279 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4281 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4282 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4286 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4287 (void *)channel->founder_passwd : (void *)channel->founder_key);
4288 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4289 channel->founder_passwd_len : 0);
4291 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4292 channel->founder_method, auth, auth_len,
4293 idata->hash, client->id, SILC_ID_CLIENT)) {
4294 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4295 SILC_STATUS_ERR_AUTH_FAILED);
4299 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4303 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4304 if (target_client == client) {
4305 /* Remove channel founder rights from itself */
4306 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4309 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4310 SILC_STATUS_ERR_NOT_YOU);
4316 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4317 /* Promote to operator */
4318 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4319 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4320 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4321 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4322 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4326 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4330 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4331 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4332 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4333 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4334 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4338 /* Demote to normal user */
4339 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4344 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4345 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4347 /* Send notify to channel, notify only if mode was actually changed. */
4349 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4350 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4351 idp->data, idp->len,
4355 /* Set CUMODE notify type to network */
4356 if (!server->standalone)
4357 silc_server_send_notify_cumode(server, server->router->connection,
4358 server->server_type == SILC_ROUTER ?
4359 TRUE : FALSE, channel,
4360 target_mask, client->id,
4365 /* Send command reply to sender */
4366 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4367 SILC_STATUS_OK, ident, 3,
4369 3, tmp_ch_id, tmp_ch_len,
4370 4, tmp_id, tmp_len);
4371 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4372 packet->data, packet->len, FALSE);
4374 silc_buffer_free(packet);
4375 silc_free(channel_id);
4376 silc_free(client_id);
4377 silc_buffer_free(idp);
4380 silc_server_command_free(cmd);
4383 /* Server side of KICK command. Kicks client out of channel. */
4385 SILC_SERVER_CMD_FUNC(kick)
4387 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4388 SilcServer server = cmd->server;
4389 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4390 SilcClientEntry target_client;
4391 SilcChannelID *channel_id;
4392 SilcClientID *client_id;
4393 SilcChannelEntry channel;
4394 SilcChannelClientEntry chl;
4396 uint32 tmp_len, target_idp_len;
4397 unsigned char *tmp, *comment, *target_idp;
4399 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4401 /* Get Channel ID */
4402 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4404 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4405 SILC_STATUS_ERR_NO_CHANNEL_ID);
4408 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
4410 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4411 SILC_STATUS_ERR_NO_CHANNEL_ID);
4415 /* Get channel entry */
4416 channel = silc_idlist_find_channel_by_id(server->local_list,
4419 channel = silc_idlist_find_channel_by_id(server->local_list,
4422 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4423 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4428 /* Check whether sender is on the channel */
4429 if (!silc_server_client_on_channel(client, channel)) {
4430 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4431 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4435 /* Check that the kicker is channel operator or channel founder */
4436 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4437 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4438 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4439 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4443 /* Get target Client ID */
4444 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4446 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4447 SILC_STATUS_ERR_NO_CLIENT_ID);
4450 client_id = silc_id_payload_parse_id(target_idp, target_idp_len);
4452 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4453 SILC_STATUS_ERR_NO_CLIENT_ID);
4457 /* Get target client's entry */
4458 target_client = silc_idlist_find_client_by_id(server->local_list,
4459 client_id, TRUE, NULL);
4460 if (!target_client) {
4461 target_client = silc_idlist_find_client_by_id(server->global_list,
4462 client_id, TRUE, NULL);
4465 /* Check that the target client is not channel founder. Channel founder
4466 cannot be kicked from the channel. */
4467 silc_hash_table_find(channel->user_list, target_client, NULL, (void *)&chl);
4468 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4469 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4470 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4474 /* Check whether target client is on the channel */
4475 if (!silc_server_client_on_channel(target_client, channel)) {
4476 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4477 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4483 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4487 /* Send command reply to sender */
4488 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4491 /* Send KICKED notify to local clients on the channel */
4492 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4493 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4494 SILC_NOTIFY_TYPE_KICKED, 3,
4495 target_idp, target_idp_len,
4496 comment, comment ? strlen(comment) : 0,
4497 idp->data, idp->len);
4498 silc_buffer_free(idp);
4500 /* Remove the client from the channel. If the channel does not exist
4501 after removing the client then the client kicked itself off the channel
4502 and we don't have to send anything after that. */
4503 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4504 target_client, FALSE))
4507 /* Send KICKED notify to primary route */
4508 if (!server->standalone)
4509 silc_server_send_notify_kicked(server, server->router->connection,
4510 server->server_type == SILC_ROUTER ?
4511 TRUE : FALSE, channel,
4512 target_client->id, comment);
4514 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4515 /* Re-generate channel key */
4516 if (!silc_server_create_channel_key(server, channel, 0))
4519 /* Send the channel key to the channel. The key of course is not sent
4520 to the client who was kicked off the channel. */
4521 silc_server_send_channel_key(server, target_client->connection, channel,
4522 server->server_type == SILC_ROUTER ?
4523 FALSE : !server->standalone);
4527 silc_server_command_free(cmd);
4530 /* Server side of OPER command. Client uses this comand to obtain server
4531 operator privileges to this server/router. */
4533 SILC_SERVER_CMD_FUNC(oper)
4535 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4536 SilcServer server = cmd->server;
4537 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4538 unsigned char *username, *auth;
4540 SilcServerConfigSectionAdminConnection *admin;
4541 SilcIDListData idata = (SilcIDListData)client;
4543 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4545 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4548 /* Get the username */
4549 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4551 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4552 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4556 /* Get the admin configuration */
4557 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4558 username, client->nickname);
4560 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4561 username, client->nickname);
4563 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4564 SILC_STATUS_ERR_AUTH_FAILED);
4569 /* Get the authentication payload */
4570 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4572 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4573 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4577 /* Verify the authentication data */
4578 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4579 admin->auth_data, admin->auth_data_len,
4580 idata->hash, client->id, SILC_ID_CLIENT)) {
4581 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4582 SILC_STATUS_ERR_AUTH_FAILED);
4586 /* Client is now server operator */
4587 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4589 /* Send UMODE change to primary router */
4590 if (!server->standalone)
4591 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4592 client->id, client->mode);
4594 /* Send reply to the sender */
4595 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4599 silc_server_command_free(cmd);
4602 /* Server side of SILCOPER command. Client uses this comand to obtain router
4603 operator privileges to this router. */
4605 SILC_SERVER_CMD_FUNC(silcoper)
4607 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4608 SilcServer server = cmd->server;
4609 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4610 unsigned char *username, *auth;
4612 SilcServerConfigSectionAdminConnection *admin;
4613 SilcIDListData idata = (SilcIDListData)client;
4615 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4617 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4620 if (server->server_type != SILC_ROUTER) {
4621 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4622 SILC_STATUS_ERR_AUTH_FAILED);
4626 /* Get the username */
4627 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4629 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4630 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4634 /* Get the admin configuration */
4635 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4636 username, client->nickname);
4638 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4639 username, client->nickname);
4641 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4642 SILC_STATUS_ERR_AUTH_FAILED);
4647 /* Get the authentication payload */
4648 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4650 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4651 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4655 /* Verify the authentication data */
4656 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4657 admin->auth_data, admin->auth_data_len,
4658 idata->hash, client->id, SILC_ID_CLIENT)) {
4659 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4660 SILC_STATUS_ERR_AUTH_FAILED);
4664 /* Client is now router operator */
4665 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4667 /* Send UMODE change to primary router */
4668 if (!server->standalone)
4669 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4670 client->id, client->mode);
4672 /* Send reply to the sender */
4673 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4677 silc_server_command_free(cmd);
4680 /* Server side command of CONNECT. Connects us to the specified remote
4681 server or router. */
4683 SILC_SERVER_CMD_FUNC(connect)
4685 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4686 SilcServer server = cmd->server;
4687 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4688 unsigned char *tmp, *host;
4690 uint32 port = SILC_PORT;
4692 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CONNECT, cmd, 1, 2);
4694 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4697 /* Check whether client has the permissions. */
4698 if (client->mode == SILC_UMODE_NONE) {
4699 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4700 SILC_STATUS_ERR_NO_SERVER_PRIV);
4704 if (server->server_type == SILC_ROUTER &&
4705 client->mode & SILC_UMODE_SERVER_OPERATOR) {
4706 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4707 SILC_STATUS_ERR_NO_ROUTER_PRIV);
4711 /* Get the remote server */
4712 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4714 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4715 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4720 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4722 SILC_GET32_MSB(port, tmp);
4724 /* Create the connection. It is done with timeout and is async. */
4725 silc_server_create_connection(server, host, port);
4727 /* Send reply to the sender */
4728 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4732 silc_server_command_free(cmd);
4735 /* Server side of command BAN. This is used to manage the ban list of the
4736 channel. To add clients and remove clients from the ban list. */
4738 SILC_SERVER_CMD_FUNC(ban)
4740 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4741 SilcServer server = cmd->server;
4742 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4744 SilcChannelEntry channel;
4745 SilcChannelClientEntry chl;
4746 SilcChannelID *channel_id = NULL;
4747 unsigned char *id, *add, *del;
4748 uint32 id_len, tmp_len;
4749 uint16 ident = silc_command_get_ident(cmd->payload);
4751 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4754 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4756 /* Get Channel ID */
4757 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4759 channel_id = silc_id_payload_parse_id(id, id_len);
4761 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4762 SILC_STATUS_ERR_NO_CHANNEL_ID);
4767 /* Get channel entry. The server must know about the channel since the
4768 client is expected to be on the channel. */
4769 channel = silc_idlist_find_channel_by_id(server->local_list,
4772 channel = silc_idlist_find_channel_by_id(server->global_list,
4775 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4776 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4781 /* Check whether this client is on the channel */
4782 if (!silc_server_client_on_channel(client, channel)) {
4783 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4784 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4788 /* Get entry to the channel user list */
4789 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4791 /* The client must be at least channel operator. */
4792 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4793 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4794 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4798 /* Get the new ban and add it to the ban list */
4799 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4801 if (!channel->ban_list)
4802 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4804 channel->ban_list = silc_realloc(channel->ban_list,
4805 sizeof(*channel->ban_list) *
4807 strlen(channel->ban_list) + 2));
4808 if (add[tmp_len - 1] == ',')
4809 add[tmp_len - 1] = '\0';
4811 strncat(channel->ban_list, add, tmp_len);
4812 strncat(channel->ban_list, ",", 1);
4815 /* Get the ban to be removed and remove it from the list */
4816 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4817 if (del && channel->ban_list) {
4818 char *start, *end, *n;
4820 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4821 silc_free(channel->ban_list);
4822 channel->ban_list = NULL;
4824 start = strstr(channel->ban_list, del);
4825 if (start && strlen(start) >= tmp_len) {
4826 end = start + tmp_len;
4827 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4828 strncat(n, channel->ban_list, start - channel->ban_list);
4829 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4831 silc_free(channel->ban_list);
4832 channel->ban_list = n;
4837 /* Send the BAN notify type to our primary router. */
4838 if (!server->standalone && (add || del))
4839 silc_server_send_notify_ban(server, server->router->connection,
4840 server->server_type == SILC_ROUTER ?
4841 TRUE : FALSE, channel, add, del);
4843 /* Send the reply back to the client */
4845 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4846 SILC_STATUS_OK, ident, 2,
4848 3, channel->ban_list,
4850 strlen(channel->ban_list) - 1 : 0);
4851 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4852 packet->data, packet->len, FALSE);
4854 silc_buffer_free(packet);
4857 silc_free(channel_id);
4858 silc_server_command_free(cmd);
4861 /* Server side command of CLOSE. Closes connection to a specified server. */
4863 SILC_SERVER_CMD_FUNC(close)
4865 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4866 SilcServer server = cmd->server;
4867 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4868 SilcServerEntry server_entry;
4869 SilcSocketConnection sock;
4872 unsigned char *name;
4873 uint32 port = SILC_PORT;
4875 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CLOSE, cmd, 1, 2);
4877 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4880 /* Check whether client has the permissions. */
4881 if (client->mode == SILC_UMODE_NONE) {
4882 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4883 SILC_STATUS_ERR_NO_SERVER_PRIV);
4887 /* Get the remote server */
4888 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4890 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4891 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4896 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4898 SILC_GET32_MSB(port, tmp);
4900 server_entry = silc_idlist_find_server_by_conn(server->local_list,
4901 name, port, FALSE, NULL);
4903 server_entry = silc_idlist_find_server_by_conn(server->global_list,
4904 name, port, FALSE, NULL);
4905 if (!server_entry) {
4906 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4907 SILC_STATUS_ERR_NO_SERVER_ID);
4911 /* Send reply to the sender */
4912 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4915 /* Close the connection to the server */
4916 sock = (SilcSocketConnection)server_entry->connection;
4918 /* If we shutdown primary router connection manually then don't trigger
4919 any reconnect or backup router connections, by setting the router
4921 if (server->router == server_entry) {
4922 server->id_entry->router = NULL;
4923 server->router = NULL;
4924 server->standalone = TRUE;
4926 silc_server_free_sock_user_data(server, sock, NULL);
4927 silc_server_close_connection(server, sock);
4930 silc_server_command_free(cmd);
4933 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4934 active connections. */
4936 SILC_SERVER_CMD_FUNC(shutdown)
4938 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4939 SilcServer server = cmd->server;
4940 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4942 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4944 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4947 /* Check whether client has the permission. */
4948 if (client->mode == SILC_UMODE_NONE) {
4949 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4950 SILC_STATUS_ERR_NO_SERVER_PRIV);
4954 /* Send reply to the sender */
4955 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4958 /* Then, gracefully, or not, bring the server down. */
4959 silc_server_stop(server);
4963 silc_server_command_free(cmd);
4966 /* Server side command of LEAVE. Removes client from a channel. */
4968 SILC_SERVER_CMD_FUNC(leave)
4970 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4971 SilcServer server = cmd->server;
4972 SilcSocketConnection sock = cmd->sock;
4973 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4974 SilcChannelID *id = NULL;
4975 SilcChannelEntry channel;
4979 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4981 /* Get Channel ID */
4982 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4984 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4985 SILC_STATUS_ERR_NO_CHANNEL_ID);
4988 id = silc_id_payload_parse_id(tmp, len);
4990 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4991 SILC_STATUS_ERR_NO_CHANNEL_ID);
4995 /* Get channel entry */
4996 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4998 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5000 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5001 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5006 /* Check whether this client is on the channel */
5007 if (!silc_server_client_on_channel(id_entry, channel)) {
5008 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5009 SILC_STATUS_ERR_NOT_ON_CHANNEL);
5013 /* Notify routers that they should remove this client from their list
5014 of clients on the channel. Send LEAVE notify type. */
5015 if (!server->standalone)
5016 silc_server_send_notify_leave(server, server->router->connection,
5017 server->server_type == SILC_ROUTER ?
5018 TRUE : FALSE, channel, id_entry->id);
5020 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5023 /* Remove client from channel */
5024 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5026 /* If the channel does not exist anymore we won't send anything */
5029 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5030 /* Re-generate channel key */
5031 if (!silc_server_create_channel_key(server, channel, 0))
5034 /* Send the channel key */
5035 silc_server_send_channel_key(server, NULL, channel,
5036 server->server_type == SILC_ROUTER ?
5037 FALSE : !server->standalone);
5042 silc_server_command_free(cmd);
5045 /* Server side of command USERS. Resolves clients and their USERS currently
5046 joined on the requested channel. The list of Client ID's and their modes
5047 on the channel is sent back. */
5049 SILC_SERVER_CMD_FUNC(users)
5051 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5052 SilcServer server = cmd->server;
5053 SilcChannelEntry channel;
5054 SilcChannelID *id = NULL;
5055 SilcBuffer packet, idp;
5056 unsigned char *channel_id;
5057 uint32 channel_id_len;
5058 SilcBuffer client_id_list;
5059 SilcBuffer client_mode_list;
5060 unsigned char lc[4];
5061 uint32 list_count = 0;
5062 uint16 ident = silc_command_get_ident(cmd->payload);
5065 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5067 /* Get Channel ID */
5068 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5070 /* Get channel name */
5071 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5073 if (!channel_id && !channel_name) {
5074 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5075 SILC_STATUS_ERR_NO_CHANNEL_ID);
5080 id = silc_id_payload_parse_id(channel_id, channel_id_len);
5082 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5083 SILC_STATUS_ERR_NO_CHANNEL_ID);
5088 /* If we are server and we don't know about this channel we will send
5089 the command to our router. If we know about the channel then we also
5090 have the list of users already. */
5092 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5094 channel = silc_idlist_find_channel_by_name(server->local_list,
5095 channel_name, NULL);
5097 if (!channel || channel->disabled) {
5098 if (server->server_type != SILC_ROUTER && !server->standalone &&
5102 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5103 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5105 /* Send USERS command */
5106 silc_server_packet_send(server, server->router->connection,
5107 SILC_PACKET_COMMAND, cmd->packet->flags,
5108 tmpbuf->data, tmpbuf->len, TRUE);
5110 /* Reprocess this packet after received reply */
5111 silc_server_command_pending(server, SILC_COMMAND_USERS,
5112 silc_command_get_ident(cmd->payload),
5113 silc_server_command_users,
5114 silc_server_command_dup(cmd));
5115 cmd->pending = TRUE;
5116 silc_command_set_ident(cmd->payload, ident);
5117 silc_buffer_free(tmpbuf);
5122 /* Check the global list as well. */
5124 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5126 channel = silc_idlist_find_channel_by_name(server->global_list,
5127 channel_name, NULL);
5129 /* Channel really does not exist */
5130 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5131 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5136 /* If the channel is private or secret do not send anything, unless the
5137 user requesting this command is on the channel. */
5138 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5139 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5140 && !silc_server_client_on_channel(cmd->sock->user_data, channel)) {
5141 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5142 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5147 (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
5148 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5149 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5154 /* Get the users list */
5155 silc_server_get_users_on_channel(server, channel, &client_id_list,
5156 &client_mode_list, &list_count);
5159 SILC_PUT32_MSB(list_count, lc);
5162 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5163 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5164 SILC_STATUS_OK, ident, 4,
5165 2, idp->data, idp->len,
5167 4, client_id_list->data,
5168 client_id_list->len,
5169 5, client_mode_list->data,
5170 client_mode_list->len);
5171 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5172 packet->data, packet->len, FALSE);
5174 silc_buffer_free(idp);
5175 silc_buffer_free(packet);
5176 silc_buffer_free(client_id_list);
5177 silc_buffer_free(client_mode_list);
5181 silc_server_command_free(cmd);
5184 /* Server side of command GETKEY. This fetches the client's public key
5185 from the server where to the client is connected. */
5187 SILC_SERVER_CMD_FUNC(getkey)
5189 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5190 SilcServer server = cmd->server;
5192 SilcClientEntry client;
5193 SilcServerEntry server_entry;
5194 SilcClientID *client_id = NULL;
5195 SilcServerID *server_id = NULL;
5196 SilcIDPayload idp = NULL;
5197 uint16 ident = silc_command_get_ident(cmd->payload);
5198 unsigned char *tmp, *pkdata;
5199 uint32 tmp_len, pklen;
5200 SilcBuffer pk = NULL;
5203 SILC_LOG_DEBUG(("Start"));
5205 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5207 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5208 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5211 idp = silc_id_payload_parse(tmp, tmp_len);
5213 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5214 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5218 id_type = silc_id_payload_get_type(idp);
5219 if (id_type == SILC_ID_CLIENT) {
5220 client_id = silc_id_payload_get_id(idp);
5222 /* If the client is not found from local list there is no chance it
5223 would be locally connected client so send the command further. */
5224 client = silc_idlist_find_client_by_id(server->local_list,
5225 client_id, TRUE, NULL);
5227 client = silc_idlist_find_client_by_id(server->global_list,
5228 client_id, TRUE, NULL);
5230 if ((!client && !cmd->pending && !server->standalone) ||
5231 (client && !client->connection && !cmd->pending) ||
5232 (client && !client->data.public_key && !cmd->pending)) {
5235 SilcSocketConnection dest_sock;
5237 dest_sock = silc_server_get_client_route(server, NULL, 0,
5242 old_ident = silc_command_get_ident(cmd->payload);
5243 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5244 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5246 silc_server_packet_send(server, dest_sock,
5247 SILC_PACKET_COMMAND, cmd->packet->flags,
5248 tmpbuf->data, tmpbuf->len, TRUE);
5250 /* Reprocess this packet after received reply from router */
5251 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5252 silc_command_get_ident(cmd->payload),
5253 silc_server_command_getkey,
5254 silc_server_command_dup(cmd));
5255 cmd->pending = TRUE;
5256 silc_command_set_ident(cmd->payload, old_ident);
5257 silc_buffer_free(tmpbuf);
5262 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5263 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5267 /* The client is locally connected, just get the public key and
5268 send it back. If they key does not exist then do not send it,
5269 send just OK reply */
5270 if (!client->data.public_key) {
5274 tmp = silc_pkcs_public_key_encode(client->data.public_key, &tmp_len);
5275 pk = silc_buffer_alloc(4 + tmp_len);
5276 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5277 silc_buffer_format(pk,
5278 SILC_STR_UI_SHORT(tmp_len),
5279 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5280 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5286 } else if (id_type == SILC_ID_SERVER) {
5287 server_id = silc_id_payload_get_id(idp);
5289 /* If the server is not found from local list there is no chance it
5290 would be locally connected server so send the command further. */
5291 server_entry = silc_idlist_find_server_by_id(server->local_list,
5292 server_id, TRUE, NULL);
5294 server_entry = silc_idlist_find_server_by_id(server->global_list,
5295 server_id, TRUE, NULL);
5297 if (server_entry != server->id_entry &&
5298 ((!server_entry && !cmd->pending && !server->standalone) ||
5299 (server_entry && !server_entry->connection && !cmd->pending &&
5300 !server->standalone) ||
5301 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5302 !server->standalone))) {
5306 old_ident = silc_command_get_ident(cmd->payload);
5307 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5308 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5310 silc_server_packet_send(server, server->router->connection,
5311 SILC_PACKET_COMMAND, cmd->packet->flags,
5312 tmpbuf->data, tmpbuf->len, TRUE);
5314 /* Reprocess this packet after received reply from router */
5315 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5316 silc_command_get_ident(cmd->payload),
5317 silc_server_command_getkey,
5318 silc_server_command_dup(cmd));
5319 cmd->pending = TRUE;
5321 silc_command_set_ident(cmd->payload, old_ident);
5322 silc_buffer_free(tmpbuf);
5326 if (!server_entry) {
5327 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5328 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5332 /* If they key does not exist then do not send it, send just OK reply */
5333 if (!server_entry->data.public_key) {
5337 tmp = silc_pkcs_public_key_encode(server_entry->data.public_key,
5339 pk = silc_buffer_alloc(4 + tmp_len);
5340 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5341 silc_buffer_format(pk,
5342 SILC_STR_UI_SHORT(tmp_len),
5343 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5344 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5354 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5355 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5356 SILC_STATUS_OK, ident,
5360 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5361 packet->data, packet->len, FALSE);
5362 silc_buffer_free(packet);
5365 silc_buffer_free(pk);
5369 silc_id_payload_free(idp);
5370 silc_free(client_id);
5371 silc_free(server_id);
5372 silc_server_command_free(cmd);