5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2001 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
22 #include "serverincludes.h"
23 #include "server_internal.h"
25 static int silc_server_is_registered(SilcServer server,
26 SilcSocketConnection sock,
27 SilcServerCommandContext cmd,
30 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
32 SilcCommandStatus status);
34 silc_server_command_send_status_data(SilcServerCommandContext cmd,
36 SilcCommandStatus status,
41 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
42 SilcServerCommandReplyContext cmdr,
44 SILC_TASK_CALLBACK(silc_server_command_process_timeout);
46 /* Server command list. */
47 SilcServerCommand silc_command_list[] =
49 SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
50 SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
51 SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
52 SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
53 SILC_SERVER_CMD(list, LIST, SILC_CF_LAG_STRICT | SILC_CF_REG),
54 SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
55 SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
56 SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
57 SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG_STRICT | SILC_CF_REG | SILC_CF_OPER),
58 SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
59 SILC_SERVER_CMD(connect, CONNECT,
60 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
61 SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
62 SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
63 SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG_STRICT | SILC_CF_REG),
64 SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
65 SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
66 SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG_STRICT | SILC_CF_REG),
67 SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
68 SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
69 SILC_SERVER_CMD(ban, BAN, SILC_CF_LAG_STRICT | SILC_CF_REG),
70 SILC_SERVER_CMD(close, CLOSE,
71 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
72 SILC_SERVER_CMD(shutdown, SHUTDOWN, SILC_CF_LAG | SILC_CF_REG |
74 SILC_SERVER_CMD(silcoper, SILCOPER,
75 SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
76 SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
77 SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
78 SILC_SERVER_CMD(getkey, GETKEY, SILC_CF_LAG | SILC_CF_REG),
83 /* Performs several checks to the command. It first checks whether this
84 command was called as pending command callback. If it was then it checks
85 whether error occurred in the command reply where the pending command
88 It also checks that the requested command includes correct amount
90 #define SILC_SERVER_COMMAND_CHECK(command, context, min, max) \
94 SILC_LOG_DEBUG(("Start")); \
96 if (silc_server_command_pending_error_check(cmd, context2, command)) { \
97 silc_server_command_free(cmd); \
101 _argc = silc_argument_get_arg_num(cmd->args); \
103 silc_server_command_send_status_reply(cmd, command, \
104 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
105 silc_server_command_free(cmd); \
109 silc_server_command_send_status_reply(cmd, command, \
110 SILC_STATUS_ERR_TOO_MANY_PARAMS); \
111 silc_server_command_free(cmd); \
116 /* Returns TRUE if the connection is registered. Unregistered connections
117 usually cannot send commands hence the check. */
119 static int silc_server_is_registered(SilcServer server,
120 SilcSocketConnection sock,
121 SilcServerCommandContext cmd,
124 SilcIDListData idata = (SilcIDListData)sock->user_data;
129 if (idata->status & SILC_IDLIST_STATUS_REGISTERED)
132 silc_server_command_send_status_reply(cmd, command,
133 SILC_STATUS_ERR_NOT_REGISTERED);
134 silc_server_command_free(cmd);
138 /* Internal context to hold data when executed command with timeout. */
140 SilcServerCommandContext ctx;
141 SilcServerCommand *cmd;
142 } *SilcServerCommandTimeout;
144 /* Timeout callback to process commands with timeout for client. Client's
145 commands are always executed with timeout. */
147 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
149 SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
150 SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data;
152 /* Update access time */
153 client->last_command = time(NULL);
155 if (!(timeout->cmd->flags & SILC_CF_REG))
156 timeout->cmd->cb(timeout->ctx, NULL);
157 else if (silc_server_is_registered(timeout->ctx->server,
161 timeout->cmd->cb(timeout->ctx, NULL);
166 /* Processes received command packet. */
168 void silc_server_command_process(SilcServer server,
169 SilcSocketConnection sock,
170 SilcPacketContext *packet)
172 SilcServerCommandContext ctx;
173 SilcServerCommand *cmd;
176 /* Allocate command context. This must be free'd by the
177 command routine receiving it. */
178 ctx = silc_server_command_alloc();
179 ctx->server = server;
180 ctx->sock = silc_socket_dup(sock);
181 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
183 /* Parse the command payload in the packet */
184 ctx->payload = silc_command_payload_parse(packet->buffer->data,
185 packet->buffer->len);
187 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
188 silc_buffer_free(packet->buffer);
189 silc_packet_context_free(packet);
190 silc_socket_free(ctx->sock);
194 ctx->args = silc_command_get_args(ctx->payload);
196 /* Get the command */
197 command = silc_command_get(ctx->payload);
198 for (cmd = silc_command_list; cmd->cb; cmd++)
199 if (cmd->cmd == command)
203 silc_server_command_send_status_reply(ctx, command,
204 SILC_STATUS_ERR_UNKNOWN_COMMAND);
205 silc_server_command_free(ctx);
209 /* Execute client's commands always with timeout. Normally they are
210 executed with zero (0) timeout but if client is sending command more
211 frequently than once in 2 seconds, then the timeout may be 0 to 2
213 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
214 SilcClientEntry client = (SilcClientEntry)sock->user_data;
215 SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
221 if (client->last_command && (time(NULL) - client->last_command) < 2) {
222 client->fast_command++;
225 client->fast_command = ((client->fast_command - 1) <= 0 ? 0 :
226 client->fast_command--);
230 if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
231 (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
232 silc_schedule_task_add(server->schedule, sock->sock,
233 silc_server_command_process_timeout,
235 2 - (time(NULL) - client->last_command), 0,
237 SILC_TASK_PRI_NORMAL);
239 silc_schedule_task_add(server->schedule, sock->sock,
240 silc_server_command_process_timeout,
244 SILC_TASK_PRI_NORMAL);
248 /* Execute for server */
250 if (!(cmd->flags & SILC_CF_REG))
252 else if (silc_server_is_registered(server, sock, ctx, cmd->cmd))
256 /* Allocate Command Context */
258 SilcServerCommandContext silc_server_command_alloc()
260 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
265 /* Free's the command context allocated before executing the command */
267 void silc_server_command_free(SilcServerCommandContext ctx)
270 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
272 if (ctx->users < 1) {
274 silc_command_payload_free(ctx->payload);
276 silc_packet_context_free(ctx->packet);
278 silc_socket_free(ctx->sock); /* Decrease reference counter */
283 /* Duplicate Command Context by adding reference counter. The context won't
284 be free'd untill it hits zero. */
286 SilcServerCommandContext
287 silc_server_command_dup(SilcServerCommandContext ctx)
290 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
295 /* Add new pending command to be executed when reply to a command has been
296 received. The `reply_cmd' is the command that will call the `callback'
297 with `context' when reply has been received. It can be SILC_COMMAND_NONE
298 to match any command with the `ident'. If `ident' is non-zero
299 the `callback' will be executed when received reply with command
300 identifier `ident'. */
302 void silc_server_command_pending(SilcServer server,
303 SilcCommand reply_cmd,
305 SilcServerPendingDestructor destructor,
306 SilcCommandCb callback,
309 SilcServerCommandPending *reply;
311 reply = silc_calloc(1, sizeof(*reply));
312 reply->reply_cmd = reply_cmd;
313 reply->ident = ident;
314 reply->context = context;
315 reply->callback = callback;
316 reply->destructor = destructor;
317 silc_dlist_add(server->pending_commands, reply);
320 /* Deletes pending command by reply command type. */
322 void silc_server_command_pending_del(SilcServer server,
323 SilcCommand reply_cmd,
326 SilcServerCommandPending *r;
328 silc_dlist_start(server->pending_commands);
329 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
330 if (r->reply_cmd == reply_cmd && r->ident == ident) {
331 silc_dlist_del(server->pending_commands, r);
337 /* Checks for pending commands and marks callbacks to be called from
338 the command reply function. Returns TRUE if there were pending command. */
340 SilcServerCommandPendingCallbacks
341 silc_server_command_pending_check(SilcServer server,
342 SilcServerCommandReplyContext ctx,
345 uint32 *callbacks_count)
347 SilcServerCommandPending *r;
348 SilcServerCommandPendingCallbacks callbacks = NULL;
351 silc_dlist_start(server->pending_commands);
352 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
353 if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE)
354 && r->ident == ident) {
355 callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
356 callbacks[i].context = r->context;
357 callbacks[i].callback = r->callback;
358 callbacks[i].destructor = r->destructor;
364 *callbacks_count = i;
368 /* Destructor function for pending callbacks. This is called when using
369 pending commands to free the context given for the pending command. */
371 static void silc_server_command_destructor(void *context)
373 silc_server_command_free((SilcServerCommandContext)context);
376 /* Sends simple status message as command reply packet */
379 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
381 SilcCommandStatus status)
385 SILC_LOG_DEBUG(("Sending command status %d", status));
388 silc_command_reply_payload_encode_va(command, status,
389 silc_command_get_ident(cmd->payload),
391 silc_server_packet_send(cmd->server, cmd->sock,
392 SILC_PACKET_COMMAND_REPLY, 0,
393 buffer->data, buffer->len, FALSE);
394 silc_buffer_free(buffer);
397 /* Sends command status reply with one extra argument. The argument
398 type must be sent as argument. */
401 silc_server_command_send_status_data(SilcServerCommandContext cmd,
403 SilcCommandStatus status,
410 SILC_LOG_DEBUG(("Sending command status %d", status));
413 silc_command_reply_payload_encode_va(command, status,
414 silc_command_get_ident(cmd->payload),
415 1, arg_type, arg, arg_len);
416 silc_server_packet_send(cmd->server, cmd->sock,
417 SILC_PACKET_COMMAND_REPLY, 0,
418 buffer->data, buffer->len, FALSE);
419 silc_buffer_free(buffer);
422 /* This function can be called to check whether in the command reply
423 an error occurred. This function has no effect if this is called
424 when the command function was not called as pending command callback.
425 This returns TRUE if error had occurred. */
428 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
429 SilcServerCommandReplyContext cmdr,
432 SilcCommandStatus status;
434 if (!cmd->pending || !cmdr)
437 SILC_GET16_MSB(status, silc_argument_get_arg_type(cmdr->args, 1, NULL));
438 if (status != SILC_STATUS_OK &&
439 status != SILC_STATUS_LIST_START &&
440 status != SILC_STATUS_LIST_ITEM &&
441 status != SILC_STATUS_LIST_END) {
442 /* Send the error message */
443 silc_server_command_send_status_reply(cmd, command, status);
450 /******************************************************************************
454 ******************************************************************************/
457 silc_server_command_whois_parse(SilcServerCommandContext cmd,
458 SilcClientID ***client_id,
459 uint32 *client_id_count,
467 uint32 argc = silc_argument_get_arg_num(cmd->args);
470 /* If client ID is in the command it must be used instead of nickname */
471 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
473 /* No ID, get the nickname@server string and parse it. */
474 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
476 silc_parse_userfqdn(tmp, nickname, server_name);
478 silc_server_command_send_status_reply(cmd, command,
479 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
483 /* Command includes ID, we must use that. Also check whether the command
484 has more than one ID set - take them all. */
486 *client_id = silc_calloc(1, sizeof(**client_id));
487 (*client_id)[0] = silc_id_payload_parse_id(tmp, len);
488 if ((*client_id)[0] == NULL) {
489 silc_free(*client_id);
492 *client_id_count = 1;
494 /* Take all ID's from the command packet */
496 for (k = 1, i = 1; i < argc; i++) {
497 tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
499 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
500 (*client_id_count + 1));
501 (*client_id)[k] = silc_id_payload_parse_id(tmp, len);
502 if ((*client_id)[k] == NULL) {
503 /* Cleanup all and fail */
504 for (i = 0; i < *client_id_count; i++)
505 silc_free((*client_id)[i]);
506 silc_free(*client_id);
509 (*client_id_count)++;
516 /* Get the max count of reply messages allowed */
517 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
526 /* Resolve context used by both WHOIS and IDENTIFY commands */
528 SilcServerEntry router;
530 unsigned char **res_argv;
531 uint32 *res_argv_lens;
532 uint32 *res_argv_types;
534 } *SilcServerResolveContext;
537 silc_server_command_whois_check(SilcServerCommandContext cmd,
538 SilcClientEntry *clients,
539 uint32 clients_count)
541 SilcServer server = cmd->server;
542 SilcClientEntry entry;
543 SilcServerResolveContext resolve = NULL, r = NULL;
544 uint32 resolve_count = 0;
548 for (i = 0; i < clients_count; i++) {
553 if ((entry->nickname && entry->username && entry->userinfo) ||
554 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
558 /* If we are normal server, and we've not resolved this client from
559 router and it is global client, we'll check whether it is on some
560 channel. If not then we cannot be sure about its validity, and
561 we'll resolve it from router. */
562 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
563 entry->connection || silc_hash_table_count(entry->channels))
567 /* We need to resolve this entry since it is not complete */
569 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
570 /* The entry is being resolved (and we are not the resolver) so attach
571 to the command reply and we're done with this one. */
572 silc_server_command_pending(server, SILC_COMMAND_NONE,
573 entry->resolve_cmd_ident,
574 silc_server_command_destructor,
575 silc_server_command_whois,
576 silc_server_command_dup(cmd));
579 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
580 /* We've resolved this and it still is not ready. We'll return
581 and are that this will be handled again after it is resolved. */
582 for (i = 0; i < resolve_count; i++) {
583 for (k = 0; k < r->res_argc; k++)
584 silc_free(r->res_argv[k]);
585 silc_free(r->res_argv);
586 silc_free(r->res_argv_lens);
587 silc_free(r->res_argv_types);
592 /* We'll resolve this client */
596 for (k = 0; k < resolve_count; k++) {
597 if (resolve[k].router == entry->router) {
604 resolve = silc_realloc(resolve, sizeof(*resolve) *
605 (resolve_count + 1));
606 r = &resolve[resolve_count];
607 memset(r, 0, sizeof(*r));
608 r->router = entry->router;
609 r->ident = ++server->cmd_ident;
613 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
615 r->res_argv_lens = silc_realloc(r->res_argv_lens,
616 sizeof(*r->res_argv_lens) *
618 r->res_argv_types = silc_realloc(r->res_argv_types,
619 sizeof(*r->res_argv_types) *
621 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
622 r->res_argv[r->res_argc] = silc_calloc(idp->len,
623 sizeof(**r->res_argv));
624 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
625 r->res_argv_lens[r->res_argc] = idp->len;
626 r->res_argv_types[r->res_argc] = r->res_argc + 3;
628 silc_buffer_free(idp);
630 entry->resolve_cmd_ident = r->ident;
631 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
632 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
637 /* Do the resolving */
638 for (i = 0; i < resolve_count; i++) {
643 /* Send WHOIS request. We send WHOIS since we're doing the requesting
644 now anyway so make it a good one. */
645 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
646 r->res_argc, r->res_argv,
650 silc_server_packet_send(server, r->router->connection,
651 SILC_PACKET_COMMAND, cmd->packet->flags,
652 res_cmd->data, res_cmd->len, FALSE);
654 /* Reprocess this packet after received reply */
655 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
657 silc_server_command_destructor,
658 silc_server_command_whois,
659 silc_server_command_dup(cmd));
662 silc_buffer_free(res_cmd);
663 for (k = 0; k < r->res_argc; k++)
664 silc_free(r->res_argv[k]);
665 silc_free(r->res_argv);
666 silc_free(r->res_argv_lens);
667 silc_free(r->res_argv_types);
676 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
677 SilcClientEntry *clients,
678 uint32 clients_count,
681 SilcServer server = cmd->server;
684 SilcBuffer packet, idp, channels;
685 SilcClientEntry entry;
686 SilcCommandStatus status;
687 uint16 ident = silc_command_get_ident(cmd->payload);
688 char nh[256], uh[256];
689 unsigned char idle[4], mode[4];
690 unsigned char *fingerprint;
691 SilcSocketConnection hsock;
694 for (i = 0; i < clients_count; i++)
695 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
698 if (len == 0 && clients_count) {
700 if (entry->nickname) {
701 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
702 SILC_STATUS_ERR_NO_SUCH_NICK,
704 strlen(entry->nickname));
706 SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
707 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
708 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
709 2, idp->data, idp->len);
710 silc_buffer_free(idp);
716 status = SILC_STATUS_OK;
718 status = SILC_STATUS_LIST_START;
720 for (i = 0, k = 0; i < clients_count; i++) {
723 if (!(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
724 if (clients_count == 1) {
725 if (entry->nickname) {
726 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
727 SILC_STATUS_ERR_NO_SUCH_NICK,
729 strlen(entry->nickname));
731 SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
732 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
733 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
734 2, idp->data, idp->len);
735 silc_buffer_free(idp);
742 status = SILC_STATUS_LIST_ITEM;
744 if (clients_count > 1 && k == clients_count - 1)
745 status = SILC_STATUS_LIST_END;
747 if (count && k - 1 == count)
748 status = SILC_STATUS_LIST_END;
750 if (count && k - 1 > count)
753 /* Sanity check, however these should never fail. However, as
754 this sanity check has been added here they have failed. */
755 if (!entry->nickname || !entry->username || !entry->userinfo)
758 /* Send WHOIS reply */
759 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
760 tmp = silc_argument_get_first_arg(cmd->args, NULL);
762 memset(uh, 0, sizeof(uh));
763 memset(nh, 0, sizeof(nh));
764 memset(idle, 0, sizeof(idle));
766 strncat(nh, entry->nickname, strlen(entry->nickname));
767 if (!strchr(entry->nickname, '@')) {
769 if (entry->servername) {
770 strncat(nh, entry->servername, strlen(entry->servername));
772 len = entry->router ? strlen(entry->router->server_name) :
773 strlen(server->server_name);
774 strncat(nh, entry->router ? entry->router->server_name :
775 server->server_name, len);
779 strncat(uh, entry->username, strlen(entry->username));
780 if (!strchr(entry->username, '@')) {
782 hsock = (SilcSocketConnection)entry->connection;
783 len = strlen(hsock->hostname);
784 strncat(uh, hsock->hostname, len);
787 channels = silc_server_get_client_channel_list(server, entry);
789 if (entry->data.fingerprint[0] != 0 && entry->data.fingerprint[1] != 0)
790 fingerprint = entry->data.fingerprint;
794 SILC_PUT32_MSB(entry->mode, mode);
796 if (entry->connection) {
797 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
801 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
803 2, idp->data, idp->len,
807 strlen(entry->userinfo),
808 6, channels ? channels->data : NULL,
809 channels ? channels->len : 0,
813 fingerprint ? 20 : 0);
815 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
816 0, packet->data, packet->len, FALSE);
818 silc_buffer_free(packet);
819 silc_buffer_free(idp);
821 silc_buffer_free(channels);
828 silc_server_command_whois_process(SilcServerCommandContext cmd)
830 SilcServer server = cmd->server;
831 char *nick = NULL, *server_name = NULL;
833 SilcClientEntry *clients = NULL, entry;
834 SilcClientID **client_id = NULL;
835 uint32 client_id_count = 0, clients_count = 0;
837 bool check_global = FALSE;
839 /* Parse the whois request */
840 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
841 &nick, &server_name, &count,
845 /* Send the WHOIS request to the router only if it included nickname.
846 Since nicknames can be expanded into many clients we need to send it
847 to router. If the WHOIS included only client ID's we will check them
848 first locally since we just might have them. */
849 if (nick && !client_id_count &&
850 cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
851 server->server_type == SILC_SERVER && !cmd->pending &&
852 !server->standalone) {
856 old_ident = silc_command_get_ident(cmd->payload);
857 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
858 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
860 /* Send WHOIS command to our router */
861 silc_server_packet_send(server, (SilcSocketConnection)
862 server->router->connection,
863 SILC_PACKET_COMMAND, cmd->packet->flags,
864 tmpbuf->data, tmpbuf->len, TRUE);
866 /* Reprocess this packet after received reply from router */
867 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
868 silc_command_get_ident(cmd->payload),
869 silc_server_command_destructor,
870 silc_server_command_whois,
871 silc_server_command_dup(cmd));
874 silc_command_set_ident(cmd->payload, old_ident);
876 silc_buffer_free(tmpbuf);
881 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
883 else if (server->server_type != SILC_SERVER)
886 /* Get all clients matching that ID or nickname from local list */
887 if (client_id_count) {
888 /* Check all Client ID's received in the command packet */
889 for (i = 0; i < client_id_count; i++) {
890 entry = silc_idlist_find_client_by_id(server->local_list,
891 client_id[i], TRUE, NULL);
892 if (!entry && check_global)
893 entry = silc_idlist_find_client_by_id(server->global_list,
894 client_id[i], TRUE, NULL);
896 clients = silc_realloc(clients, sizeof(*clients) *
897 (clients_count + 1));
898 clients[clients_count++] = entry;
902 if (!silc_idlist_get_clients_by_hash(server->local_list,
903 nick, server->md5hash,
904 &clients, &clients_count))
905 silc_idlist_get_clients_by_nickname(server->local_list,
907 &clients, &clients_count);
909 if (!silc_idlist_get_clients_by_hash(server->global_list,
910 nick, server->md5hash,
911 &clients, &clients_count))
912 silc_idlist_get_clients_by_nickname(server->global_list,
914 &clients, &clients_count);
919 /* Such client(s) really does not exist in the SILC network. */
920 if (!client_id_count) {
921 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
922 SILC_STATUS_ERR_NO_SUCH_NICK,
923 3, nick, strlen(nick));
925 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
926 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
927 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
928 2, idp->data, idp->len);
929 silc_buffer_free(idp);
934 /* Router always finds the client entry if it exists in the SILC network.
935 However, it might be incomplete entry and does not include all the
936 mandatory fields that WHOIS command reply requires. Check for these and
937 make query from the server who owns the client if some fields are
939 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
944 /* Send the command reply */
945 silc_server_command_whois_send_reply(cmd, clients, clients_count,
949 if (client_id_count) {
950 for (i = 0; i < client_id_count; i++)
951 silc_free(client_id[i]);
952 silc_free(client_id);
956 silc_free(server_name);
961 /* Server side of command WHOIS. Processes user's query and sends found
962 results as command replies back to the client. */
964 SILC_SERVER_CMD_FUNC(whois)
966 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
969 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 3328);
971 ret = silc_server_command_whois_process(cmd);
974 silc_server_command_free(cmd);
977 /******************************************************************************
981 ******************************************************************************/
984 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
992 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
994 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
995 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
999 /* Get the nickname@server string and parse it. */
1000 silc_parse_userfqdn(tmp, nickname, server_name);
1002 /* Get the max count of reply messages allowed */
1003 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1013 silc_server_command_whowas_check(SilcServerCommandContext cmd,
1014 SilcClientEntry *clients,
1015 uint32 clients_count)
1017 SilcServer server = cmd->server;
1019 SilcClientEntry entry;
1021 for (i = 0; i < clients_count; i++) {
1024 if (!entry->nickname || !entry->username) {
1031 old_ident = silc_command_get_ident(cmd->payload);
1032 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1033 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1035 /* Send WHOWAS command */
1036 silc_server_packet_send(server, entry->router->connection,
1037 SILC_PACKET_COMMAND, cmd->packet->flags,
1038 tmpbuf->data, tmpbuf->len, TRUE);
1040 /* Reprocess this packet after received reply */
1041 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1042 silc_command_get_ident(cmd->payload),
1043 silc_server_command_destructor,
1044 silc_server_command_whowas,
1045 silc_server_command_dup(cmd));
1046 cmd->pending = TRUE;
1048 silc_command_set_ident(cmd->payload, old_ident);
1050 silc_buffer_free(tmpbuf);
1059 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1060 SilcClientEntry *clients,
1061 uint32 clients_count)
1063 SilcServer server = cmd->server;
1065 int i, count = 0, len;
1066 SilcBuffer packet, idp;
1067 SilcClientEntry entry = NULL;
1068 SilcCommandStatus status;
1069 uint16 ident = silc_command_get_ident(cmd->payload);
1071 char nh[256], uh[256];
1073 status = SILC_STATUS_OK;
1074 if (clients_count > 1)
1075 status = SILC_STATUS_LIST_START;
1077 for (i = 0; i < clients_count; i++) {
1080 /* We will take only clients that are not valid anymore. They are the
1081 ones that are not registered anymore but still have a ID. They
1082 have disconnected us, and thus valid for WHOWAS. */
1083 if (entry->data.status & SILC_IDLIST_STATUS_REGISTERED)
1085 if (entry->id == NULL)
1088 if (count && i - 1 == count)
1093 if (clients_count > 2)
1094 status = SILC_STATUS_LIST_ITEM;
1096 if (clients_count > 1 && i == clients_count - 1)
1097 status = SILC_STATUS_LIST_END;
1099 /* Sanity check, however these should never fail. However, as
1100 this sanity check has been added here they have failed. */
1101 if (!entry->nickname || !entry->username)
1104 /* Send WHOWAS reply */
1105 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1106 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1108 memset(uh, 0, sizeof(uh));
1109 memset(nh, 0, sizeof(nh));
1111 strncat(nh, entry->nickname, strlen(entry->nickname));
1112 if (!strchr(entry->nickname, '@')) {
1113 strncat(nh, "@", 1);
1114 if (entry->servername) {
1115 strncat(nh, entry->servername, strlen(entry->servername));
1117 len = entry->router ? strlen(entry->router->server_name) :
1118 strlen(server->server_name);
1119 strncat(nh, entry->router ? entry->router->server_name :
1120 server->server_name, len);
1124 strncat(uh, entry->username, strlen(entry->username));
1125 if (!strchr(entry->username, '@')) {
1126 strncat(uh, "@", 1);
1127 strcat(uh, "*private*");
1131 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1133 2, idp->data, idp->len,
1138 strlen(entry->userinfo) : 0);
1139 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1140 0, packet->data, packet->len, FALSE);
1142 silc_buffer_free(packet);
1143 silc_buffer_free(idp);
1146 if (found == FALSE && entry)
1147 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1148 SILC_STATUS_ERR_NO_SUCH_NICK,
1150 strlen(entry->nickname));
1154 silc_server_command_whowas_process(SilcServerCommandContext cmd)
1156 SilcServer server = cmd->server;
1157 char *nick = NULL, *server_name = NULL;
1159 SilcClientEntry *clients = NULL;
1160 uint32 clients_count = 0;
1162 bool check_global = FALSE;
1164 /* Protocol dictates that we must always send the received WHOWAS request
1165 to our router if we are normal server, so let's do it now unless we
1166 are standalone. We will not send any replies to the client until we
1167 have received reply from the router. */
1168 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1169 server->server_type == SILC_SERVER && !cmd->pending &&
1170 !server->standalone) {
1174 old_ident = silc_command_get_ident(cmd->payload);
1175 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1176 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1178 /* Send WHOWAS command to our router */
1179 silc_server_packet_send(server, (SilcSocketConnection)
1180 server->router->connection,
1181 SILC_PACKET_COMMAND, cmd->packet->flags,
1182 tmpbuf->data, tmpbuf->len, TRUE);
1184 /* Reprocess this packet after received reply from router */
1185 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1186 silc_command_get_ident(cmd->payload),
1187 silc_server_command_destructor,
1188 silc_server_command_whowas,
1189 silc_server_command_dup(cmd));
1190 cmd->pending = TRUE;
1192 silc_command_set_ident(cmd->payload, old_ident);
1194 silc_buffer_free(tmpbuf);
1199 /* We are ready to process the command request. Let's search for the
1200 requested client and send reply to the requesting client. */
1202 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1203 check_global = TRUE;
1204 else if (server->server_type != SILC_SERVER)
1205 check_global = TRUE;
1207 /* Parse the whowas request */
1208 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1211 /* Get all clients matching that nickname from local list */
1212 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1214 &clients, &clients_count))
1215 silc_idlist_get_clients_by_hash(server->local_list,
1216 nick, server->md5hash,
1217 &clients, &clients_count);
1219 /* Check global list as well */
1221 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1223 &clients, &clients_count))
1224 silc_idlist_get_clients_by_hash(server->global_list,
1225 nick, server->md5hash,
1226 &clients, &clients_count);
1230 /* Such a client really does not exist in the SILC network. */
1231 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1232 SILC_STATUS_ERR_NO_SUCH_NICK,
1233 3, nick, strlen(nick));
1237 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1242 /* Send the command reply to the client */
1243 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1248 silc_free(server_name);
1253 /* Server side of command WHOWAS. */
1255 SILC_SERVER_CMD_FUNC(whowas)
1257 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1260 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1262 ret = silc_server_command_whowas_process(cmd);
1265 silc_server_command_free(cmd);
1268 /******************************************************************************
1272 ******************************************************************************/
1275 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1276 SilcClientEntry **clients,
1277 uint32 *clients_count,
1278 SilcServerEntry **servers,
1279 uint32 *servers_count,
1280 SilcChannelEntry **channels,
1281 uint32 *channels_count,
1285 SilcServer server = cmd->server;
1288 uint32 argc = silc_argument_get_arg_num(cmd->args);
1290 bool check_global = FALSE;
1295 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1296 check_global = TRUE;
1297 else if (server->server_type != SILC_SERVER)
1298 check_global = TRUE;
1300 /* If ID Payload is in the command it must be used instead of names */
1301 tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1303 /* No ID, get the names. */
1306 /* Try to get nickname@server. */
1307 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1310 char *nick_server = NULL;
1312 silc_parse_userfqdn(tmp, &nick, &nick_server);
1314 if (!silc_idlist_get_clients_by_hash(server->local_list,
1315 nick, server->md5hash,
1316 clients, clients_count))
1317 silc_idlist_get_clients_by_nickname(server->local_list,
1319 clients, clients_count);
1321 if (!silc_idlist_get_clients_by_hash(server->global_list,
1322 nick, server->md5hash,
1323 clients, clients_count))
1324 silc_idlist_get_clients_by_nickname(server->global_list,
1326 clients, clients_count);
1330 silc_free(nick_server);
1333 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1334 SILC_STATUS_ERR_NO_SUCH_NICK,
1335 3, tmp, strlen(tmp));
1340 /* Try to get server name */
1341 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1343 entry = silc_idlist_find_server_by_name(server->local_list,
1345 if (!entry && check_global)
1346 entry = silc_idlist_find_server_by_name(server->global_list,
1349 *servers = silc_realloc(*servers, sizeof(**servers) *
1350 (*servers_count + 1));
1351 (*servers)[(*servers_count)++] = entry;
1355 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1356 SILC_STATUS_ERR_NO_SUCH_SERVER,
1357 3, tmp, strlen(tmp));
1362 /* Try to get channel name */
1363 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1365 entry = silc_idlist_find_channel_by_name(server->local_list,
1367 if (!entry && check_global)
1368 entry = silc_idlist_find_channel_by_name(server->global_list,
1371 *channels = silc_realloc(*channels, sizeof(**channels) *
1372 (*channels_count + 1));
1373 (*channels)[(*channels_count)++] = entry;
1377 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1378 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1379 3, tmp, strlen(tmp));
1384 if (!(*clients) && !(*servers) && !(*channels)) {
1385 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1386 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1390 /* Command includes ID, we must use that. Also check whether the command
1391 has more than one ID set - take them all. */
1394 /* Take all ID's from the command packet */
1395 for (i = 0; i < argc; i++) {
1398 tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
1402 idp = silc_id_payload_parse(tmp, len);
1404 silc_free(*clients);
1405 silc_free(*servers);
1406 silc_free(*channels);
1407 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1408 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1412 id = silc_id_payload_get_id(idp);
1414 switch (silc_id_payload_get_type(idp)) {
1416 case SILC_ID_CLIENT:
1417 entry = (void *)silc_idlist_find_client_by_id(server->local_list,
1419 if (!entry && check_global)
1420 entry = (void *)silc_idlist_find_client_by_id(server->global_list,
1423 *clients = silc_realloc(*clients, sizeof(**clients) *
1424 (*clients_count + 1));
1425 (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
1427 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1428 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1435 case SILC_ID_SERVER:
1436 entry = (void *)silc_idlist_find_server_by_id(server->local_list,
1438 if (!entry && check_global)
1439 entry = (void *)silc_idlist_find_server_by_id(server->global_list,
1442 *servers = silc_realloc(*servers, sizeof(**servers) *
1443 (*servers_count + 1));
1444 (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
1446 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1447 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
1453 case SILC_ID_CHANNEL:
1454 entry = (void *)silc_idlist_find_channel_by_id(server->local_list,
1456 if (!entry && check_global)
1457 entry = (void *)silc_idlist_find_channel_by_id(server->global_list,
1460 *channels = silc_realloc(*channels, sizeof(**channels) *
1461 (*channels_count + 1));
1462 (*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
1464 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1465 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
1477 silc_free(*clients);
1478 silc_free(*servers);
1479 silc_free(*channels);
1483 /* Get the max count of reply messages allowed */
1484 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1493 /* Checks that all mandatory fields in client entry are present. If not
1494 then send WHOIS request to the server who owns the client. We use
1495 WHOIS because we want to get as much information as possible at once. */
1498 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1499 SilcClientEntry *clients,
1500 uint32 clients_count)
1502 SilcServer server = cmd->server;
1503 SilcClientEntry entry;
1504 SilcServerResolveContext resolve = NULL, r = NULL;
1505 uint32 resolve_count = 0;
1509 for (i = 0; i < clients_count; i++) {
1514 if (entry->nickname ||
1515 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1519 /* If we are normal server, and we've not resolved this client from
1520 router and it is global client, we'll check whether it is on some
1521 channel. If not then we cannot be sure about its validity, and
1522 we'll resolve it from router. */
1523 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
1524 entry->connection || silc_hash_table_count(entry->channels))
1528 /* We need to resolve this entry since it is not complete */
1530 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1531 /* The entry is being resolved (and we are not the resolver) so attach
1532 to the command reply and we're done with this one. */
1533 silc_server_command_pending(server, SILC_COMMAND_NONE,
1534 entry->resolve_cmd_ident,
1535 silc_server_command_destructor,
1536 silc_server_command_identify,
1537 silc_server_command_dup(cmd));
1540 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1541 /* We've resolved this and it still is not ready. We'll return
1542 and are that this will be handled again after it is resolved. */
1543 for (i = 0; i < resolve_count; i++) {
1544 for (k = 0; k < r->res_argc; k++)
1545 silc_free(r->res_argv[k]);
1546 silc_free(r->res_argv);
1547 silc_free(r->res_argv_lens);
1548 silc_free(r->res_argv_types);
1553 /* We'll resolve this client */
1557 for (k = 0; k < resolve_count; k++) {
1558 if (resolve[k].router == entry->router) {
1565 resolve = silc_realloc(resolve, sizeof(*resolve) *
1566 (resolve_count + 1));
1567 r = &resolve[resolve_count];
1568 memset(r, 0, sizeof(*r));
1569 r->router = entry->router;
1570 r->ident = ++server->cmd_ident;
1574 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1576 r->res_argv_lens = silc_realloc(r->res_argv_lens,
1577 sizeof(*r->res_argv_lens) *
1579 r->res_argv_types = silc_realloc(r->res_argv_types,
1580 sizeof(*r->res_argv_types) *
1582 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1583 r->res_argv[r->res_argc] = silc_calloc(idp->len,
1584 sizeof(**r->res_argv));
1585 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1586 r->res_argv_lens[r->res_argc] = idp->len;
1587 r->res_argv_types[r->res_argc] = r->res_argc + 3;
1589 silc_buffer_free(idp);
1591 entry->resolve_cmd_ident = r->ident;
1592 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1593 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1598 /* Do the resolving */
1599 for (i = 0; i < resolve_count; i++) {
1604 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1605 now anyway so make it a good one. */
1606 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1607 r->res_argc, r->res_argv,
1611 silc_server_packet_send(server, r->router->connection,
1612 SILC_PACKET_COMMAND, cmd->packet->flags,
1613 res_cmd->data, res_cmd->len, FALSE);
1615 /* Reprocess this packet after received reply */
1616 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1618 silc_server_command_destructor,
1619 silc_server_command_identify,
1620 silc_server_command_dup(cmd));
1621 cmd->pending = TRUE;
1623 silc_buffer_free(res_cmd);
1624 for (k = 0; k < r->res_argc; k++)
1625 silc_free(r->res_argv[k]);
1626 silc_free(r->res_argv);
1627 silc_free(r->res_argv_lens);
1628 silc_free(r->res_argv_types);
1637 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1638 SilcClientEntry *clients,
1639 uint32 clients_count,
1640 SilcServerEntry *servers,
1641 uint32 servers_count,
1642 SilcChannelEntry *channels,
1643 uint32 channels_count,
1646 SilcServer server = cmd->server;
1648 SilcBuffer packet, idp;
1649 SilcCommandStatus status;
1650 uint16 ident = silc_command_get_ident(cmd->payload);
1651 char nh[256], uh[256];
1652 SilcSocketConnection hsock;
1654 status = SILC_STATUS_OK;
1657 SilcClientEntry entry;
1660 for (i = 0; i < clients_count; i++)
1661 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1664 if (len == 0 && clients_count) {
1666 if (entry->nickname) {
1667 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1668 SILC_STATUS_ERR_NO_SUCH_NICK,
1670 strlen(entry->nickname));
1672 SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1673 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1674 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1675 2, idp->data, idp->len);
1676 silc_buffer_free(idp);
1683 status = SILC_STATUS_LIST_START;
1685 for (i = 0, k = 0; i < clients_count; i++) {
1688 if (!(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1689 if (clients_count == 1) {
1690 SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1691 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1692 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1693 2, idp->data, idp->len);
1694 silc_buffer_free(idp);
1700 status = SILC_STATUS_LIST_ITEM;
1701 if (clients_count > 1 && k == clients_count - 1
1702 && !servers_count && !channels_count)
1703 status = SILC_STATUS_LIST_END;
1704 if (count && k - 1 == count)
1705 status = SILC_STATUS_LIST_END;
1706 if (count && k - 1 > count)
1709 /* Send IDENTIFY reply */
1710 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1712 memset(uh, 0, sizeof(uh));
1713 memset(nh, 0, sizeof(nh));
1715 strncat(nh, entry->nickname, strlen(entry->nickname));
1716 if (!strchr(entry->nickname, '@')) {
1717 strncat(nh, "@", 1);
1718 if (entry->servername) {
1719 strncat(nh, entry->servername, strlen(entry->servername));
1721 len = entry->router ? strlen(entry->router->server_name) :
1722 strlen(server->server_name);
1723 strncat(nh, entry->router ? entry->router->server_name :
1724 server->server_name, len);
1728 if (!entry->username) {
1729 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1731 2, idp->data, idp->len,
1734 strncat(uh, entry->username, strlen(entry->username));
1735 if (!strchr(entry->username, '@')) {
1736 strncat(uh, "@", 1);
1737 hsock = (SilcSocketConnection)entry->connection;
1738 len = strlen(hsock->hostname);
1739 strncat(uh, hsock->hostname, len);
1742 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1744 2, idp->data, idp->len,
1749 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1750 0, packet->data, packet->len, FALSE);
1752 silc_buffer_free(packet);
1753 silc_buffer_free(idp);
1759 status = (status == SILC_STATUS_LIST_ITEM ?
1760 SILC_STATUS_LIST_ITEM : SILC_STATUS_OK);
1763 SilcServerEntry entry;
1765 if (status == SILC_STATUS_OK && servers_count > 1)
1766 status = SILC_STATUS_LIST_START;
1768 for (i = 0, k = 0; i < servers_count; i++) {
1772 status = SILC_STATUS_LIST_ITEM;
1773 if (servers_count > 1 && k == servers_count - 1 && !channels_count)
1774 status = SILC_STATUS_LIST_END;
1775 if (count && k - 1 == count)
1776 status = SILC_STATUS_LIST_END;
1777 if (count && k - 1 > count)
1780 /* Send IDENTIFY reply */
1781 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1783 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1785 2, idp->data, idp->len,
1786 3, entry->server_name,
1787 entry->server_name ?
1788 strlen(entry->server_name) : 0);
1789 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1790 0, packet->data, packet->len, FALSE);
1792 silc_buffer_free(packet);
1793 silc_buffer_free(idp);
1799 status = (status == SILC_STATUS_LIST_ITEM ?
1800 SILC_STATUS_LIST_ITEM : SILC_STATUS_OK);
1803 SilcChannelEntry entry;
1805 if (status == SILC_STATUS_OK && channels_count > 1)
1806 status = SILC_STATUS_LIST_START;
1808 for (i = 0, k = 0; i < channels_count; i++) {
1809 entry = channels[i];
1812 status = SILC_STATUS_LIST_ITEM;
1813 if (channels_count > 1 && k == channels_count - 1)
1814 status = SILC_STATUS_LIST_END;
1815 if (count && k - 1 == count)
1816 status = SILC_STATUS_LIST_END;
1817 if (count && k - 1 > count)
1820 /* Send IDENTIFY reply */
1821 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1823 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1825 2, idp->data, idp->len,
1826 3, entry->channel_name,
1827 entry->channel_name ?
1828 strlen(entry->channel_name): 0);
1829 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1830 0, packet->data, packet->len, FALSE);
1832 silc_buffer_free(packet);
1833 silc_buffer_free(idp);
1841 silc_server_command_identify_process(SilcServerCommandContext cmd)
1843 SilcServer server = cmd->server;
1846 SilcClientEntry *clients = NULL;
1847 SilcServerEntry *servers = NULL;
1848 SilcChannelEntry *channels = NULL;
1849 uint32 clients_count = 0, servers_count = 0, channels_count = 0;
1852 /* Parse the IDENTIFY request */
1853 if (!silc_server_command_identify_parse(cmd,
1854 &clients, &clients_count,
1855 &servers, &servers_count,
1856 &channels, &channels_count,
1860 /* Send the IDENTIFY request to the router only if it included nickname.
1861 Since nicknames can be expanded into many clients we need to send it
1862 to router. If the IDENTIFY included only client ID's we will check them
1863 first locally since we just might have them. */
1864 if (names && cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1865 server->server_type == SILC_SERVER && !cmd->pending &&
1866 !server->standalone) {
1870 old_ident = silc_command_get_ident(cmd->payload);
1871 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1872 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1874 /* Send IDENTIFY command to our router */
1875 silc_server_packet_send(server, (SilcSocketConnection)
1876 server->router->connection,
1877 SILC_PACKET_COMMAND, cmd->packet->flags,
1878 tmpbuf->data, tmpbuf->len, TRUE);
1880 /* Reprocess this packet after received reply from router */
1881 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1882 silc_command_get_ident(cmd->payload),
1883 silc_server_command_destructor,
1884 silc_server_command_identify,
1885 silc_server_command_dup(cmd));
1886 cmd->pending = TRUE;
1888 silc_command_set_ident(cmd->payload, old_ident);
1890 silc_buffer_free(tmpbuf);
1895 /* Check that all mandatory fields are present and request those data
1896 from the server who owns the client if necessary. */
1897 if (clients && !silc_server_command_identify_check_client(cmd, clients,
1903 /* Send the command reply to the client */
1904 silc_server_command_identify_send_reply(cmd,
1905 clients, clients_count,
1906 servers, servers_count,
1907 channels, channels_count,
1913 silc_free(channels);
1918 SILC_SERVER_CMD_FUNC(identify)
1920 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1923 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1925 ret = silc_server_command_identify_process(cmd);
1928 silc_server_command_free(cmd);
1931 /* Checks string for bad characters and returns TRUE if they are found. */
1933 static int silc_server_command_bad_chars(char *nick)
1937 for (i = 0; i < strlen(nick); i++) {
1938 if (!isascii(nick[i]))
1940 if (nick[i] <= 32) return TRUE;
1941 if (nick[i] == ' ') return TRUE;
1942 if (nick[i] == '*') return TRUE;
1943 if (nick[i] == '?') return TRUE;
1944 if (nick[i] == ',') return TRUE;
1950 /* Server side of command NICK. Sets nickname for user. Setting
1951 nickname causes generation of a new client ID for the client. The
1952 new client ID is sent to the client after changing the nickname. */
1954 SILC_SERVER_CMD_FUNC(nick)
1956 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1957 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1958 SilcServer server = cmd->server;
1959 SilcBuffer packet, nidp, oidp = NULL;
1960 SilcClientID *new_id;
1962 uint16 ident = silc_command_get_ident(cmd->payload);
1965 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1968 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
1970 /* Check nickname */
1971 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1972 if (silc_server_command_bad_chars(nick) == TRUE) {
1973 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1974 SILC_STATUS_ERR_BAD_NICKNAME);
1978 if (strlen(nick) > 128)
1981 /* Check for same nickname */
1982 if (!strcmp(client->nickname, nick)) {
1983 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1987 /* Create new Client ID */
1988 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
1990 cmd->server->md5hash, nick,
1993 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
1996 /* Send notify about nickname change to our router. We send the new
1997 ID and ask to replace it with the old one. If we are router the
1998 packet is broadcasted. Send NICK_CHANGE notify. */
1999 if (!server->standalone)
2000 silc_server_send_notify_nick_change(server, server->router->connection,
2001 server->server_type == SILC_SERVER ?
2002 FALSE : TRUE, client->id,
2005 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2007 /* Remove old cache entry */
2008 silc_idcache_del_by_context(server->local_list->clients, client);
2011 silc_free(client->id);
2013 /* Save the nickname as this client is our local client */
2014 silc_free(client->nickname);
2016 client->nickname = strdup(nick);
2017 client->id = new_id;
2019 /* Update client cache */
2020 silc_idcache_add(server->local_list->clients, client->nickname,
2021 client->id, (void *)client, FALSE);
2023 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2025 /* Send NICK_CHANGE notify to the client's channels */
2026 silc_server_send_notify_on_channels(server, NULL, client,
2027 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
2028 oidp->data, oidp->len,
2029 nidp->data, nidp->len);
2032 /* Send the new Client ID as reply command back to client */
2033 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
2034 SILC_STATUS_OK, ident, 1,
2035 2, nidp->data, nidp->len);
2036 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2037 0, packet->data, packet->len, FALSE);
2039 silc_buffer_free(packet);
2040 silc_buffer_free(nidp);
2042 silc_buffer_free(oidp);
2045 silc_server_command_free(cmd);
2048 /* Sends the LIST command reply */
2051 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2052 SilcChannelEntry *lch,
2054 SilcChannelEntry *gch,
2058 SilcBuffer packet, idp;
2059 SilcChannelEntry entry;
2060 SilcCommandStatus status;
2061 uint16 ident = silc_command_get_ident(cmd->payload);
2063 unsigned char usercount[4];
2066 for (i = 0; i < lch_count; i++)
2067 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2069 for (i = 0; i < gch_count; i++)
2070 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2073 status = SILC_STATUS_OK;
2074 if ((lch_count + gch_count) > 1)
2075 status = SILC_STATUS_LIST_START;
2078 for (i = 0; i < lch_count; i++) {
2084 status = SILC_STATUS_LIST_ITEM;
2085 if (i >= 1 && i == lch_count - 1 && !gch_count)
2086 status = SILC_STATUS_LIST_END;
2088 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2090 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2091 topic = "*private*";
2092 memset(usercount, 0, sizeof(usercount));
2094 topic = entry->topic;
2095 users = silc_hash_table_count(entry->user_list);
2096 SILC_PUT32_MSB(users, usercount);
2099 /* Send the reply */
2101 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2103 2, idp->data, idp->len,
2104 3, entry->channel_name,
2105 strlen(entry->channel_name),
2106 4, topic, topic ? strlen(topic) : 0,
2108 silc_server_packet_send(cmd->server, cmd->sock,
2109 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2110 packet->len, FALSE);
2111 silc_buffer_free(packet);
2112 silc_buffer_free(idp);
2116 for (i = 0; i < gch_count; i++) {
2122 status = SILC_STATUS_LIST_ITEM;
2123 if (i >= 1 && i == gch_count - 1)
2124 status = SILC_STATUS_LIST_END;
2126 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2128 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2129 topic = "*private*";
2130 memset(usercount, 0, sizeof(usercount));
2132 topic = entry->topic;
2133 users = silc_hash_table_count(entry->user_list);
2134 SILC_PUT32_MSB(users, usercount);
2137 /* Send the reply */
2139 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2141 2, idp->data, idp->len,
2142 3, entry->channel_name,
2143 strlen(entry->channel_name),
2144 4, topic, topic ? strlen(topic) : 0,
2146 silc_server_packet_send(cmd->server, cmd->sock,
2147 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2148 packet->len, FALSE);
2149 silc_buffer_free(packet);
2150 silc_buffer_free(idp);
2154 /* Server side of LIST command. This lists the channel of the requested
2155 server. Secret channels are not listed. */
2157 SILC_SERVER_CMD_FUNC(list)
2159 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2160 SilcServer server = cmd->server;
2161 SilcChannelID *channel_id = NULL;
2164 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2165 uint32 lch_count = 0, gch_count = 0;
2167 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2169 /* If we are normal server, send the command to router, since we
2170 want to know all channels in the network. */
2171 if (!cmd->pending && server->server_type == SILC_SERVER &&
2172 !server->standalone) {
2176 old_ident = silc_command_get_ident(cmd->payload);
2177 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2178 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2179 silc_server_packet_send(server, server->router->connection,
2180 SILC_PACKET_COMMAND, cmd->packet->flags,
2181 tmpbuf->data, tmpbuf->len, TRUE);
2183 /* Reprocess this packet after received reply from router */
2184 silc_server_command_pending(server, SILC_COMMAND_LIST,
2185 silc_command_get_ident(cmd->payload),
2186 silc_server_command_destructor,
2187 silc_server_command_list,
2188 silc_server_command_dup(cmd));
2189 cmd->pending = TRUE;
2190 silc_command_set_ident(cmd->payload, old_ident);
2191 silc_buffer_free(tmpbuf);
2195 /* Get Channel ID */
2196 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2198 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2200 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2201 SILC_STATUS_ERR_NO_CHANNEL_ID);
2206 /* Get the channels from local list */
2207 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2210 /* Get the channels from global list */
2211 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2214 /* Send the reply */
2215 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2216 gchannels, gch_count);
2218 silc_free(lchannels);
2219 silc_free(gchannels);
2222 silc_server_command_free(cmd);
2225 /* Server side of TOPIC command. Sets topic for channel and/or returns
2226 current topic to client. */
2228 SILC_SERVER_CMD_FUNC(topic)
2230 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2231 SilcServer server = cmd->server;
2232 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2233 SilcChannelID *channel_id;
2234 SilcChannelEntry channel;
2235 SilcChannelClientEntry chl;
2236 SilcBuffer packet, idp;
2238 uint32 argc, tmp_len;
2239 uint16 ident = silc_command_get_ident(cmd->payload);
2241 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2243 argc = silc_argument_get_arg_num(cmd->args);
2245 /* Get Channel ID */
2246 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2248 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2249 SILC_STATUS_ERR_NO_CHANNEL_ID);
2252 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2254 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2255 SILC_STATUS_ERR_NO_CHANNEL_ID);
2259 /* Check whether the channel exists */
2260 channel = silc_idlist_find_channel_by_id(server->local_list,
2263 channel = silc_idlist_find_channel_by_id(server->global_list,
2266 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2267 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2274 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2276 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2277 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2281 if (strlen(tmp) > 256) {
2282 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2283 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2287 /* See whether the client is on channel and has rights to change topic */
2288 if (!silc_hash_table_find(channel->user_list, client, NULL,
2290 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2291 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2295 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2296 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2297 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2298 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2303 /* Set the topic for channel */
2304 silc_free(channel->topic);
2305 channel->topic = strdup(tmp);
2307 /* Send TOPIC_SET notify type to the network */
2308 if (!server->standalone)
2309 silc_server_send_notify_topic_set(server, server->router->connection,
2310 server->server_type == SILC_ROUTER ?
2311 TRUE : FALSE, channel,
2312 client->id, SILC_ID_CLIENT,
2315 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2317 /* Send notify about topic change to all clients on the channel */
2318 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2319 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2320 idp->data, idp->len,
2321 channel->topic, strlen(channel->topic));
2322 silc_buffer_free(idp);
2325 /* Send the topic to client as reply packet */
2326 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2327 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2328 SILC_STATUS_OK, ident, 2,
2329 2, idp->data, idp->len,
2332 strlen(channel->topic) : 0);
2333 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2334 0, packet->data, packet->len, FALSE);
2336 silc_buffer_free(packet);
2337 silc_buffer_free(idp);
2338 silc_free(channel_id);
2341 silc_server_command_free(cmd);
2344 /* Server side of INVITE command. Invites some client to join some channel.
2345 This command is also used to manage the invite list of the channel. */
2347 SILC_SERVER_CMD_FUNC(invite)
2349 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2350 SilcServer server = cmd->server;
2351 SilcSocketConnection sock = cmd->sock, dest_sock;
2352 SilcChannelClientEntry chl;
2353 SilcClientEntry sender, dest;
2354 SilcClientID *dest_id = NULL;
2355 SilcChannelEntry channel;
2356 SilcChannelID *channel_id = NULL;
2357 SilcIDListData idata;
2358 SilcBuffer idp, idp2, packet;
2359 unsigned char *tmp, *add, *del;
2361 uint16 ident = silc_command_get_ident(cmd->payload);
2363 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2365 /* Get Channel ID */
2366 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2368 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2369 SILC_STATUS_ERR_NO_CHANNEL_ID);
2372 channel_id = silc_id_payload_parse_id(tmp, len);
2374 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2375 SILC_STATUS_ERR_NO_CHANNEL_ID);
2379 /* Get the channel entry */
2380 channel = silc_idlist_find_channel_by_id(server->local_list,
2383 channel = silc_idlist_find_channel_by_id(server->global_list,
2386 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2387 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2392 /* Check whether the sender of this command is on the channel. */
2393 sender = (SilcClientEntry)sock->user_data;
2394 if (!silc_server_client_on_channel(sender, channel)) {
2395 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2396 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2400 /* Check whether the channel is invite-only channel. If yes then the
2401 sender of this command must be at least channel operator. */
2402 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2403 silc_hash_table_find(channel->user_list, sender, NULL, (void *)&chl);
2404 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2405 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2406 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2411 /* Get destination client ID */
2412 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2416 dest_id = silc_id_payload_parse_id(tmp, len);
2418 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2419 SILC_STATUS_ERR_NO_CLIENT_ID);
2423 /* Get the client entry */
2424 dest = silc_server_get_client_resolve(server, dest_id);
2426 if (server->server_type != SILC_SERVER) {
2427 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2428 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2432 /* The client info is being resolved. Reprocess this packet after
2433 receiving the reply to the query. */
2434 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2436 silc_server_command_destructor,
2437 silc_server_command_invite,
2438 silc_server_command_dup(cmd));
2439 cmd->pending = TRUE;
2440 silc_free(channel_id);
2445 /* Check whether the requested client is already on the channel. */
2446 if (silc_server_client_on_channel(dest, channel)) {
2447 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2448 SILC_STATUS_ERR_USER_ON_CHANNEL);
2452 /* Get route to the client */
2453 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2455 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2456 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2460 memset(invite, 0, sizeof(invite));
2461 strncat(invite, dest->nickname, strlen(dest->nickname));
2462 strncat(invite, "!", 1);
2463 strncat(invite, dest->username, strlen(dest->username));
2464 if (!strchr(dest->username, '@')) {
2465 strncat(invite, "@", 1);
2466 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2469 len = strlen(invite);
2470 if (!channel->invite_list)
2471 channel->invite_list = silc_calloc(len + 2,
2472 sizeof(*channel->invite_list));
2474 channel->invite_list = silc_realloc(channel->invite_list,
2475 sizeof(*channel->invite_list) *
2477 strlen(channel->invite_list) + 2));
2478 strncat(channel->invite_list, invite, len);
2479 strncat(channel->invite_list, ",", 1);
2481 /* Send notify to the client that is invited to the channel */
2482 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2483 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2484 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2486 SILC_NOTIFY_TYPE_INVITE, 3,
2487 idp->data, idp->len,
2488 channel->channel_name,
2489 strlen(channel->channel_name),
2490 idp2->data, idp2->len);
2491 silc_buffer_free(idp);
2492 silc_buffer_free(idp2);
2495 /* Add the client to the invite list of the channel */
2496 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2498 if (!channel->invite_list)
2499 channel->invite_list = silc_calloc(len + 2,
2500 sizeof(*channel->invite_list));
2502 channel->invite_list = silc_realloc(channel->invite_list,
2503 sizeof(*channel->invite_list) *
2505 strlen(channel->invite_list) + 2));
2506 if (add[len - 1] == ',')
2507 add[len - 1] = '\0';
2509 strncat(channel->invite_list, add, len);
2510 strncat(channel->invite_list, ",", 1);
2513 /* Get the invite to be removed and remove it from the list */
2514 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2515 if (del && channel->invite_list) {
2516 char *start, *end, *n;
2518 if (!strncmp(channel->invite_list, del,
2519 strlen(channel->invite_list) - 1)) {
2520 silc_free(channel->invite_list);
2521 channel->invite_list = NULL;
2523 start = strstr(channel->invite_list, del);
2524 if (start && strlen(start) >= len) {
2526 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2527 strncat(n, channel->invite_list, start - channel->invite_list);
2528 strncat(n, end + 1, ((channel->invite_list +
2529 strlen(channel->invite_list)) - end) - 1);
2530 silc_free(channel->invite_list);
2531 channel->invite_list = n;
2536 /* Send notify to the primary router */
2537 if (!server->standalone)
2538 silc_server_send_notify_invite(server, server->router->connection,
2539 server->server_type == SILC_ROUTER ?
2540 TRUE : FALSE, channel,
2541 sender->id, add, del);
2543 /* Send command reply */
2544 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2548 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2549 SILC_STATUS_OK, ident, 2,
2551 3, channel->invite_list,
2552 channel->invite_list ?
2553 strlen(channel->invite_list) : 0);
2556 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2557 SILC_STATUS_OK, ident, 1,
2559 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2560 packet->data, packet->len, FALSE);
2561 silc_buffer_free(packet);
2565 silc_free(channel_id);
2566 silc_server_command_free(cmd);
2571 SilcSocketConnection sock;
2575 /* Quits connection to client. This gets called if client won't
2576 close the connection even when it has issued QUIT command. */
2578 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2580 QuitInternal q = (QuitInternal)context;
2582 /* Free all client specific data, such as client entry and entires
2583 on channels this client may be on. */
2584 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2586 q->sock->user_data = NULL;
2588 /* Close the connection on our side */
2589 silc_server_close_connection(q->server, q->sock);
2591 silc_free(q->signoff);
2595 /* Quits SILC session. This is the normal way to disconnect client. */
2597 SILC_SERVER_CMD_FUNC(quit)
2599 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2600 SilcServer server = cmd->server;
2601 SilcSocketConnection sock = cmd->sock;
2603 unsigned char *tmp = NULL;
2606 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2608 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2611 /* Get destination ID */
2612 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2616 q = silc_calloc(1, sizeof(*q));
2619 q->signoff = tmp ? strdup(tmp) : NULL;
2621 /* We quit the connection with little timeout */
2622 silc_schedule_task_add(server->schedule, sock->sock,
2623 silc_server_command_quit_cb, (void *)q,
2624 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2627 silc_server_command_free(cmd);
2630 /* Server side of command KILL. This command is used by router operator
2631 to remove an client from the SILC Network temporarily. */
2633 SILC_SERVER_CMD_FUNC(kill)
2635 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2636 SilcServer server = cmd->server;
2637 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2638 SilcClientEntry remote_client;
2639 SilcClientID *client_id;
2640 unsigned char *tmp, *comment;
2641 uint32 tmp_len, tmp_len2;
2643 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2645 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2648 /* KILL command works only on router */
2649 if (server->server_type != SILC_ROUTER) {
2650 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2651 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2655 /* Check whether client has the permissions. */
2656 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2657 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2658 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2662 /* Get the client ID */
2663 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2665 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2666 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2669 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2671 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2672 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2676 /* Get the client entry */
2677 remote_client = silc_idlist_find_client_by_id(server->local_list,
2678 client_id, TRUE, NULL);
2679 if (!remote_client) {
2680 remote_client = silc_idlist_find_client_by_id(server->global_list,
2681 client_id, TRUE, NULL);
2682 if (!remote_client) {
2683 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2684 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2690 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2694 /* Send reply to the sender */
2695 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2698 /* Send the KILL notify packets. First send it to the channel, then
2699 to our primary router and then directly to the client who is being
2700 killed right now. */
2702 /* Send KILLED notify to the channels. It is not sent to the client
2703 as it will be sent differently destined directly to the client and not
2705 silc_server_send_notify_on_channels(server, remote_client,
2706 remote_client, SILC_NOTIFY_TYPE_KILLED,
2709 comment, comment ? tmp_len2 : 0);
2711 /* Send KILLED notify to primary route */
2712 if (!server->standalone)
2713 silc_server_send_notify_killed(server, server->router->connection, TRUE,
2714 remote_client->id, comment);
2716 /* Send KILLED notify to the client directly */
2717 silc_server_send_notify_killed(server, remote_client->connection ?
2718 remote_client->connection :
2719 remote_client->router->connection, FALSE,
2720 remote_client->id, comment);
2722 /* Remove the client from all channels. This generates new keys to the
2723 channels as well. */
2724 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2727 /* Remove the client entry, If it is locally connected then we will also
2728 disconnect the client here */
2729 if (remote_client->connection) {
2730 /* Remove locally conneted client */
2731 SilcSocketConnection sock = remote_client->connection;
2732 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2733 silc_server_close_connection(server, sock);
2735 /* Remove remote client */
2736 if (!silc_idlist_del_client(server->global_list, remote_client))
2737 silc_idlist_del_client(server->local_list, remote_client);
2741 silc_server_command_free(cmd);
2744 /* Server side of command INFO. This sends information about us to
2745 the client. If client requested specific server we will send the
2746 command to that server. */
2748 SILC_SERVER_CMD_FUNC(info)
2750 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2751 SilcServer server = cmd->server;
2752 SilcBuffer packet, idp;
2755 char *dest_server, *server_info = NULL, *server_name;
2756 uint16 ident = silc_command_get_ident(cmd->payload);
2757 SilcServerEntry entry = NULL;
2758 SilcServerID *server_id = NULL;
2760 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2762 /* Get server name */
2763 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2766 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2768 server_id = silc_id_payload_parse_id(tmp, tmp_len);
2770 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2771 SILC_STATUS_ERR_NO_SERVER_ID);
2777 /* Check whether we have this server cached */
2778 entry = silc_idlist_find_server_by_id(server->local_list,
2779 server_id, TRUE, NULL);
2781 entry = silc_idlist_find_server_by_id(server->global_list,
2782 server_id, TRUE, NULL);
2783 if (!entry && server->server_type != SILC_SERVER) {
2784 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2785 SILC_STATUS_ERR_NO_SUCH_SERVER);
2791 /* Some buggy servers has sent request to router about themselves. */
2792 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2795 if ((!dest_server && !server_id && !entry) || (entry &&
2796 entry == server->id_entry) ||
2797 (dest_server && !cmd->pending &&
2798 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2799 /* Send our reply */
2800 char info_string[256];
2802 memset(info_string, 0, sizeof(info_string));
2803 snprintf(info_string, sizeof(info_string),
2804 "location: %s server: %s admin: %s <%s>",
2805 server->config->admin_info->location,
2806 server->config->admin_info->server_type,
2807 server->config->admin_info->admin_name,
2808 server->config->admin_info->admin_email);
2810 server_info = info_string;
2811 entry = server->id_entry;
2813 /* Check whether we have this server cached */
2814 if (!entry && dest_server) {
2815 entry = silc_idlist_find_server_by_name(server->global_list,
2816 dest_server, TRUE, NULL);
2818 entry = silc_idlist_find_server_by_name(server->local_list,
2819 dest_server, TRUE, NULL);
2823 if (!cmd->pending &&
2824 server->server_type != SILC_SERVER && entry && !entry->server_info) {
2825 /* Send to the server */
2829 old_ident = silc_command_get_ident(cmd->payload);
2830 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2831 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2833 silc_server_packet_send(server, entry->connection,
2834 SILC_PACKET_COMMAND, cmd->packet->flags,
2835 tmpbuf->data, tmpbuf->len, TRUE);
2837 /* Reprocess this packet after received reply from router */
2838 silc_server_command_pending(server, SILC_COMMAND_INFO,
2839 silc_command_get_ident(cmd->payload),
2840 silc_server_command_destructor,
2841 silc_server_command_info,
2842 silc_server_command_dup(cmd));
2843 cmd->pending = TRUE;
2844 silc_command_set_ident(cmd->payload, old_ident);
2845 silc_buffer_free(tmpbuf);
2849 if (!entry && !cmd->pending && !server->standalone) {
2850 /* Send to the primary router */
2854 old_ident = silc_command_get_ident(cmd->payload);
2855 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2856 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2858 silc_server_packet_send(server, server->router->connection,
2859 SILC_PACKET_COMMAND, cmd->packet->flags,
2860 tmpbuf->data, tmpbuf->len, TRUE);
2862 /* Reprocess this packet after received reply from router */
2863 silc_server_command_pending(server, SILC_COMMAND_INFO,
2864 silc_command_get_ident(cmd->payload),
2865 silc_server_command_destructor,
2866 silc_server_command_info,
2867 silc_server_command_dup(cmd));
2868 cmd->pending = TRUE;
2869 silc_command_set_ident(cmd->payload, old_ident);
2870 silc_buffer_free(tmpbuf);
2875 silc_free(server_id);
2878 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2879 SILC_STATUS_ERR_NO_SUCH_SERVER);
2883 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2885 server_info = entry->server_info;
2886 server_name = entry->server_name;
2888 /* Send the reply */
2889 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2890 SILC_STATUS_OK, ident, 3,
2891 2, idp->data, idp->len,
2893 strlen(server_name),
2896 strlen(server_info) : 0);
2897 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2898 packet->data, packet->len, FALSE);
2900 silc_buffer_free(packet);
2901 silc_buffer_free(idp);
2904 silc_server_command_free(cmd);
2907 /* Server side of command PING. This just replies to the ping. */
2909 SILC_SERVER_CMD_FUNC(ping)
2911 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2912 SilcServer server = cmd->server;
2917 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
2920 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2922 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2923 SILC_STATUS_ERR_NO_SERVER_ID);
2926 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2930 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2931 /* Send our reply */
2932 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2935 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2936 SILC_STATUS_ERR_NO_SUCH_SERVER);
2943 silc_server_command_free(cmd);
2946 /* Internal routine to join channel. The channel sent to this function
2947 has been either created or resolved from ID lists. This joins the sent
2948 client to the channel. */
2950 static void silc_server_command_join_channel(SilcServer server,
2951 SilcServerCommandContext cmd,
2952 SilcChannelEntry channel,
2953 SilcClientID *client_id,
2957 const unsigned char *auth,
2960 SilcSocketConnection sock = cmd->sock;
2962 uint32 tmp_len, user_count;
2963 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
2964 SilcClientEntry client;
2965 SilcChannelClientEntry chl;
2966 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
2967 uint16 ident = silc_command_get_ident(cmd->payload);
2968 char check[512], check2[512];
2969 bool founder = FALSE;
2971 SILC_LOG_DEBUG(("Start"));
2976 /* Get the client entry */
2977 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2978 client = (SilcClientEntry)sock->user_data;
2980 client = silc_server_get_client_resolve(server, client_id);
2985 /* The client info is being resolved. Reprocess this packet after
2986 receiving the reply to the query. */
2987 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2988 server->cmd_ident, NULL,
2989 silc_server_command_join,
2990 silc_server_command_dup(cmd));
2991 cmd->pending = TRUE;
2995 cmd->pending = FALSE;
2999 * Check founder auth payload if provided. If client can gain founder
3000 * privileges it can override various conditions on joining the channel,
3001 * and can have directly the founder mode set on the channel.
3003 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3004 SilcIDListData idata = (SilcIDListData)client;
3006 if (channel->founder_key && idata->public_key &&
3007 silc_pkcs_public_key_compare(channel->founder_key,
3008 idata->public_key)) {
3009 void *auth_data = (channel->founder_method == SILC_AUTH_PASSWORD ?
3010 (void *)channel->founder_passwd :
3011 (void *)channel->founder_key);
3012 uint32 auth_data_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
3013 channel->founder_passwd_len : 0);
3015 /* Check whether the client is to become founder */
3016 if (silc_auth_verify_data(auth, auth_len, channel->founder_method,
3017 auth_data, auth_data_len,
3018 idata->hash, client->id, SILC_ID_CLIENT)) {
3019 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3026 * Check channel modes
3030 memset(check, 0, sizeof(check));
3031 memset(check2, 0, sizeof(check2));
3032 strncat(check, client->nickname, strlen(client->nickname));
3033 strncat(check, "!", 1);
3034 strncat(check, client->username, strlen(client->username));
3035 if (!strchr(client->username, '@')) {
3036 strncat(check, "@", 1);
3037 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3040 strncat(check2, client->nickname, strlen(client->nickname));
3041 if (!strchr(client->nickname, '@')) {
3042 strncat(check2, "@", 1);
3043 strncat(check2, server->server_name, strlen(server->server_name));
3045 strncat(check2, "!", 1);
3046 strncat(check2, client->username, strlen(client->username));
3047 if (!strchr(client->username, '@')) {
3048 strncat(check2, "@", 1);
3049 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3052 /* Check invite list if channel is invite-only channel */
3053 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3054 if (!channel->invite_list ||
3055 (!silc_string_match(channel->invite_list, check) &&
3056 !silc_string_match(channel->invite_list, check2))) {
3057 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3058 SILC_STATUS_ERR_NOT_INVITED);
3063 /* Check ban list if it exists. If the client's nickname, server,
3064 username and/or hostname is in the ban list the access to the
3065 channel is denied. */
3066 if (channel->ban_list) {
3067 if (!channel->ban_list ||
3068 silc_string_match(channel->ban_list, check) ||
3069 silc_string_match(channel->ban_list, check2)) {
3070 silc_server_command_send_status_reply(
3071 cmd, SILC_COMMAND_JOIN,
3072 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
3077 /* Check user count limit if set. */
3078 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3079 if (silc_hash_table_count(channel->user_list) + 1 >
3080 channel->user_limit) {
3081 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3082 SILC_STATUS_ERR_CHANNEL_IS_FULL);
3088 /* Check the channel passphrase if set. */
3089 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3090 /* Get passphrase */
3091 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3093 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
3094 memcpy(passphrase, tmp, tmp_len);
3097 if (!passphrase || !channel->passphrase ||
3098 memcmp(channel->passphrase, passphrase,
3099 strlen(channel->passphrase))) {
3100 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3101 SILC_STATUS_ERR_BAD_PASSWORD);
3107 * Client is allowed to join to the channel. Make it happen.
3110 /* Check whether the client already is on the channel */
3111 if (silc_server_client_on_channel(client, channel)) {
3112 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3113 SILC_STATUS_ERR_USER_ON_CHANNEL);
3117 /* Generate new channel key as protocol dictates */
3119 if (!silc_server_create_channel_key(server, channel, 0))
3122 /* Send the channel key. This is broadcasted to the channel but is not
3123 sent to the client who is joining to the channel. */
3124 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3125 silc_server_send_channel_key(server, NULL, channel,
3126 server->server_type == SILC_ROUTER ?
3127 FALSE : !server->standalone);
3130 /* Join the client to the channel by adding it to channel's user list.
3131 Add also the channel to client entry's channels list for fast cross-
3133 chl = silc_calloc(1, sizeof(*chl));
3135 chl->client = client;
3136 chl->channel = channel;
3137 silc_hash_table_add(channel->user_list, client, chl);
3138 silc_hash_table_add(client->channels, channel, chl);
3140 /* Get users on the channel */
3141 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3144 /* Encode Client ID Payload of the original client who wants to join */
3145 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3147 /* Encode command reply packet */
3148 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3149 SILC_PUT32_MSB(channel->mode, mode);
3150 SILC_PUT32_MSB(created, tmp2);
3151 SILC_PUT32_MSB(user_count, tmp3);
3153 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3154 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3155 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
3156 strlen(channel->channel_key->
3158 channel->channel_key->cipher->name,
3159 channel->key_len / 8, channel->key);
3164 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3165 SILC_STATUS_OK, ident, 13,
3166 2, channel->channel_name,
3167 strlen(channel->channel_name),
3168 3, chidp->data, chidp->len,
3169 4, clidp->data, clidp->len,
3172 7, keyp ? keyp->data : NULL,
3173 keyp ? keyp->len : 0,
3174 8, channel->ban_list,
3176 strlen(channel->ban_list) : 0,
3177 9, channel->invite_list,
3178 channel->invite_list ?
3179 strlen(channel->invite_list) : 0,
3182 strlen(channel->topic) : 0,
3183 11, silc_hmac_get_name(channel->hmac),
3184 strlen(silc_hmac_get_name(channel->
3187 13, user_list->data, user_list->len,
3188 14, mode_list->data,
3191 /* Send command reply */
3192 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3193 reply->data, reply->len, FALSE);
3195 /* Send JOIN notify to locally connected clients on the channel. If
3196 we are normal server then router will send or have sent JOIN notify
3197 already. However since we've added the client already to our channel
3198 we'll ignore it (in packet_receive.c) so we must send it here. If
3199 we are router then this will send it to local clients and local
3201 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3202 SILC_NOTIFY_TYPE_JOIN, 2,
3203 clidp->data, clidp->len,
3204 chidp->data, chidp->len);
3206 if (!cmd->pending) {
3207 /* Send JOIN notify packet to our primary router */
3208 if (!server->standalone)
3209 silc_server_send_notify_join(server, server->router->connection,
3210 server->server_type == SILC_ROUTER ?
3211 TRUE : FALSE, channel, client->id);
3214 /* Distribute the channel key to all backup routers. */
3215 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3216 keyp->data, keyp->len, FALSE, TRUE);
3218 /* If client became founder by providing correct founder auth data
3219 notify the mode change to the channel. */
3221 SILC_PUT32_MSB(chl->mode, mode);
3222 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3223 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3224 clidp->data, clidp->len,
3225 mode, 4, clidp->data, clidp->len);
3227 /* Set CUMODE notify type to network */
3228 if (!server->standalone)
3229 silc_server_send_notify_cumode(server, server->router->connection,
3230 server->server_type == SILC_ROUTER ?
3231 TRUE : FALSE, channel,
3232 chl->mode, client->id, SILC_ID_CLIENT,
3237 silc_buffer_free(reply);
3238 silc_buffer_free(clidp);
3239 silc_buffer_free(chidp);
3240 silc_buffer_free(keyp);
3241 silc_buffer_free(user_list);
3242 silc_buffer_free(mode_list);
3245 silc_free(passphrase);
3248 /* Server side of command JOIN. Joins client into requested channel. If
3249 the channel does not exist it will be created. */
3251 SILC_SERVER_CMD_FUNC(join)
3253 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3254 SilcServer server = cmd->server;
3255 unsigned char *auth;
3256 uint32 tmp_len, auth_len;
3257 char *tmp, *channel_name = NULL, *cipher, *hmac;
3258 SilcChannelEntry channel;
3260 bool created = FALSE, create_key = TRUE;
3261 SilcClientID *client_id;
3263 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3265 /* Get channel name */
3266 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3268 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3269 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3274 if (strlen(channel_name) > 256)
3275 channel_name[255] = '\0';
3277 if (silc_server_command_bad_chars(channel_name) == TRUE) {
3278 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3279 SILC_STATUS_ERR_BAD_CHANNEL);
3283 /* Get Client ID of the client who is joining to the channel */
3284 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3286 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3287 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3290 client_id = silc_id_payload_parse_id(tmp, tmp_len);
3292 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3293 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3297 /* Get cipher, hmac name and auth payload */
3298 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3299 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3300 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3302 /* See if the channel exists */
3303 channel = silc_idlist_find_channel_by_name(server->local_list,
3304 channel_name, NULL);
3306 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3307 /* If this is coming from client the Client ID in the command packet must
3308 be same as the client's ID. */
3309 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3310 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3311 if (!SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
3312 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3313 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3318 if (!channel || channel->disabled) {
3319 /* Channel not found */
3321 /* If we are standalone server we don't have a router, we just create
3322 the channel by ourselves. */
3323 if (server->standalone) {
3324 channel = silc_server_create_new_channel(server, server->id, cipher,
3325 hmac, channel_name, TRUE);
3327 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3328 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3332 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3338 /* The channel does not exist on our server. If we are normal server
3339 we will send JOIN command to our router which will handle the
3340 joining procedure (either creates the channel if it doesn't exist
3341 or joins the client to it). */
3342 if (server->server_type != SILC_ROUTER) {
3346 /* If this is pending command callback then we've resolved
3347 it and it didn't work, return since we've notified the
3348 client already in the command reply callback. */
3352 old_ident = silc_command_get_ident(cmd->payload);
3353 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3354 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3356 /* Send JOIN command to our router */
3357 silc_server_packet_send(server, (SilcSocketConnection)
3358 server->router->connection,
3359 SILC_PACKET_COMMAND, cmd->packet->flags,
3360 tmpbuf->data, tmpbuf->len, TRUE);
3362 /* Reprocess this packet after received reply from router */
3363 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3364 silc_command_get_ident(cmd->payload),
3365 silc_server_command_destructor,
3366 silc_server_command_join,
3367 silc_server_command_dup(cmd));
3368 cmd->pending = TRUE;
3372 /* We are router and the channel does not seem exist so we will check
3373 our global list as well for the channel. */
3374 channel = silc_idlist_find_channel_by_name(server->global_list,
3375 channel_name, NULL);
3377 /* Channel really does not exist, create it */
3378 channel = silc_server_create_new_channel(server, server->id, cipher,
3379 hmac, channel_name, TRUE);
3381 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3382 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3386 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3394 /* Channel not found */
3396 /* If the command came from router and we are normal server then
3397 something went wrong with the joining as the channel was not found.
3398 We can't do anything else but ignore this. */
3399 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3400 server->server_type != SILC_ROUTER)
3403 /* We are router and the channel does not seem exist so we will check
3404 our global list as well for the channel. */
3405 channel = silc_idlist_find_channel_by_name(server->global_list,
3406 channel_name, NULL);
3408 /* Channel really does not exist, create it */
3409 channel = silc_server_create_new_channel(server, server->id, cipher,
3410 hmac, channel_name, TRUE);
3412 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3413 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3417 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3424 /* Check whether the channel was created by our router */
3425 if (cmd->pending && context2) {
3426 SilcServerCommandReplyContext reply =
3427 (SilcServerCommandReplyContext)context2;
3428 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3429 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3430 SILC_GET32_MSB(created, tmp);
3431 create_key = FALSE; /* Router returned the key already */
3435 /* If the channel does not have global users and is also empty the client
3436 will be the channel founder and operator. */
3437 if (!channel->global_users && !silc_hash_table_count(channel->user_list))
3438 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3440 /* Join to the channel */
3441 silc_server_command_join_channel(server, cmd, channel, client_id,
3442 created, create_key, umode,
3445 silc_free(client_id);
3448 silc_server_command_free(cmd);
3451 /* Server side of command MOTD. Sends server's current "message of the
3452 day" to the client. */
3454 SILC_SERVER_CMD_FUNC(motd)
3456 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3457 SilcServer server = cmd->server;
3458 SilcBuffer packet, idp;
3459 char *motd, *dest_server;
3461 uint16 ident = silc_command_get_ident(cmd->payload);
3463 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3465 /* Get server name */
3466 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3468 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3469 SILC_STATUS_ERR_NO_SUCH_SERVER);
3473 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3476 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3478 if (server->config && server->config->motd &&
3479 server->config->motd->motd_file) {
3481 motd = silc_file_readfile(server->config->motd->motd_file, &motd_len);
3486 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3487 SILC_STATUS_OK, ident, 2,
3492 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3493 SILC_STATUS_OK, ident, 1,
3497 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3498 packet->data, packet->len, FALSE);
3499 silc_buffer_free(packet);
3500 silc_buffer_free(idp);
3502 SilcServerEntry entry;
3504 /* Check whether we have this server cached */
3505 entry = silc_idlist_find_server_by_name(server->global_list,
3506 dest_server, TRUE, NULL);
3508 entry = silc_idlist_find_server_by_name(server->local_list,
3509 dest_server, TRUE, NULL);
3512 if (server->server_type != SILC_SERVER && !cmd->pending &&
3513 entry && !entry->motd) {
3514 /* Send to the server */
3518 old_ident = silc_command_get_ident(cmd->payload);
3519 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3520 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3522 silc_server_packet_send(server, entry->connection,
3523 SILC_PACKET_COMMAND, cmd->packet->flags,
3524 tmpbuf->data, tmpbuf->len, TRUE);
3526 /* Reprocess this packet after received reply from router */
3527 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3528 silc_command_get_ident(cmd->payload),
3529 silc_server_command_destructor,
3530 silc_server_command_motd,
3531 silc_server_command_dup(cmd));
3532 cmd->pending = TRUE;
3533 silc_command_set_ident(cmd->payload, old_ident);
3534 silc_buffer_free(tmpbuf);
3538 if (!entry && !cmd->pending && !server->standalone) {
3539 /* Send to the primary router */
3543 old_ident = silc_command_get_ident(cmd->payload);
3544 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3545 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3547 silc_server_packet_send(server, server->router->connection,
3548 SILC_PACKET_COMMAND, cmd->packet->flags,
3549 tmpbuf->data, tmpbuf->len, TRUE);
3551 /* Reprocess this packet after received reply from router */
3552 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3553 silc_command_get_ident(cmd->payload),
3554 silc_server_command_destructor,
3555 silc_server_command_motd,
3556 silc_server_command_dup(cmd));
3557 cmd->pending = TRUE;
3558 silc_command_set_ident(cmd->payload, old_ident);
3559 silc_buffer_free(tmpbuf);
3564 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3565 SILC_STATUS_ERR_NO_SUCH_SERVER);
3569 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3570 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3571 SILC_STATUS_OK, ident, 2,
3575 strlen(entry->motd) : 0);
3576 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3577 packet->data, packet->len, FALSE);
3578 silc_buffer_free(packet);
3579 silc_buffer_free(idp);
3583 silc_server_command_free(cmd);
3586 /* Server side of command UMODE. Client can use this command to set/unset
3587 user mode. Client actually cannot set itself to be as server/router
3588 operator so this can be used only to unset the modes. */
3590 SILC_SERVER_CMD_FUNC(umode)
3592 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3593 SilcServer server = cmd->server;
3594 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3596 unsigned char *tmp_mask;
3598 uint16 ident = silc_command_get_ident(cmd->payload);
3600 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3603 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 2, 2);
3605 /* Get the client's mode mask */
3606 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3608 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3609 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3612 SILC_GET32_MSB(mask, tmp_mask);
3618 if (mask & SILC_UMODE_SERVER_OPERATOR) {
3619 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR)) {
3620 /* Cannot operator mode */
3621 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3622 SILC_STATUS_ERR_PERM_DENIED);
3626 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
3627 /* Remove the server operator rights */
3628 client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3631 if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3632 if (!(client->mode & SILC_UMODE_ROUTER_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_ROUTER_OPERATOR)
3640 /* Remove the router operator rights */
3641 client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3644 if (mask & SILC_UMODE_GONE) {
3645 client->mode |= SILC_UMODE_GONE;
3647 if (client->mode & SILC_UMODE_GONE)
3648 /* Remove the gone status */
3649 client->mode &= ~SILC_UMODE_GONE;
3652 /* Send UMODE change to primary router */
3653 if (!server->standalone)
3654 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3655 client->id, client->mode);
3657 /* Send command reply to sender */
3658 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3659 SILC_STATUS_OK, ident, 1,
3661 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3662 packet->data, packet->len, FALSE);
3663 silc_buffer_free(packet);
3666 silc_server_command_free(cmd);
3669 /* Checks that client has rights to add or remove channel modes. If any
3670 of the checks fails FALSE is returned. */
3672 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3673 SilcChannelClientEntry client,
3676 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3677 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3679 /* Check whether has rights to change anything */
3680 if (!is_op && !is_fo)
3683 /* Check whether has rights to change everything */
3687 /* We know that client is channel operator, check that they are not
3688 changing anything that requires channel founder rights. Rest of the
3689 modes are available automatically for channel operator. */
3691 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3692 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3693 if (is_op && !is_fo)
3696 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3697 if (is_op && !is_fo)
3702 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3703 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE))
3704 if (is_op && !is_fo)
3707 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3708 if (is_op && !is_fo)
3713 if (mode & SILC_CHANNEL_MODE_CIPHER) {
3714 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER))
3715 if (is_op && !is_fo)
3718 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3719 if (is_op && !is_fo)
3724 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3725 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH))
3726 if (is_op && !is_fo)
3729 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3730 if (is_op && !is_fo)
3738 /* Server side command of CMODE. Changes channel mode */
3740 SILC_SERVER_CMD_FUNC(cmode)
3742 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3743 SilcServer server = cmd->server;
3744 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3745 SilcIDListData idata = (SilcIDListData)client;
3746 SilcChannelID *channel_id;
3747 SilcChannelEntry channel;
3748 SilcChannelClientEntry chl;
3749 SilcBuffer packet, cidp;
3750 unsigned char *tmp, *tmp_id, *tmp_mask;
3751 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3752 uint32 mode_mask, tmp_len, tmp_len2;
3753 uint16 ident = silc_command_get_ident(cmd->payload);
3755 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 2, 7);
3757 /* Get Channel ID */
3758 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3760 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3761 SILC_STATUS_ERR_NO_CHANNEL_ID);
3764 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3766 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3767 SILC_STATUS_ERR_NO_CHANNEL_ID);
3771 /* Get the channel mode mask */
3772 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3774 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3775 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3778 SILC_GET32_MSB(mode_mask, tmp_mask);
3780 /* Get channel entry */
3781 channel = silc_idlist_find_channel_by_id(server->local_list,
3784 channel = silc_idlist_find_channel_by_id(server->global_list,
3787 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3788 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3793 /* Check whether this client is on the channel */
3794 if (!silc_server_client_on_channel(client, channel)) {
3795 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3796 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3800 /* Get entry to the channel user list */
3801 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
3803 /* Check that client has rights to change any requested channel modes */
3804 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3805 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3806 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3811 * Check the modes. Modes that requires nothing special operation are
3815 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3816 /* Channel uses private keys to protect traffic. Client(s) has set the
3817 key locally they want to use, server does not know that key. */
3818 /* Nothing interesting to do here */
3820 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3821 /* The mode is removed and we need to generate and distribute
3822 new channel key. Clients are not using private channel keys
3823 anymore after this. */
3825 /* Re-generate channel key */
3826 if (!silc_server_create_channel_key(server, channel, 0))
3829 /* Send the channel key. This sends it to our local clients and if
3830 we are normal server to our router as well. */
3831 silc_server_send_channel_key(server, NULL, channel,
3832 server->server_type == SILC_ROUTER ?
3833 FALSE : !server->standalone);
3835 cipher = channel->channel_key->cipher->name;
3836 hmac = (char *)silc_hmac_get_name(channel->hmac);
3840 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3841 /* User limit is set on channel */
3844 /* Get user limit */
3845 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3847 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3848 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3849 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3853 SILC_GET32_MSB(user_limit, tmp);
3854 channel->user_limit = user_limit;
3857 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3858 /* User limit mode is unset. Remove user limit */
3859 channel->user_limit = 0;
3862 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3863 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3864 /* Passphrase has been set to channel */
3866 /* Get the passphrase */
3867 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3869 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3870 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3874 /* Save the passphrase */
3875 passphrase = channel->passphrase = strdup(tmp);
3878 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3879 /* Passphrase mode is unset. remove the passphrase */
3880 if (channel->passphrase) {
3881 silc_free(channel->passphrase);
3882 channel->passphrase = NULL;
3887 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3888 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3889 /* Cipher to use protect the traffic */
3890 SilcCipher newkey, oldkey;
3893 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3895 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3896 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3900 /* Delete old cipher and allocate the new one */
3901 if (!silc_cipher_alloc(cipher, &newkey)) {
3902 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3903 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3907 oldkey = channel->channel_key;
3908 channel->channel_key = newkey;
3910 /* Re-generate channel key */
3911 if (!silc_server_create_channel_key(server, channel, 0)) {
3912 /* We don't have new key, revert to old one */
3913 channel->channel_key = oldkey;
3917 /* Remove old channel key for good */
3918 silc_cipher_free(oldkey);
3920 /* Send the channel key. This sends it to our local clients and if
3921 we are normal server to our router as well. */
3922 silc_server_send_channel_key(server, NULL, channel,
3923 server->server_type == SILC_ROUTER ?
3924 FALSE : !server->standalone);
3927 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3928 /* Cipher mode is unset. Remove the cipher and revert back to
3930 SilcCipher newkey, oldkey;
3931 cipher = channel->cipher;
3933 /* Delete old cipher and allocate default one */
3934 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
3935 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3936 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3940 oldkey = channel->channel_key;
3941 channel->channel_key = newkey;
3943 /* Re-generate channel key */
3944 if (!silc_server_create_channel_key(server, channel, 0)) {
3945 /* We don't have new key, revert to old one */
3946 channel->channel_key = oldkey;
3950 /* Remove old channel key for good */
3951 silc_cipher_free(oldkey);
3953 /* Send the channel key. This sends it to our local clients and if
3954 we are normal server to our router as well. */
3955 silc_server_send_channel_key(server, NULL, channel,
3956 server->server_type == SILC_ROUTER ?
3957 FALSE : !server->standalone);
3961 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3962 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3963 /* HMAC to use protect the traffic */
3964 unsigned char hash[32];
3968 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3970 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3971 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3975 /* Delete old hmac and allocate the new one */
3976 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
3977 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3978 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3982 silc_hmac_free(channel->hmac);
3983 channel->hmac = newhmac;
3985 /* Set the HMAC key out of current channel key. The client must do
3987 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
3988 channel->key_len / 8, hash);
3989 silc_hmac_set_key(channel->hmac, hash,
3990 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3991 memset(hash, 0, sizeof(hash));
3994 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
3995 /* Hmac mode is unset. Remove the hmac and revert back to
3998 unsigned char hash[32];
3999 hmac = channel->hmac_name;
4001 /* Delete old hmac and allocate default one */
4002 silc_hmac_free(channel->hmac);
4003 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4004 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4005 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4009 silc_hmac_free(channel->hmac);
4010 channel->hmac = newhmac;
4012 /* Set the HMAC key out of current channel key. The client must do
4014 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4015 channel->key_len / 8,
4017 silc_hmac_set_key(channel->hmac, hash,
4018 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4019 memset(hash, 0, sizeof(hash));
4023 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4024 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4025 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4026 /* Set the founder authentication */
4027 SilcAuthPayload auth;
4029 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4031 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4032 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4036 auth = silc_auth_payload_parse(tmp, tmp_len);
4038 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4039 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4043 /* Save the public key */
4044 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
4045 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
4048 channel->founder_method = silc_auth_get_method(auth);
4050 if (channel->founder_method == SILC_AUTH_PASSWORD) {
4051 tmp = silc_auth_get_data(auth, &tmp_len);
4052 channel->founder_passwd =
4053 silc_calloc(tmp_len + 1, sizeof(*channel->founder_passwd));
4054 memcpy(channel->founder_passwd, tmp, tmp_len);
4055 channel->founder_passwd_len = tmp_len;
4057 /* Verify the payload before setting the mode */
4058 if (!silc_auth_verify(auth, channel->founder_method,
4059 channel->founder_key, 0, idata->hash,
4060 client->id, SILC_ID_CLIENT)) {
4061 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4062 SILC_STATUS_ERR_AUTH_FAILED);
4067 silc_auth_payload_free(auth);
4071 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4072 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4073 if (channel->founder_key)
4074 silc_pkcs_public_key_free(channel->founder_key);
4075 if (channel->founder_passwd) {
4076 silc_free(channel->founder_passwd);
4077 channel->founder_passwd = NULL;
4083 /* Finally, set the mode */
4084 channel->mode = mode_mask;
4086 /* Send CMODE_CHANGE notify. */
4087 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4088 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4089 SILC_NOTIFY_TYPE_CMODE_CHANGE, 5,
4090 cidp->data, cidp->len,
4092 cipher, cipher ? strlen(cipher) : 0,
4093 hmac, hmac ? strlen(hmac) : 0,
4094 passphrase, passphrase ?
4095 strlen(passphrase) : 0);
4097 /* Set CMODE notify type to network */
4098 if (!server->standalone)
4099 silc_server_send_notify_cmode(server, server->router->connection,
4100 server->server_type == SILC_ROUTER ?
4101 TRUE : FALSE, channel,
4102 mode_mask, client->id, SILC_ID_CLIENT,
4103 cipher, hmac, passphrase);
4105 /* Send command reply to sender */
4106 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4107 SILC_STATUS_OK, ident, 2,
4108 2, tmp_id, tmp_len2,
4110 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4111 packet->data, packet->len, FALSE);
4113 silc_buffer_free(packet);
4114 silc_free(channel_id);
4115 silc_buffer_free(cidp);
4118 silc_server_command_free(cmd);
4121 /* Server side of CUMODE command. Changes client's mode on a channel. */
4123 SILC_SERVER_CMD_FUNC(cumode)
4125 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4126 SilcServer server = cmd->server;
4127 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4128 SilcIDListData idata = (SilcIDListData)client;
4129 SilcChannelID *channel_id;
4130 SilcClientID *client_id;
4131 SilcChannelEntry channel;
4132 SilcClientEntry target_client;
4133 SilcChannelClientEntry chl;
4134 SilcBuffer packet, idp;
4135 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4136 uint32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4138 uint16 ident = silc_command_get_ident(cmd->payload);
4140 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4142 /* Get Channel ID */
4143 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4145 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4146 SILC_STATUS_ERR_NO_CHANNEL_ID);
4149 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
4151 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4152 SILC_STATUS_ERR_NO_CHANNEL_ID);
4156 /* Get channel entry */
4157 channel = silc_idlist_find_channel_by_id(server->local_list,
4160 channel = silc_idlist_find_channel_by_id(server->global_list,
4163 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4164 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4169 /* Check whether sender is on the channel */
4170 if (!silc_server_client_on_channel(client, channel)) {
4171 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4172 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4176 /* Check that client has rights to change other's rights */
4177 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4178 sender_mask = chl->mode;
4180 /* Get the target client's channel mode mask */
4181 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4183 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4184 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4187 SILC_GET32_MSB(target_mask, tmp_mask);
4189 /* Get target Client ID */
4190 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4192 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4193 SILC_STATUS_ERR_NO_CLIENT_ID);
4196 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
4198 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4199 SILC_STATUS_ERR_NO_CLIENT_ID);
4203 /* Get target client's entry */
4204 target_client = silc_idlist_find_client_by_id(server->local_list,
4205 client_id, TRUE, NULL);
4206 if (!target_client) {
4207 target_client = silc_idlist_find_client_by_id(server->global_list,
4208 client_id, TRUE, NULL);
4211 if (target_client != client &&
4212 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4213 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4214 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4215 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4219 /* Check whether target client is on the channel */
4220 if (target_client != client) {
4221 if (!silc_server_client_on_channel(target_client, channel)) {
4222 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4223 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4227 /* Get entry to the channel user list */
4228 silc_hash_table_find(channel->user_list, target_client, NULL,
4236 /* If the target client is founder, no one else can change their mode
4238 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
4239 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4240 SILC_STATUS_ERR_NOT_YOU);
4244 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4245 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4246 /* The client tries to claim the founder rights. */
4247 unsigned char *tmp_auth;
4248 uint32 tmp_auth_len, auth_len;
4251 if (target_client != client) {
4252 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4253 SILC_STATUS_ERR_NOT_YOU);
4257 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4258 !channel->founder_key || !idata->public_key ||
4259 !silc_pkcs_public_key_compare(channel->founder_key,
4260 idata->public_key)) {
4261 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4262 SILC_STATUS_ERR_NOT_YOU);
4266 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4268 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4269 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4273 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4274 (void *)channel->founder_passwd : (void *)channel->founder_key);
4275 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4276 channel->founder_passwd_len : 0);
4278 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4279 channel->founder_method, auth, auth_len,
4280 idata->hash, client->id, SILC_ID_CLIENT)) {
4281 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4282 SILC_STATUS_ERR_AUTH_FAILED);
4286 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4290 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4291 if (target_client == client) {
4292 /* Remove channel founder rights from itself */
4293 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4296 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4297 SILC_STATUS_ERR_NOT_YOU);
4303 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4304 /* Promote to operator */
4305 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4306 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4307 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4308 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4309 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4313 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4317 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4318 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4319 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4320 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4321 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4325 /* Demote to normal user */
4326 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4331 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4332 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4334 /* Send notify to channel, notify only if mode was actually changed. */
4336 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4337 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4338 idp->data, idp->len,
4342 /* Set CUMODE notify type to network */
4343 if (!server->standalone)
4344 silc_server_send_notify_cumode(server, server->router->connection,
4345 server->server_type == SILC_ROUTER ?
4346 TRUE : FALSE, channel,
4347 target_mask, client->id,
4352 /* Send command reply to sender */
4353 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4354 SILC_STATUS_OK, ident, 3,
4356 3, tmp_ch_id, tmp_ch_len,
4357 4, tmp_id, tmp_len);
4358 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4359 packet->data, packet->len, FALSE);
4361 silc_buffer_free(packet);
4362 silc_free(channel_id);
4363 silc_free(client_id);
4364 silc_buffer_free(idp);
4367 silc_server_command_free(cmd);
4370 /* Server side of KICK command. Kicks client out of channel. */
4372 SILC_SERVER_CMD_FUNC(kick)
4374 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4375 SilcServer server = cmd->server;
4376 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4377 SilcClientEntry target_client;
4378 SilcChannelID *channel_id;
4379 SilcClientID *client_id;
4380 SilcChannelEntry channel;
4381 SilcChannelClientEntry chl;
4383 uint32 tmp_len, target_idp_len;
4384 unsigned char *tmp, *comment, *target_idp;
4386 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4388 /* Get Channel ID */
4389 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4391 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4392 SILC_STATUS_ERR_NO_CHANNEL_ID);
4395 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
4397 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4398 SILC_STATUS_ERR_NO_CHANNEL_ID);
4402 /* Get channel entry */
4403 channel = silc_idlist_find_channel_by_id(server->local_list,
4406 channel = silc_idlist_find_channel_by_id(server->local_list,
4409 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4410 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4415 /* Check whether sender is on the channel */
4416 if (!silc_server_client_on_channel(client, channel)) {
4417 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4418 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4422 /* Check that the kicker is channel operator or channel founder */
4423 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4424 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4425 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4426 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4430 /* Get target Client ID */
4431 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4433 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4434 SILC_STATUS_ERR_NO_CLIENT_ID);
4437 client_id = silc_id_payload_parse_id(target_idp, target_idp_len);
4439 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4440 SILC_STATUS_ERR_NO_CLIENT_ID);
4444 /* Get target client's entry */
4445 target_client = silc_idlist_find_client_by_id(server->local_list,
4446 client_id, TRUE, NULL);
4447 if (!target_client) {
4448 target_client = silc_idlist_find_client_by_id(server->global_list,
4449 client_id, TRUE, NULL);
4452 /* Check that the target client is not channel founder. Channel founder
4453 cannot be kicked from the channel. */
4454 silc_hash_table_find(channel->user_list, target_client, NULL, (void *)&chl);
4455 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4456 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4457 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4461 /* Check whether target client is on the channel */
4462 if (!silc_server_client_on_channel(target_client, channel)) {
4463 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4464 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4470 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4474 /* Send command reply to sender */
4475 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4478 /* Send KICKED notify to local clients on the channel */
4479 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4480 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4481 SILC_NOTIFY_TYPE_KICKED, 3,
4482 target_idp, target_idp_len,
4483 comment, comment ? strlen(comment) : 0,
4484 idp->data, idp->len);
4485 silc_buffer_free(idp);
4487 /* Remove the client from the channel. If the channel does not exist
4488 after removing the client then the client kicked itself off the channel
4489 and we don't have to send anything after that. */
4490 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4491 target_client, FALSE))
4494 /* Send KICKED notify to primary route */
4495 if (!server->standalone)
4496 silc_server_send_notify_kicked(server, server->router->connection,
4497 server->server_type == SILC_ROUTER ?
4498 TRUE : FALSE, channel,
4499 target_client->id, comment);
4501 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4502 /* Re-generate channel key */
4503 if (!silc_server_create_channel_key(server, channel, 0))
4506 /* Send the channel key to the channel. The key of course is not sent
4507 to the client who was kicked off the channel. */
4508 silc_server_send_channel_key(server, target_client->connection, channel,
4509 server->server_type == SILC_ROUTER ?
4510 FALSE : !server->standalone);
4514 silc_server_command_free(cmd);
4517 /* Server side of OPER command. Client uses this comand to obtain server
4518 operator privileges to this server/router. */
4520 SILC_SERVER_CMD_FUNC(oper)
4522 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4523 SilcServer server = cmd->server;
4524 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4525 unsigned char *username, *auth;
4527 SilcServerConfigSectionAdminConnection *admin;
4528 SilcIDListData idata = (SilcIDListData)client;
4530 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4532 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4535 /* Get the username */
4536 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4538 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4539 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4543 /* Get the admin configuration */
4544 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4545 username, client->nickname);
4547 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4548 username, client->nickname);
4550 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4551 SILC_STATUS_ERR_AUTH_FAILED);
4556 /* Get the authentication payload */
4557 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4559 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4560 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4564 /* Verify the authentication data */
4565 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4566 admin->auth_data, admin->auth_data_len,
4567 idata->hash, client->id, SILC_ID_CLIENT)) {
4568 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4569 SILC_STATUS_ERR_AUTH_FAILED);
4573 /* Client is now server operator */
4574 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4576 /* Send UMODE change to primary router */
4577 if (!server->standalone)
4578 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4579 client->id, client->mode);
4581 /* Send reply to the sender */
4582 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4586 silc_server_command_free(cmd);
4589 /* Server side of SILCOPER command. Client uses this comand to obtain router
4590 operator privileges to this router. */
4592 SILC_SERVER_CMD_FUNC(silcoper)
4594 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4595 SilcServer server = cmd->server;
4596 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4597 unsigned char *username, *auth;
4599 SilcServerConfigSectionAdminConnection *admin;
4600 SilcIDListData idata = (SilcIDListData)client;
4602 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4604 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4607 if (server->server_type != SILC_ROUTER) {
4608 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4609 SILC_STATUS_ERR_AUTH_FAILED);
4613 /* Get the username */
4614 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4616 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4617 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4621 /* Get the admin configuration */
4622 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4623 username, client->nickname);
4625 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4626 username, client->nickname);
4628 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4629 SILC_STATUS_ERR_AUTH_FAILED);
4634 /* Get the authentication payload */
4635 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4637 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4638 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4642 /* Verify the authentication data */
4643 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4644 admin->auth_data, admin->auth_data_len,
4645 idata->hash, client->id, SILC_ID_CLIENT)) {
4646 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4647 SILC_STATUS_ERR_AUTH_FAILED);
4651 /* Client is now router operator */
4652 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4654 /* Send UMODE change to primary router */
4655 if (!server->standalone)
4656 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4657 client->id, client->mode);
4659 /* Send reply to the sender */
4660 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4664 silc_server_command_free(cmd);
4667 /* Server side command of CONNECT. Connects us to the specified remote
4668 server or router. */
4670 SILC_SERVER_CMD_FUNC(connect)
4672 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4673 SilcServer server = cmd->server;
4674 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4675 unsigned char *tmp, *host;
4677 uint32 port = SILC_PORT;
4679 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CONNECT, cmd, 1, 2);
4681 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4684 /* Check whether client has the permissions. */
4685 if (client->mode == SILC_UMODE_NONE) {
4686 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4687 SILC_STATUS_ERR_NO_SERVER_PRIV);
4691 if (server->server_type == SILC_ROUTER &&
4692 client->mode & SILC_UMODE_SERVER_OPERATOR) {
4693 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4694 SILC_STATUS_ERR_NO_ROUTER_PRIV);
4698 /* Get the remote server */
4699 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4701 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4702 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4707 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4709 SILC_GET32_MSB(port, tmp);
4711 /* Create the connection. It is done with timeout and is async. */
4712 silc_server_create_connection(server, host, port);
4714 /* Send reply to the sender */
4715 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4719 silc_server_command_free(cmd);
4722 /* Server side of command BAN. This is used to manage the ban list of the
4723 channel. To add clients and remove clients from the ban list. */
4725 SILC_SERVER_CMD_FUNC(ban)
4727 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4728 SilcServer server = cmd->server;
4729 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4731 SilcChannelEntry channel;
4732 SilcChannelClientEntry chl;
4733 SilcChannelID *channel_id = NULL;
4734 unsigned char *id, *add, *del;
4735 uint32 id_len, tmp_len;
4736 uint16 ident = silc_command_get_ident(cmd->payload);
4738 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4741 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4743 /* Get Channel ID */
4744 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4746 channel_id = silc_id_payload_parse_id(id, id_len);
4748 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4749 SILC_STATUS_ERR_NO_CHANNEL_ID);
4754 /* Get channel entry. The server must know about the channel since the
4755 client is expected to be on the channel. */
4756 channel = silc_idlist_find_channel_by_id(server->local_list,
4759 channel = silc_idlist_find_channel_by_id(server->global_list,
4762 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4763 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4768 /* Check whether this client is on the channel */
4769 if (!silc_server_client_on_channel(client, channel)) {
4770 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4771 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4775 /* Get entry to the channel user list */
4776 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4778 /* The client must be at least channel operator. */
4779 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4780 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4781 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4785 /* Get the new ban and add it to the ban list */
4786 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4788 if (!channel->ban_list)
4789 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4791 channel->ban_list = silc_realloc(channel->ban_list,
4792 sizeof(*channel->ban_list) *
4794 strlen(channel->ban_list) + 2));
4795 if (add[tmp_len - 1] == ',')
4796 add[tmp_len - 1] = '\0';
4798 strncat(channel->ban_list, add, tmp_len);
4799 strncat(channel->ban_list, ",", 1);
4802 /* Get the ban to be removed and remove it from the list */
4803 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4804 if (del && channel->ban_list) {
4805 char *start, *end, *n;
4807 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4808 silc_free(channel->ban_list);
4809 channel->ban_list = NULL;
4811 start = strstr(channel->ban_list, del);
4812 if (start && strlen(start) >= tmp_len) {
4813 end = start + tmp_len;
4814 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4815 strncat(n, channel->ban_list, start - channel->ban_list);
4816 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4818 silc_free(channel->ban_list);
4819 channel->ban_list = n;
4824 /* Send the BAN notify type to our primary router. */
4825 if (!server->standalone && (add || del))
4826 silc_server_send_notify_ban(server, server->router->connection,
4827 server->server_type == SILC_ROUTER ?
4828 TRUE : FALSE, channel, add, del);
4830 /* Send the reply back to the client */
4832 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4833 SILC_STATUS_OK, ident, 2,
4835 3, channel->ban_list,
4837 strlen(channel->ban_list) - 1 : 0);
4838 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4839 packet->data, packet->len, FALSE);
4841 silc_buffer_free(packet);
4844 silc_free(channel_id);
4845 silc_server_command_free(cmd);
4848 /* Server side command of CLOSE. Closes connection to a specified server. */
4850 SILC_SERVER_CMD_FUNC(close)
4852 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4853 SilcServer server = cmd->server;
4854 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4855 SilcServerEntry server_entry;
4856 SilcSocketConnection sock;
4859 unsigned char *name;
4860 uint32 port = SILC_PORT;
4862 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CLOSE, cmd, 1, 2);
4864 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4867 /* Check whether client has the permissions. */
4868 if (client->mode == SILC_UMODE_NONE) {
4869 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4870 SILC_STATUS_ERR_NO_SERVER_PRIV);
4874 /* Get the remote server */
4875 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4877 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4878 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4883 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4885 SILC_GET32_MSB(port, tmp);
4887 server_entry = silc_idlist_find_server_by_conn(server->local_list,
4888 name, port, FALSE, NULL);
4890 server_entry = silc_idlist_find_server_by_conn(server->global_list,
4891 name, port, FALSE, NULL);
4892 if (!server_entry) {
4893 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4894 SILC_STATUS_ERR_NO_SERVER_ID);
4898 /* Send reply to the sender */
4899 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4902 /* Close the connection to the server */
4903 sock = (SilcSocketConnection)server_entry->connection;
4905 /* If we shutdown primary router connection manually then don't trigger
4906 any reconnect or backup router connections, by setting the router
4908 if (server->router == server_entry) {
4909 server->id_entry->router = NULL;
4910 server->router = NULL;
4911 server->standalone = TRUE;
4913 silc_server_free_sock_user_data(server, sock);
4914 silc_server_close_connection(server, sock);
4917 silc_server_command_free(cmd);
4920 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4921 active connections. */
4923 SILC_SERVER_CMD_FUNC(shutdown)
4925 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4926 SilcServer server = cmd->server;
4927 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4929 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4931 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4934 /* Check whether client has the permission. */
4935 if (client->mode == SILC_UMODE_NONE) {
4936 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4937 SILC_STATUS_ERR_NO_SERVER_PRIV);
4941 /* Send reply to the sender */
4942 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4945 /* Then, gracefully, or not, bring the server down. */
4946 silc_server_stop(server);
4950 silc_server_command_free(cmd);
4953 /* Server side command of LEAVE. Removes client from a channel. */
4955 SILC_SERVER_CMD_FUNC(leave)
4957 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4958 SilcServer server = cmd->server;
4959 SilcSocketConnection sock = cmd->sock;
4960 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4961 SilcChannelID *id = NULL;
4962 SilcChannelEntry channel;
4966 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4968 /* Get Channel ID */
4969 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4971 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4972 SILC_STATUS_ERR_NO_CHANNEL_ID);
4975 id = silc_id_payload_parse_id(tmp, len);
4977 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4978 SILC_STATUS_ERR_NO_CHANNEL_ID);
4982 /* Get channel entry */
4983 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4985 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4987 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4988 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4993 /* Check whether this client is on the channel */
4994 if (!silc_server_client_on_channel(id_entry, channel)) {
4995 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4996 SILC_STATUS_ERR_NOT_ON_CHANNEL);
5000 /* Notify routers that they should remove this client from their list
5001 of clients on the channel. Send LEAVE notify type. */
5002 if (!server->standalone)
5003 silc_server_send_notify_leave(server, server->router->connection,
5004 server->server_type == SILC_ROUTER ?
5005 TRUE : FALSE, channel, id_entry->id);
5007 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5010 /* Remove client from channel */
5011 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5013 /* If the channel does not exist anymore we won't send anything */
5016 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5017 /* Re-generate channel key */
5018 if (!silc_server_create_channel_key(server, channel, 0))
5021 /* Send the channel key */
5022 silc_server_send_channel_key(server, NULL, channel,
5023 server->server_type == SILC_ROUTER ?
5024 FALSE : !server->standalone);
5029 silc_server_command_free(cmd);
5032 /* Server side of command USERS. Resolves clients and their USERS currently
5033 joined on the requested channel. The list of Client ID's and their modes
5034 on the channel is sent back. */
5036 SILC_SERVER_CMD_FUNC(users)
5038 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5039 SilcServer server = cmd->server;
5040 SilcChannelEntry channel;
5041 SilcChannelID *id = NULL;
5042 SilcBuffer packet, idp;
5043 unsigned char *channel_id;
5044 uint32 channel_id_len;
5045 SilcBuffer client_id_list;
5046 SilcBuffer client_mode_list;
5047 unsigned char lc[4];
5048 uint32 list_count = 0;
5049 uint16 ident = silc_command_get_ident(cmd->payload);
5052 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5054 /* Get Channel ID */
5055 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5057 /* Get channel name */
5058 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5060 if (!channel_id && !channel_name) {
5061 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5062 SILC_STATUS_ERR_NO_CHANNEL_ID);
5067 id = silc_id_payload_parse_id(channel_id, channel_id_len);
5069 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5070 SILC_STATUS_ERR_NO_CHANNEL_ID);
5075 /* If we are server and we don't know about this channel we will send
5076 the command to our router. If we know about the channel then we also
5077 have the list of users already. */
5079 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5081 channel = silc_idlist_find_channel_by_name(server->local_list,
5082 channel_name, NULL);
5084 if (!channel || channel->disabled) {
5085 if (server->server_type != SILC_ROUTER && !server->standalone &&
5089 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5090 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5092 /* Send USERS command */
5093 silc_server_packet_send(server, server->router->connection,
5094 SILC_PACKET_COMMAND, cmd->packet->flags,
5095 tmpbuf->data, tmpbuf->len, TRUE);
5097 /* Reprocess this packet after received reply */
5098 silc_server_command_pending(server, SILC_COMMAND_USERS,
5099 silc_command_get_ident(cmd->payload),
5100 silc_server_command_destructor,
5101 silc_server_command_users,
5102 silc_server_command_dup(cmd));
5103 cmd->pending = TRUE;
5104 silc_command_set_ident(cmd->payload, ident);
5106 silc_buffer_free(tmpbuf);
5111 /* Check the global list as well. */
5113 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5115 channel = silc_idlist_find_channel_by_name(server->global_list,
5116 channel_name, NULL);
5118 /* Channel really does not exist */
5119 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5120 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5125 /* If the channel is private or secret do not send anything, unless the
5126 user requesting this command is on the channel. */
5127 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5128 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5129 && !silc_server_client_on_channel(cmd->sock->user_data, channel)) {
5130 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5131 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5136 (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
5137 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5138 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5143 /* Get the users list */
5144 silc_server_get_users_on_channel(server, channel, &client_id_list,
5145 &client_mode_list, &list_count);
5148 SILC_PUT32_MSB(list_count, lc);
5151 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5152 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5153 SILC_STATUS_OK, ident, 4,
5154 2, idp->data, idp->len,
5156 4, client_id_list->data,
5157 client_id_list->len,
5158 5, client_mode_list->data,
5159 client_mode_list->len);
5160 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5161 packet->data, packet->len, FALSE);
5163 silc_buffer_free(idp);
5164 silc_buffer_free(packet);
5165 silc_buffer_free(client_id_list);
5166 silc_buffer_free(client_mode_list);
5170 silc_server_command_free(cmd);
5173 /* Server side of command GETKEY. This fetches the client's public key
5174 from the server where to the client is connected. */
5176 SILC_SERVER_CMD_FUNC(getkey)
5178 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5179 SilcServer server = cmd->server;
5181 SilcClientEntry client;
5182 SilcServerEntry server_entry;
5183 SilcClientID *client_id = NULL;
5184 SilcServerID *server_id = NULL;
5185 SilcIDPayload idp = NULL;
5186 uint16 ident = silc_command_get_ident(cmd->payload);
5187 unsigned char *tmp, *pkdata;
5188 uint32 tmp_len, pklen;
5189 SilcBuffer pk = NULL;
5192 SILC_LOG_DEBUG(("Start"));
5194 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5196 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5197 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5200 idp = silc_id_payload_parse(tmp, tmp_len);
5202 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5203 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5207 id_type = silc_id_payload_get_type(idp);
5208 if (id_type == SILC_ID_CLIENT) {
5209 client_id = silc_id_payload_get_id(idp);
5211 /* If the client is not found from local list there is no chance it
5212 would be locally connected client so send the command further. */
5213 client = silc_idlist_find_client_by_id(server->local_list,
5214 client_id, TRUE, NULL);
5216 client = silc_idlist_find_client_by_id(server->global_list,
5217 client_id, TRUE, NULL);
5219 if ((!client && !cmd->pending && !server->standalone) ||
5220 (client && !client->connection && !cmd->pending) ||
5221 (client && !client->data.public_key && !cmd->pending)) {
5224 SilcSocketConnection dest_sock;
5226 dest_sock = silc_server_get_client_route(server, NULL, 0,
5231 old_ident = silc_command_get_ident(cmd->payload);
5232 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5233 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5235 silc_server_packet_send(server, dest_sock,
5236 SILC_PACKET_COMMAND, cmd->packet->flags,
5237 tmpbuf->data, tmpbuf->len, TRUE);
5239 /* Reprocess this packet after received reply from router */
5240 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5241 silc_command_get_ident(cmd->payload),
5242 silc_server_command_destructor,
5243 silc_server_command_getkey,
5244 silc_server_command_dup(cmd));
5245 cmd->pending = TRUE;
5247 silc_command_set_ident(cmd->payload, old_ident);
5248 silc_buffer_free(tmpbuf);
5253 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5254 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5258 /* The client is locally connected, just get the public key and
5259 send it back. If they key does not exist then do not send it,
5260 send just OK reply */
5261 if (!client->data.public_key) {
5265 tmp = silc_pkcs_public_key_encode(client->data.public_key, &tmp_len);
5266 pk = silc_buffer_alloc(4 + tmp_len);
5267 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5268 silc_buffer_format(pk,
5269 SILC_STR_UI_SHORT(tmp_len),
5270 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5271 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5277 } else if (id_type == SILC_ID_SERVER) {
5278 server_id = silc_id_payload_get_id(idp);
5280 /* If the server is not found from local list there is no chance it
5281 would be locally connected server so send the command further. */
5282 server_entry = silc_idlist_find_server_by_id(server->local_list,
5283 server_id, TRUE, NULL);
5285 server_entry = silc_idlist_find_server_by_id(server->global_list,
5286 server_id, TRUE, NULL);
5288 if (server_entry != server->id_entry &&
5289 ((!server_entry && !cmd->pending && !server->standalone) ||
5290 (server_entry && !server_entry->connection && !cmd->pending &&
5291 !server->standalone) ||
5292 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5293 !server->standalone))) {
5297 old_ident = silc_command_get_ident(cmd->payload);
5298 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5299 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5301 silc_server_packet_send(server, server->router->connection,
5302 SILC_PACKET_COMMAND, cmd->packet->flags,
5303 tmpbuf->data, tmpbuf->len, TRUE);
5305 /* Reprocess this packet after received reply from router */
5306 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5307 silc_command_get_ident(cmd->payload),
5308 silc_server_command_destructor,
5309 silc_server_command_getkey,
5310 silc_server_command_dup(cmd));
5311 cmd->pending = TRUE;
5313 silc_command_set_ident(cmd->payload, old_ident);
5314 silc_buffer_free(tmpbuf);
5318 if (!server_entry) {
5319 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5320 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5324 /* If they key does not exist then do not send it, send just OK reply */
5325 if (!server_entry->data.public_key) {
5329 tmp = silc_pkcs_public_key_encode(server_entry->data.public_key,
5331 pk = silc_buffer_alloc(4 + tmp_len);
5332 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5333 silc_buffer_format(pk,
5334 SILC_STR_UI_SHORT(tmp_len),
5335 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5336 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5346 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5347 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5348 SILC_STATUS_OK, ident,
5352 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5353 packet->data, packet->len, FALSE);
5354 silc_buffer_free(packet);
5357 silc_buffer_free(pk);
5361 silc_id_payload_free(idp);
5362 silc_free(client_id);
5363 silc_free(server_id);
5364 silc_server_command_free(cmd);