5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2001 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
22 #include "serverincludes.h"
23 #include "server_internal.h"
25 static int silc_server_is_registered(SilcServer server,
26 SilcSocketConnection sock,
27 SilcServerCommandContext cmd,
30 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
32 SilcCommandStatus status);
34 silc_server_command_send_status_data(SilcServerCommandContext cmd,
36 SilcCommandStatus status,
38 const unsigned char *arg,
41 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
42 SilcServerCommandReplyContext cmdr,
44 SILC_TASK_CALLBACK(silc_server_command_process_timeout);
46 /* Server command list. */
47 SilcServerCommand silc_command_list[] =
49 SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
50 SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
51 SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
52 SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
53 SILC_SERVER_CMD(list, LIST, SILC_CF_LAG_STRICT | SILC_CF_REG),
54 SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
55 SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
56 SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
57 SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG_STRICT | SILC_CF_REG | SILC_CF_OPER),
58 SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
59 SILC_SERVER_CMD(connect, CONNECT,
60 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
61 SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
62 SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
63 SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG_STRICT | SILC_CF_REG),
64 SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
65 SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
66 SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG_STRICT | SILC_CF_REG),
67 SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
68 SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
69 SILC_SERVER_CMD(ban, BAN, SILC_CF_LAG_STRICT | SILC_CF_REG),
70 SILC_SERVER_CMD(close, CLOSE,
71 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
72 SILC_SERVER_CMD(shutdown, SHUTDOWN, SILC_CF_LAG | SILC_CF_REG |
74 SILC_SERVER_CMD(silcoper, SILCOPER,
75 SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
76 SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
77 SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
78 SILC_SERVER_CMD(getkey, GETKEY, SILC_CF_LAG | SILC_CF_REG),
83 /* Performs several checks to the command. It first checks whether this
84 command was called as pending command callback. If it was then it checks
85 whether error occurred in the command reply where the pending command
88 It also checks that the requested command includes correct amount
90 #define SILC_SERVER_COMMAND_CHECK(command, context, min, max) \
94 SILC_LOG_DEBUG(("Start")); \
96 if (silc_server_command_pending_error_check(cmd, context2, command)) { \
97 silc_server_command_free(cmd); \
101 _argc = silc_argument_get_arg_num(cmd->args); \
103 silc_server_command_send_status_reply(cmd, command, \
104 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
105 silc_server_command_free(cmd); \
109 silc_server_command_send_status_reply(cmd, command, \
110 SILC_STATUS_ERR_TOO_MANY_PARAMS); \
111 silc_server_command_free(cmd); \
116 /* Returns TRUE if the connection is registered. Unregistered connections
117 usually cannot send commands hence the check. */
119 static int silc_server_is_registered(SilcServer server,
120 SilcSocketConnection sock,
121 SilcServerCommandContext cmd,
124 SilcIDListData idata = (SilcIDListData)sock->user_data;
129 if (idata->status & SILC_IDLIST_STATUS_REGISTERED)
132 silc_server_command_send_status_reply(cmd, command,
133 SILC_STATUS_ERR_NOT_REGISTERED);
134 silc_server_command_free(cmd);
138 /* Internal context to hold data when executed command with timeout. */
140 SilcServerCommandContext ctx;
141 SilcServerCommand *cmd;
142 } *SilcServerCommandTimeout;
144 /* Timeout callback to process commands with timeout for client. Client's
145 commands are always executed with timeout. */
147 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
149 SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
150 SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data;
152 /* Update access time */
153 client->last_command = time(NULL);
155 if (!(timeout->cmd->flags & SILC_CF_REG))
156 timeout->cmd->cb(timeout->ctx, NULL);
157 else if (silc_server_is_registered(timeout->ctx->server,
161 timeout->cmd->cb(timeout->ctx, NULL);
166 /* Processes received command packet. */
168 void silc_server_command_process(SilcServer server,
169 SilcSocketConnection sock,
170 SilcPacketContext *packet)
172 SilcServerCommandContext ctx;
173 SilcServerCommand *cmd;
176 /* Allocate command context. This must be free'd by the
177 command routine receiving it. */
178 ctx = silc_server_command_alloc();
179 ctx->server = server;
180 ctx->sock = silc_socket_dup(sock);
181 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
183 /* Parse the command payload in the packet */
184 ctx->payload = silc_command_payload_parse(packet->buffer->data,
185 packet->buffer->len);
187 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
188 silc_buffer_free(packet->buffer);
189 silc_packet_context_free(packet);
190 silc_socket_free(ctx->sock);
194 ctx->args = silc_command_get_args(ctx->payload);
196 /* Get the command */
197 command = silc_command_get(ctx->payload);
198 for (cmd = silc_command_list; cmd->cb; cmd++)
199 if (cmd->cmd == command)
203 silc_server_command_send_status_reply(ctx, command,
204 SILC_STATUS_ERR_UNKNOWN_COMMAND);
205 silc_server_command_free(ctx);
209 /* Execute client's commands always with timeout. Normally they are
210 executed with zero (0) timeout but if client is sending command more
211 frequently than once in 2 seconds, then the timeout may be 0 to 2
213 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
214 SilcClientEntry client = (SilcClientEntry)sock->user_data;
215 SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
221 if (client->last_command && (time(NULL) - client->last_command) < 2) {
222 client->fast_command++;
225 client->fast_command = ((client->fast_command - 1) <= 0 ? 0 :
226 client->fast_command--);
230 if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
231 (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
232 silc_schedule_task_add(server->schedule, sock->sock,
233 silc_server_command_process_timeout,
235 2 - (time(NULL) - client->last_command), 0,
237 SILC_TASK_PRI_NORMAL);
239 silc_schedule_task_add(server->schedule, sock->sock,
240 silc_server_command_process_timeout,
244 SILC_TASK_PRI_NORMAL);
248 /* Execute for server */
250 if (!(cmd->flags & SILC_CF_REG))
252 else if (silc_server_is_registered(server, sock, ctx, cmd->cmd))
256 /* Allocate Command Context */
258 SilcServerCommandContext silc_server_command_alloc()
260 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
265 /* Free's the command context allocated before executing the command */
267 void silc_server_command_free(SilcServerCommandContext ctx)
270 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
272 if (ctx->users < 1) {
274 silc_command_payload_free(ctx->payload);
276 silc_packet_context_free(ctx->packet);
278 silc_socket_free(ctx->sock); /* Decrease reference counter */
283 /* Duplicate Command Context by adding reference counter. The context won't
284 be free'd untill it hits zero. */
286 SilcServerCommandContext
287 silc_server_command_dup(SilcServerCommandContext ctx)
290 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
295 /* Add new pending command to be executed when reply to a command has been
296 received. The `reply_cmd' is the command that will call the `callback'
297 with `context' when reply has been received. It can be SILC_COMMAND_NONE
298 to match any command with the `ident'. If `ident' is non-zero
299 the `callback' will be executed when received reply with command
300 identifier `ident'. If there already exists pending command for the
301 specified command, ident, callback and context this function has no
304 bool silc_server_command_pending(SilcServer server,
305 SilcCommand reply_cmd,
307 SilcServerPendingDestructor destructor,
308 SilcCommandCb callback,
311 SilcServerCommandPending *reply;
313 /* Check whether identical pending already exists for same command,
314 ident, callback and callback context. If it does then it would be
315 error to register it again. */
316 silc_dlist_start(server->pending_commands);
317 while ((reply = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
318 if (reply->reply_cmd == reply_cmd && reply->ident == ident &&
319 reply->callback == callback && reply->context == context)
323 reply = silc_calloc(1, sizeof(*reply));
324 reply->reply_cmd = reply_cmd;
325 reply->ident = ident;
326 reply->context = context;
327 reply->callback = callback;
328 reply->destructor = destructor;
329 silc_dlist_add(server->pending_commands, reply);
334 /* Deletes pending command by reply command type. */
336 void silc_server_command_pending_del(SilcServer server,
337 SilcCommand reply_cmd,
340 SilcServerCommandPending *r;
342 silc_dlist_start(server->pending_commands);
343 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
344 if (r->reply_cmd == reply_cmd && r->ident == ident) {
345 silc_dlist_del(server->pending_commands, r);
351 /* Checks for pending commands and marks callbacks to be called from
352 the command reply function. Returns TRUE if there were pending command. */
354 SilcServerCommandPendingCallbacks
355 silc_server_command_pending_check(SilcServer server,
356 SilcServerCommandReplyContext ctx,
359 uint32 *callbacks_count)
361 SilcServerCommandPending *r;
362 SilcServerCommandPendingCallbacks callbacks = NULL;
365 silc_dlist_start(server->pending_commands);
366 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
367 if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE)
368 && r->ident == ident) {
369 callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
370 callbacks[i].context = r->context;
371 callbacks[i].callback = r->callback;
372 callbacks[i].destructor = r->destructor;
378 *callbacks_count = i;
382 /* Destructor function for pending callbacks. This is called when using
383 pending commands to free the context given for the pending command. */
385 static void silc_server_command_destructor(void *context)
387 silc_server_command_free((SilcServerCommandContext)context);
390 /* Sends simple status message as command reply packet */
393 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
395 SilcCommandStatus status)
399 SILC_LOG_DEBUG(("Sending command status %d", status));
402 silc_command_reply_payload_encode_va(command, status,
403 silc_command_get_ident(cmd->payload),
405 silc_server_packet_send(cmd->server, cmd->sock,
406 SILC_PACKET_COMMAND_REPLY, 0,
407 buffer->data, buffer->len, FALSE);
408 silc_buffer_free(buffer);
411 /* Sends command status reply with one extra argument. The argument
412 type must be sent as argument. */
415 silc_server_command_send_status_data(SilcServerCommandContext cmd,
417 SilcCommandStatus status,
419 const unsigned char *arg,
424 SILC_LOG_DEBUG(("Sending command status %d", status));
427 silc_command_reply_payload_encode_va(command, status,
428 silc_command_get_ident(cmd->payload),
429 1, arg_type, arg, arg_len);
430 silc_server_packet_send(cmd->server, cmd->sock,
431 SILC_PACKET_COMMAND_REPLY, 0,
432 buffer->data, buffer->len, FALSE);
433 silc_buffer_free(buffer);
436 /* This function can be called to check whether in the command reply
437 an error occurred. This function has no effect if this is called
438 when the command function was not called as pending command callback.
439 This returns TRUE if error had occurred. */
442 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
443 SilcServerCommandReplyContext cmdr,
446 SilcCommandStatus status;
448 if (!cmd->pending || !cmdr)
451 SILC_GET16_MSB(status, silc_argument_get_arg_type(cmdr->args, 1, NULL));
452 if (status != SILC_STATUS_OK &&
453 status != SILC_STATUS_LIST_START &&
454 status != SILC_STATUS_LIST_ITEM &&
455 status != SILC_STATUS_LIST_END) {
458 /* Send the same command reply payload */
459 silc_command_set_ident(cmdr->payload,
460 silc_command_get_ident(cmd->payload));
461 buffer = silc_command_payload_encode_payload(cmdr->payload);
462 silc_server_packet_send(cmd->server, cmd->sock,
463 SILC_PACKET_COMMAND_REPLY, 0,
464 buffer->data, buffer->len, FALSE);
465 silc_buffer_free(buffer);
472 /******************************************************************************
476 ******************************************************************************/
479 silc_server_command_whois_parse(SilcServerCommandContext cmd,
480 SilcClientID ***client_id,
481 uint32 *client_id_count,
489 uint32 argc = silc_argument_get_arg_num(cmd->args);
492 /* If client ID is in the command it must be used instead of nickname */
493 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
495 /* No ID, get the nickname@server string and parse it. */
496 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
498 silc_parse_userfqdn(tmp, nickname, server_name);
500 silc_server_command_send_status_reply(cmd, command,
501 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
505 /* Command includes ID, we must use that. Also check whether the command
506 has more than one ID set - take them all. */
508 *client_id = silc_calloc(1, sizeof(**client_id));
509 (*client_id)[0] = silc_id_payload_parse_id(tmp, len);
510 if ((*client_id)[0] == NULL) {
511 silc_free(*client_id);
514 *client_id_count = 1;
516 /* Take all ID's from the command packet */
518 for (k = 1, i = 1; i < argc; i++) {
519 tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
521 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
522 (*client_id_count + 1));
523 (*client_id)[k] = silc_id_payload_parse_id(tmp, len);
524 if ((*client_id)[k] == NULL) {
525 /* Cleanup all and fail */
526 for (i = 0; i < *client_id_count; i++)
527 silc_free((*client_id)[i]);
528 silc_free(*client_id);
531 (*client_id_count)++;
538 /* Get the max count of reply messages allowed */
539 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
548 /* Resolve context used by both WHOIS and IDENTIFY commands */
550 SilcServerEntry router;
552 unsigned char **res_argv;
553 uint32 *res_argv_lens;
554 uint32 *res_argv_types;
556 } *SilcServerResolveContext;
559 silc_server_command_whois_check(SilcServerCommandContext cmd,
560 SilcClientEntry *clients,
561 uint32 clients_count)
563 SilcServer server = cmd->server;
564 SilcClientEntry entry;
565 SilcServerResolveContext resolve = NULL, r = NULL;
566 uint32 resolve_count = 0;
570 for (i = 0; i < clients_count; i++) {
575 if ((entry->nickname && entry->username && entry->userinfo) ||
576 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
580 /* If we are normal server, and we've not resolved this client from
581 router and it is global client, we'll check whether it is on some
582 channel. If not then we cannot be sure about its validity, and
583 we'll resolve it from router. */
584 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
585 entry->connection || silc_hash_table_count(entry->channels))
589 /* We need to resolve this entry since it is not complete */
591 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
592 /* The entry is being resolved (and we are not the resolver) so attach
593 to the command reply and we're done with this one. */
594 silc_server_command_pending(server, SILC_COMMAND_NONE,
595 entry->resolve_cmd_ident,
596 silc_server_command_destructor,
597 silc_server_command_whois,
598 silc_server_command_dup(cmd));
601 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
602 /* We've resolved this and it still is not ready. We'll return
603 and are that this will be handled again after it is resolved. */
604 for (i = 0; i < resolve_count; i++) {
605 for (k = 0; k < r->res_argc; k++)
606 silc_free(r->res_argv[k]);
607 silc_free(r->res_argv);
608 silc_free(r->res_argv_lens);
609 silc_free(r->res_argv_types);
614 /* We'll resolve this client */
618 for (k = 0; k < resolve_count; k++) {
619 if (resolve[k].router == entry->router) {
626 resolve = silc_realloc(resolve, sizeof(*resolve) *
627 (resolve_count + 1));
628 r = &resolve[resolve_count];
629 memset(r, 0, sizeof(*r));
630 r->router = entry->router;
631 r->ident = ++server->cmd_ident;
635 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
637 r->res_argv_lens = silc_realloc(r->res_argv_lens,
638 sizeof(*r->res_argv_lens) *
640 r->res_argv_types = silc_realloc(r->res_argv_types,
641 sizeof(*r->res_argv_types) *
643 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
644 r->res_argv[r->res_argc] = silc_calloc(idp->len,
645 sizeof(**r->res_argv));
646 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
647 r->res_argv_lens[r->res_argc] = idp->len;
648 r->res_argv_types[r->res_argc] = r->res_argc + 3;
650 silc_buffer_free(idp);
652 entry->resolve_cmd_ident = r->ident;
653 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
654 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
659 /* Do the resolving */
660 for (i = 0; i < resolve_count; i++) {
665 /* Send WHOIS request. We send WHOIS since we're doing the requesting
666 now anyway so make it a good one. */
667 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
668 r->res_argc, r->res_argv,
672 silc_server_packet_send(server, r->router->connection,
673 SILC_PACKET_COMMAND, cmd->packet->flags,
674 res_cmd->data, res_cmd->len, FALSE);
676 /* Reprocess this packet after received reply */
677 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
679 silc_server_command_destructor,
680 silc_server_command_whois,
681 silc_server_command_dup(cmd));
684 silc_buffer_free(res_cmd);
685 for (k = 0; k < r->res_argc; k++)
686 silc_free(r->res_argv[k]);
687 silc_free(r->res_argv);
688 silc_free(r->res_argv_lens);
689 silc_free(r->res_argv_types);
698 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
699 SilcClientEntry *clients,
700 uint32 clients_count,
702 const char *nickname,
703 SilcClientID **client_ids)
705 SilcServer server = cmd->server;
707 int i, k, len, valid_count;
708 SilcBuffer packet, idp, channels;
709 SilcClientEntry entry;
710 SilcCommandStatus status;
711 uint16 ident = silc_command_get_ident(cmd->payload);
712 char nh[256], uh[256];
713 unsigned char idle[4], mode[4];
714 unsigned char *fingerprint;
715 SilcSocketConnection hsock;
717 /* Process only valid clients and ignore those that are not registered. */
719 for (i = 0; i < clients_count; i++) {
720 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
727 /* No valid clients found, send error reply */
729 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
730 SILC_STATUS_ERR_NO_SUCH_NICK,
731 3, nickname, strlen(nickname));
732 } else if (client_ids && client_ids[0]) {
733 SilcBuffer idp = silc_id_payload_encode(client_ids[0], SILC_ID_CLIENT);
734 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
735 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
736 2, idp->data, idp->len);
737 silc_buffer_free(idp);
742 /* Start processing found clients. */
744 status = SILC_STATUS_LIST_START;
746 status = SILC_STATUS_OK;
748 for (i = 0, k = 0; i < clients_count; i++) {
754 status = SILC_STATUS_LIST_ITEM;
755 if (valid_count > 1 && k == valid_count - 1)
756 status = SILC_STATUS_LIST_END;
757 if (count && k - 1 == count)
758 status = SILC_STATUS_LIST_END;
760 /* Send WHOIS reply */
761 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
762 tmp = silc_argument_get_first_arg(cmd->args, NULL);
764 memset(uh, 0, sizeof(uh));
765 memset(nh, 0, sizeof(nh));
766 memset(idle, 0, sizeof(idle));
768 strncat(nh, entry->nickname, strlen(entry->nickname));
769 if (!strchr(entry->nickname, '@')) {
771 if (entry->servername) {
772 strncat(nh, entry->servername, strlen(entry->servername));
774 len = entry->router ? strlen(entry->router->server_name) :
775 strlen(server->server_name);
776 strncat(nh, entry->router ? entry->router->server_name :
777 server->server_name, len);
781 strncat(uh, entry->username, strlen(entry->username));
782 if (!strchr(entry->username, '@')) {
784 hsock = (SilcSocketConnection)entry->connection;
785 len = strlen(hsock->hostname);
786 strncat(uh, hsock->hostname, len);
789 channels = silc_server_get_client_channel_list(server, entry);
791 if (entry->data.fingerprint[0] != 0 && entry->data.fingerprint[1] != 0)
792 fingerprint = entry->data.fingerprint;
796 SILC_PUT32_MSB(entry->mode, mode);
798 if (entry->connection) {
799 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
803 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
805 2, idp->data, idp->len,
809 strlen(entry->userinfo),
810 6, channels ? channels->data : NULL,
811 channels ? channels->len : 0,
815 fingerprint ? 20 : 0);
817 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
818 0, packet->data, packet->len, FALSE);
820 silc_buffer_free(packet);
821 silc_buffer_free(idp);
823 silc_buffer_free(channels);
830 silc_server_command_whois_send_router(SilcServerCommandContext cmd)
832 SilcServer server = cmd->server;
836 old_ident = silc_command_get_ident(cmd->payload);
837 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
838 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
840 /* Send WHOIS command to our router */
841 silc_server_packet_send(server, (SilcSocketConnection)
842 server->router->connection,
843 SILC_PACKET_COMMAND, cmd->packet->flags,
844 tmpbuf->data, tmpbuf->len, TRUE);
846 /* Reprocess this packet after received reply from router */
847 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
848 silc_command_get_ident(cmd->payload),
849 silc_server_command_destructor,
850 silc_server_command_whois,
851 silc_server_command_dup(cmd));
853 silc_command_set_ident(cmd->payload, old_ident);
854 silc_buffer_free(tmpbuf);
858 silc_server_command_whois_process(SilcServerCommandContext cmd)
860 SilcServer server = cmd->server;
861 char *nick = NULL, *server_name = NULL;
863 SilcClientEntry *clients = NULL, entry;
864 SilcClientID **client_id = NULL;
865 uint32 client_id_count = 0, clients_count = 0;
867 bool check_global = FALSE;
869 /* Parse the whois request */
870 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
871 &nick, &server_name, &count,
875 /* Send the WHOIS request to the router only if it included nickname.
876 Since nicknames can be expanded into many clients we need to send it
877 to router. If the WHOIS included only client ID's we will check them
878 first locally since we just might have them. */
879 if (nick && !client_id_count && cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
880 server->server_type == SILC_SERVER && !cmd->pending &&
881 !server->standalone) {
882 silc_server_command_whois_send_router(cmd);
887 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
889 else if (server->server_type != SILC_SERVER)
892 /* Get all clients matching that ID or nickname from local list */
893 if (client_id_count) {
894 /* Check all Client ID's received in the command packet */
895 for (i = 0; i < client_id_count; i++) {
896 entry = silc_idlist_find_client_by_id(server->local_list,
897 client_id[i], TRUE, NULL);
898 if (!entry && check_global)
899 entry = silc_idlist_find_client_by_id(server->global_list,
900 client_id[i], TRUE, NULL);
902 clients = silc_realloc(clients, sizeof(*clients) *
903 (clients_count + 1));
904 clients[clients_count++] = entry;
906 /* If we are normal server and did not send the request first to router
907 do it now, since we do not have the Client ID information. */
908 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
909 server->server_type == SILC_SERVER && !cmd->pending &&
910 !server->standalone) {
911 silc_server_command_whois_send_router(cmd);
918 /* Find by nickname */
919 if (!silc_idlist_get_clients_by_hash(server->local_list,
920 nick, server->md5hash,
921 &clients, &clients_count))
922 silc_idlist_get_clients_by_nickname(server->local_list,
924 &clients, &clients_count);
926 if (!silc_idlist_get_clients_by_hash(server->global_list,
927 nick, server->md5hash,
928 &clients, &clients_count))
929 silc_idlist_get_clients_by_nickname(server->global_list,
931 &clients, &clients_count);
936 /* If we are normal server and did not send the request first to router
937 do it now, since we do not have the information. */
938 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
939 server->server_type == SILC_SERVER && !cmd->pending &&
940 !server->standalone) {
941 silc_server_command_whois_send_router(cmd);
946 /* Such client(s) really does not exist in the SILC network. */
947 if (!client_id_count) {
948 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
949 SILC_STATUS_ERR_NO_SUCH_NICK,
950 3, nick, strlen(nick));
952 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
953 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
954 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
955 2, idp->data, idp->len);
956 silc_buffer_free(idp);
961 /* Router always finds the client entry if it exists in the SILC network.
962 However, it might be incomplete entry and does not include all the
963 mandatory fields that WHOIS command reply requires. Check for these and
964 make query from the server who owns the client if some fields are
966 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
971 /* Send the command reply */
972 silc_server_command_whois_send_reply(cmd, clients, clients_count,
973 count, nick, client_id);
976 if (client_id_count) {
977 for (i = 0; i < client_id_count; i++)
978 silc_free(client_id[i]);
979 silc_free(client_id);
983 silc_free(server_name);
988 /* Server side of command WHOIS. Processes user's query and sends found
989 results as command replies back to the client. */
991 SILC_SERVER_CMD_FUNC(whois)
993 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
996 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 3328);
998 ret = silc_server_command_whois_process(cmd);
1001 silc_server_command_free(cmd);
1004 /******************************************************************************
1008 ******************************************************************************/
1011 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
1019 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1021 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
1022 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1026 /* Get the nickname@server string and parse it. */
1027 silc_parse_userfqdn(tmp, nickname, server_name);
1029 /* Get the max count of reply messages allowed */
1030 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1040 silc_server_command_whowas_check(SilcServerCommandContext cmd,
1041 SilcClientEntry *clients,
1042 uint32 clients_count)
1044 SilcServer server = cmd->server;
1046 SilcClientEntry entry;
1048 for (i = 0; i < clients_count; i++) {
1051 if (!entry->nickname || !entry->username) {
1058 old_ident = silc_command_get_ident(cmd->payload);
1059 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1060 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1062 /* Send WHOWAS command */
1063 silc_server_packet_send(server, entry->router->connection,
1064 SILC_PACKET_COMMAND, cmd->packet->flags,
1065 tmpbuf->data, tmpbuf->len, TRUE);
1067 /* Reprocess this packet after received reply */
1068 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1069 silc_command_get_ident(cmd->payload),
1070 silc_server_command_destructor,
1071 silc_server_command_whowas,
1072 silc_server_command_dup(cmd));
1073 cmd->pending = TRUE;
1075 silc_command_set_ident(cmd->payload, old_ident);
1077 silc_buffer_free(tmpbuf);
1086 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1087 SilcClientEntry *clients,
1088 uint32 clients_count)
1090 SilcServer server = cmd->server;
1092 int i, count = 0, len;
1093 SilcBuffer packet, idp;
1094 SilcClientEntry entry = NULL;
1095 SilcCommandStatus status;
1096 uint16 ident = silc_command_get_ident(cmd->payload);
1098 char nh[256], uh[256];
1100 status = SILC_STATUS_OK;
1101 if (clients_count > 1)
1102 status = SILC_STATUS_LIST_START;
1104 for (i = 0; i < clients_count; i++) {
1107 /* We will take only clients that are not valid anymore. They are the
1108 ones that are not registered anymore but still have a ID. They
1109 have disconnected us, and thus valid for WHOWAS. */
1110 if (entry->data.status & SILC_IDLIST_STATUS_REGISTERED || !entry->id)
1113 if (count && i - 1 == count)
1118 if (clients_count > 2)
1119 status = SILC_STATUS_LIST_ITEM;
1120 if (clients_count > 1 && i == clients_count - 1)
1121 status = SILC_STATUS_LIST_END;
1123 /* Send WHOWAS reply */
1124 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1125 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1126 memset(uh, 0, sizeof(uh));
1127 memset(nh, 0, sizeof(nh));
1129 strncat(nh, entry->nickname, strlen(entry->nickname));
1130 if (!strchr(entry->nickname, '@')) {
1131 strncat(nh, "@", 1);
1132 if (entry->servername) {
1133 strncat(nh, entry->servername, strlen(entry->servername));
1135 len = entry->router ? strlen(entry->router->server_name) :
1136 strlen(server->server_name);
1137 strncat(nh, entry->router ? entry->router->server_name :
1138 server->server_name, len);
1142 strncat(uh, entry->username, strlen(entry->username));
1143 if (!strchr(entry->username, '@')) {
1144 strncat(uh, "@", 1);
1145 strcat(uh, "*private*");
1149 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1151 2, idp->data, idp->len,
1156 strlen(entry->userinfo) : 0);
1157 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1158 0, packet->data, packet->len, FALSE);
1160 silc_buffer_free(packet);
1161 silc_buffer_free(idp);
1164 if (found == FALSE && entry)
1165 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1166 SILC_STATUS_ERR_NO_SUCH_NICK,
1168 strlen(entry->nickname));
1172 silc_server_command_whowas_process(SilcServerCommandContext cmd)
1174 SilcServer server = cmd->server;
1175 char *nick = NULL, *server_name = NULL;
1177 SilcClientEntry *clients = NULL;
1178 uint32 clients_count = 0;
1180 bool check_global = FALSE;
1182 /* Protocol dictates that we must always send the received WHOWAS request
1183 to our router if we are normal server, so let's do it now unless we
1184 are standalone. We will not send any replies to the client until we
1185 have received reply from the router. */
1186 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1187 server->server_type == SILC_SERVER && !cmd->pending &&
1188 !server->standalone) {
1192 old_ident = silc_command_get_ident(cmd->payload);
1193 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1194 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1196 /* Send WHOWAS command to our router */
1197 silc_server_packet_send(server, (SilcSocketConnection)
1198 server->router->connection,
1199 SILC_PACKET_COMMAND, cmd->packet->flags,
1200 tmpbuf->data, tmpbuf->len, TRUE);
1202 /* Reprocess this packet after received reply from router */
1203 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1204 silc_command_get_ident(cmd->payload),
1205 silc_server_command_destructor,
1206 silc_server_command_whowas,
1207 silc_server_command_dup(cmd));
1208 cmd->pending = TRUE;
1210 silc_command_set_ident(cmd->payload, old_ident);
1212 silc_buffer_free(tmpbuf);
1217 /* We are ready to process the command request. Let's search for the
1218 requested client and send reply to the requesting client. */
1220 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1221 check_global = TRUE;
1222 else if (server->server_type != SILC_SERVER)
1223 check_global = TRUE;
1225 /* Parse the whowas request */
1226 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1229 /* Get all clients matching that nickname from local list */
1230 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1232 &clients, &clients_count))
1233 silc_idlist_get_clients_by_hash(server->local_list,
1234 nick, server->md5hash,
1235 &clients, &clients_count);
1237 /* Check global list as well */
1239 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1241 &clients, &clients_count))
1242 silc_idlist_get_clients_by_hash(server->global_list,
1243 nick, server->md5hash,
1244 &clients, &clients_count);
1248 /* Such a client really does not exist in the SILC network. */
1249 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1250 SILC_STATUS_ERR_NO_SUCH_NICK,
1251 3, nick, strlen(nick));
1255 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1260 /* Send the command reply to the client */
1261 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1266 silc_free(server_name);
1271 /* Server side of command WHOWAS. */
1273 SILC_SERVER_CMD_FUNC(whowas)
1275 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1278 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1280 ret = silc_server_command_whowas_process(cmd);
1283 silc_server_command_free(cmd);
1286 /******************************************************************************
1290 ******************************************************************************/
1293 silc_server_command_identify_send_router(SilcServerCommandContext cmd)
1295 SilcServer server = cmd->server;
1299 old_ident = silc_command_get_ident(cmd->payload);
1300 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1301 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1303 /* Send IDENTIFY command to our router */
1304 silc_server_packet_send(server, (SilcSocketConnection)
1305 server->router->connection,
1306 SILC_PACKET_COMMAND, cmd->packet->flags,
1307 tmpbuf->data, tmpbuf->len, TRUE);
1309 /* Reprocess this packet after received reply from router */
1310 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1311 silc_command_get_ident(cmd->payload),
1312 silc_server_command_destructor,
1313 silc_server_command_identify,
1314 silc_server_command_dup(cmd));
1315 cmd->pending = TRUE;
1316 silc_command_set_ident(cmd->payload, old_ident);
1317 silc_buffer_free(tmpbuf);
1321 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1322 SilcClientEntry **clients,
1323 uint32 *clients_count,
1324 SilcServerEntry **servers,
1325 uint32 *servers_count,
1326 SilcChannelEntry **channels,
1327 uint32 *channels_count,
1330 SilcServer server = cmd->server;
1333 uint32 argc = silc_argument_get_arg_num(cmd->args);
1335 bool check_global = FALSE;
1340 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1341 check_global = TRUE;
1342 else if (server->server_type != SILC_SERVER)
1343 check_global = TRUE;
1345 /* If ID Payload is in the command it must be used instead of names */
1346 tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1348 /* No ID, get the names. */
1350 /* If we are normal server and have not resolved information from
1351 router yet, do so now. */
1352 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1353 server->server_type == SILC_SERVER && !cmd->pending &&
1354 !server->standalone) {
1355 silc_server_command_identify_send_router(cmd);
1359 /* Try to get nickname@server. */
1360 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1363 char *nick_server = NULL;
1365 silc_parse_userfqdn(tmp, &nick, &nick_server);
1367 if (!silc_idlist_get_clients_by_hash(server->local_list,
1368 nick, server->md5hash,
1369 clients, clients_count))
1370 silc_idlist_get_clients_by_nickname(server->local_list,
1372 clients, clients_count);
1374 if (!silc_idlist_get_clients_by_hash(server->global_list,
1375 nick, server->md5hash,
1376 clients, clients_count))
1377 silc_idlist_get_clients_by_nickname(server->global_list,
1379 clients, clients_count);
1383 silc_free(nick_server);
1386 /* the nickname does not exist, send error reply */
1387 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1388 SILC_STATUS_ERR_NO_SUCH_NICK,
1389 3, tmp, strlen(tmp));
1394 /* Try to get server name */
1395 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1397 entry = silc_idlist_find_server_by_name(server->local_list,
1399 if (!entry && check_global)
1400 entry = silc_idlist_find_server_by_name(server->global_list,
1403 *servers = silc_realloc(*servers, sizeof(**servers) *
1404 (*servers_count + 1));
1405 (*servers)[(*servers_count)++] = entry;
1409 /* the server does not exist, send error reply */
1410 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1411 SILC_STATUS_ERR_NO_SUCH_SERVER,
1412 3, tmp, strlen(tmp));
1417 /* Try to get channel name */
1418 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1420 entry = silc_idlist_find_channel_by_name(server->local_list,
1422 if (!entry && check_global)
1423 entry = silc_idlist_find_channel_by_name(server->global_list,
1426 *channels = silc_realloc(*channels, sizeof(**channels) *
1427 (*channels_count + 1));
1428 (*channels)[(*channels_count)++] = entry;
1432 /* The channel does not exist, send error reply */
1433 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1434 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1435 3, tmp, strlen(tmp));
1440 if (!(*clients) && !(*servers) && !(*channels)) {
1441 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1442 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1446 /* Command includes ID, we must use that. Also check whether the command
1447 has more than one ID set - take them all. */
1449 /* Take all ID's from the command packet */
1450 for (i = 0; i < argc; i++) {
1453 tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
1457 idp = silc_id_payload_parse(tmp, len);
1459 silc_free(*clients);
1460 silc_free(*servers);
1461 silc_free(*channels);
1462 silc_server_command_send_status_reply(
1463 cmd, SILC_COMMAND_IDENTIFY,
1464 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1468 id = silc_id_payload_get_id(idp);
1470 switch (silc_id_payload_get_type(idp)) {
1472 case SILC_ID_CLIENT:
1473 entry = (void *)silc_idlist_find_client_by_id(server->local_list,
1475 if (!entry && check_global)
1476 entry = (void *)silc_idlist_find_client_by_id(server->global_list,
1479 *clients = silc_realloc(*clients, sizeof(**clients) *
1480 (*clients_count + 1));
1481 (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
1483 /* If we are normal server and have not resolved information from
1484 router yet, do so now. */
1485 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1486 server->server_type == SILC_SERVER && !cmd->pending &&
1487 !server->standalone) {
1488 silc_server_command_identify_send_router(cmd);
1489 silc_free(*clients);
1490 silc_free(*servers);
1491 silc_free(*channels);
1494 silc_server_command_send_status_data(
1495 cmd, SILC_COMMAND_IDENTIFY,
1496 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1504 case SILC_ID_SERVER:
1505 entry = (void *)silc_idlist_find_server_by_id(server->local_list,
1507 if (!entry && check_global)
1508 entry = (void *)silc_idlist_find_server_by_id(server->global_list,
1511 *servers = silc_realloc(*servers, sizeof(**servers) *
1512 (*servers_count + 1));
1513 (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
1515 /* If we are normal server and have not resolved information from
1516 router yet, do so now. */
1517 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1518 server->server_type == SILC_SERVER && !cmd->pending &&
1519 !server->standalone) {
1520 silc_server_command_identify_send_router(cmd);
1521 silc_free(*clients);
1522 silc_free(*servers);
1523 silc_free(*channels);
1526 silc_server_command_send_status_data(
1527 cmd, SILC_COMMAND_IDENTIFY,
1528 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
1535 case SILC_ID_CHANNEL:
1536 entry = (void *)silc_idlist_find_channel_by_id(server->local_list,
1538 if (!entry && check_global)
1539 entry = (void *)silc_idlist_find_channel_by_id(server->global_list,
1542 *channels = silc_realloc(*channels, sizeof(**channels) *
1543 (*channels_count + 1));
1544 (*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
1546 /* If we are normal server and have not resolved information from
1547 router yet, do so now. */
1548 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1549 server->server_type == SILC_SERVER && !cmd->pending &&
1550 !server->standalone) {
1551 silc_server_command_identify_send_router(cmd);
1552 silc_free(*clients);
1553 silc_free(*servers);
1554 silc_free(*channels);
1557 silc_server_command_send_status_data(
1558 cmd, SILC_COMMAND_IDENTIFY,
1559 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
1572 silc_free(*clients);
1573 silc_free(*servers);
1574 silc_free(*channels);
1578 /* Get the max count of reply messages allowed */
1579 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1588 /* Checks that all mandatory fields in client entry are present. If not
1589 then send WHOIS request to the server who owns the client. We use
1590 WHOIS because we want to get as much information as possible at once. */
1593 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1594 SilcClientEntry *clients,
1595 uint32 clients_count)
1597 SilcServer server = cmd->server;
1598 SilcClientEntry entry;
1599 SilcServerResolveContext resolve = NULL, r = NULL;
1600 uint32 resolve_count = 0;
1604 for (i = 0; i < clients_count; i++) {
1609 if (entry->nickname ||
1610 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1614 /* If we are normal server, and we've not resolved this client from
1615 router and it is global client, we'll check whether it is on some
1616 channel. If not then we cannot be sure about its validity, and
1617 we'll resolve it from router. */
1618 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
1619 entry->connection || silc_hash_table_count(entry->channels))
1623 /* We need to resolve this entry since it is not complete */
1625 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1626 /* The entry is being resolved (and we are not the resolver) so attach
1627 to the command reply and we're done with this one. */
1628 silc_server_command_pending(server, SILC_COMMAND_NONE,
1629 entry->resolve_cmd_ident,
1630 silc_server_command_destructor,
1631 silc_server_command_identify,
1632 silc_server_command_dup(cmd));
1635 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1636 /* We've resolved this and it still is not ready. We'll return
1637 and are that this will be handled again after it is resolved. */
1638 for (i = 0; i < resolve_count; i++) {
1639 for (k = 0; k < r->res_argc; k++)
1640 silc_free(r->res_argv[k]);
1641 silc_free(r->res_argv);
1642 silc_free(r->res_argv_lens);
1643 silc_free(r->res_argv_types);
1648 /* We'll resolve this client */
1652 for (k = 0; k < resolve_count; k++) {
1653 if (resolve[k].router == entry->router) {
1660 resolve = silc_realloc(resolve, sizeof(*resolve) *
1661 (resolve_count + 1));
1662 r = &resolve[resolve_count];
1663 memset(r, 0, sizeof(*r));
1664 r->router = entry->router;
1665 r->ident = ++server->cmd_ident;
1669 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1671 r->res_argv_lens = silc_realloc(r->res_argv_lens,
1672 sizeof(*r->res_argv_lens) *
1674 r->res_argv_types = silc_realloc(r->res_argv_types,
1675 sizeof(*r->res_argv_types) *
1677 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1678 r->res_argv[r->res_argc] = silc_calloc(idp->len,
1679 sizeof(**r->res_argv));
1680 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1681 r->res_argv_lens[r->res_argc] = idp->len;
1682 r->res_argv_types[r->res_argc] = r->res_argc + 3;
1684 silc_buffer_free(idp);
1686 entry->resolve_cmd_ident = r->ident;
1687 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1688 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1693 /* Do the resolving */
1694 for (i = 0; i < resolve_count; i++) {
1699 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1700 now anyway so make it a good one. */
1701 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1702 r->res_argc, r->res_argv,
1706 silc_server_packet_send(server, r->router->connection,
1707 SILC_PACKET_COMMAND, cmd->packet->flags,
1708 res_cmd->data, res_cmd->len, FALSE);
1710 /* Reprocess this packet after received reply */
1711 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1713 silc_server_command_destructor,
1714 silc_server_command_identify,
1715 silc_server_command_dup(cmd));
1716 cmd->pending = TRUE;
1718 silc_buffer_free(res_cmd);
1719 for (k = 0; k < r->res_argc; k++)
1720 silc_free(r->res_argv[k]);
1721 silc_free(r->res_argv);
1722 silc_free(r->res_argv_lens);
1723 silc_free(r->res_argv_types);
1732 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1733 SilcClientEntry *clients,
1734 uint32 clients_count,
1735 SilcServerEntry *servers,
1736 uint32 servers_count,
1737 SilcChannelEntry *channels,
1738 uint32 channels_count,
1741 SilcServer server = cmd->server;
1742 int i, k, len, valid_count;
1743 SilcBuffer packet, idp;
1744 SilcCommandStatus status;
1745 uint16 ident = silc_command_get_ident(cmd->payload);
1746 char nh[256], uh[256];
1747 SilcSocketConnection hsock;
1749 status = SILC_STATUS_OK;
1752 SilcClientEntry entry;
1754 /* Process only valid entries. */
1756 for (i = 0; i < clients_count; i++) {
1757 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1764 /* No valid entries found at all, just send error */
1767 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1769 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1770 SILC_STATUS_ERR_NO_SUCH_NICK,
1771 3, tmp, strlen(tmp));
1773 tmp = silc_argument_get_arg_type(cmd->args, 5, (uint32 *)&len);
1774 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1775 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1781 /* Process all valid client entries and send command replies */
1783 if (valid_count > 1)
1784 status = SILC_STATUS_LIST_START;
1786 for (i = 0, k = 0; i < clients_count; i++) {
1792 status = SILC_STATUS_LIST_ITEM;
1793 if (valid_count > 1 && k == valid_count - 1
1794 && !servers_count && !channels_count)
1795 status = SILC_STATUS_LIST_END;
1796 if (count && k - 1 == count)
1797 status = SILC_STATUS_LIST_END;
1798 if (count && k - 1 > count)
1801 /* Send IDENTIFY reply */
1803 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1804 memset(uh, 0, sizeof(uh));
1805 memset(nh, 0, sizeof(nh));
1806 strncat(nh, entry->nickname, strlen(entry->nickname));
1807 if (!strchr(entry->nickname, '@')) {
1808 strncat(nh, "@", 1);
1809 if (entry->servername) {
1810 strncat(nh, entry->servername, strlen(entry->servername));
1812 len = entry->router ? strlen(entry->router->server_name) :
1813 strlen(server->server_name);
1814 strncat(nh, entry->router ? entry->router->server_name :
1815 server->server_name, len);
1819 if (!entry->username) {
1820 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1822 2, idp->data, idp->len,
1825 strncat(uh, entry->username, strlen(entry->username));
1826 if (!strchr(entry->username, '@')) {
1827 strncat(uh, "@", 1);
1828 hsock = (SilcSocketConnection)entry->connection;
1829 len = strlen(hsock->hostname);
1830 strncat(uh, hsock->hostname, len);
1833 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1835 2, idp->data, idp->len,
1840 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1841 0, packet->data, packet->len, FALSE);
1843 silc_buffer_free(packet);
1844 silc_buffer_free(idp);
1851 SilcServerEntry entry;
1853 if (status == SILC_STATUS_OK && servers_count > 1)
1854 status = SILC_STATUS_LIST_START;
1856 for (i = 0, k = 0; i < servers_count; i++) {
1860 status = SILC_STATUS_LIST_ITEM;
1861 if (servers_count > 1 && k == servers_count - 1 && !channels_count)
1862 status = SILC_STATUS_LIST_END;
1863 if (count && k - 1 == count)
1864 status = SILC_STATUS_LIST_END;
1865 if (count && k - 1 > count)
1868 /* Send IDENTIFY reply */
1869 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1871 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1873 2, idp->data, idp->len,
1874 3, entry->server_name,
1875 entry->server_name ?
1876 strlen(entry->server_name) : 0);
1877 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1878 0, packet->data, packet->len, FALSE);
1880 silc_buffer_free(packet);
1881 silc_buffer_free(idp);
1888 SilcChannelEntry entry;
1890 if (status == SILC_STATUS_OK && channels_count > 1)
1891 status = SILC_STATUS_LIST_START;
1893 for (i = 0, k = 0; i < channels_count; i++) {
1894 entry = channels[i];
1897 status = SILC_STATUS_LIST_ITEM;
1898 if (channels_count > 1 && k == channels_count - 1)
1899 status = SILC_STATUS_LIST_END;
1900 if (count && k - 1 == count)
1901 status = SILC_STATUS_LIST_END;
1902 if (count && k - 1 > count)
1905 /* Send IDENTIFY reply */
1906 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1908 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1910 2, idp->data, idp->len,
1911 3, entry->channel_name,
1912 entry->channel_name ?
1913 strlen(entry->channel_name): 0);
1914 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1915 0, packet->data, packet->len, FALSE);
1917 silc_buffer_free(packet);
1918 silc_buffer_free(idp);
1926 silc_server_command_identify_process(SilcServerCommandContext cmd)
1930 SilcClientEntry *clients = NULL;
1931 SilcServerEntry *servers = NULL;
1932 SilcChannelEntry *channels = NULL;
1933 uint32 clients_count = 0, servers_count = 0, channels_count = 0;
1935 /* Parse the IDENTIFY request */
1936 ret = silc_server_command_identify_parse(cmd,
1937 &clients, &clients_count,
1938 &servers, &servers_count,
1939 &channels, &channels_count,
1945 /* Check that all mandatory fields are present and request those data
1946 from the server who owns the client if necessary. */
1947 if (clients && !silc_server_command_identify_check_client(cmd, clients,
1953 /* Send the command reply to the client */
1954 silc_server_command_identify_send_reply(cmd,
1955 clients, clients_count,
1956 servers, servers_count,
1957 channels, channels_count,
1963 silc_free(channels);
1967 SILC_SERVER_CMD_FUNC(identify)
1969 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1972 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1974 ret = silc_server_command_identify_process(cmd);
1977 silc_server_command_free(cmd);
1980 /* Checks string for bad characters and returns TRUE if they are found. */
1982 static int silc_server_command_bad_chars(char *nick)
1986 for (i = 0; i < strlen(nick); i++) {
1987 if (!isascii(nick[i]))
1989 if (nick[i] <= 32) return TRUE;
1990 if (nick[i] == ' ') return TRUE;
1991 if (nick[i] == '*') return TRUE;
1992 if (nick[i] == '?') return TRUE;
1993 if (nick[i] == ',') return TRUE;
1999 /* Server side of command NICK. Sets nickname for user. Setting
2000 nickname causes generation of a new client ID for the client. The
2001 new client ID is sent to the client after changing the nickname. */
2003 SILC_SERVER_CMD_FUNC(nick)
2005 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2006 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2007 SilcServer server = cmd->server;
2008 SilcBuffer packet, nidp, oidp = NULL;
2009 SilcClientID *new_id;
2011 uint16 ident = silc_command_get_ident(cmd->payload);
2014 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2017 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
2019 /* Check nickname */
2020 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
2021 if (silc_server_command_bad_chars(nick) == TRUE) {
2022 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2023 SILC_STATUS_ERR_BAD_NICKNAME);
2027 if (strlen(nick) > 128)
2030 /* Check for same nickname */
2031 if (!strcmp(client->nickname, nick)) {
2032 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2036 /* Create new Client ID */
2037 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
2039 cmd->server->md5hash, nick,
2042 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2045 /* Send notify about nickname change to our router. We send the new
2046 ID and ask to replace it with the old one. If we are router the
2047 packet is broadcasted. Send NICK_CHANGE notify. */
2048 if (!server->standalone)
2049 silc_server_send_notify_nick_change(server, server->router->connection,
2050 server->server_type == SILC_SERVER ?
2051 FALSE : TRUE, client->id,
2054 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2056 /* Remove old cache entry */
2057 silc_idcache_del_by_context(server->local_list->clients, client);
2060 silc_free(client->id);
2062 /* Save the nickname as this client is our local client */
2063 silc_free(client->nickname);
2065 client->nickname = strdup(nick);
2066 client->id = new_id;
2068 /* Update client cache */
2069 silc_idcache_add(server->local_list->clients, client->nickname,
2070 client->id, (void *)client, 0, NULL);
2072 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2074 /* Send NICK_CHANGE notify to the client's channels */
2075 silc_server_send_notify_on_channels(server, NULL, client,
2076 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
2077 oidp->data, oidp->len,
2078 nidp->data, nidp->len);
2081 /* Send the new Client ID as reply command back to client */
2082 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
2083 SILC_STATUS_OK, ident, 1,
2084 2, nidp->data, nidp->len);
2085 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2086 0, packet->data, packet->len, FALSE);
2088 silc_buffer_free(packet);
2089 silc_buffer_free(nidp);
2091 silc_buffer_free(oidp);
2094 silc_server_command_free(cmd);
2097 /* Sends the LIST command reply */
2100 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2101 SilcChannelEntry *lch,
2103 SilcChannelEntry *gch,
2107 SilcBuffer packet, idp;
2108 SilcChannelEntry entry;
2109 SilcCommandStatus status;
2110 uint16 ident = silc_command_get_ident(cmd->payload);
2112 unsigned char usercount[4];
2115 for (i = 0; i < lch_count; i++)
2116 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2118 for (i = 0; i < gch_count; i++)
2119 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2122 status = SILC_STATUS_OK;
2123 if ((lch_count + gch_count) > 1)
2124 status = SILC_STATUS_LIST_START;
2127 for (i = 0; i < lch_count; i++) {
2133 status = SILC_STATUS_LIST_ITEM;
2134 if (i >= 1 && i == lch_count - 1 && !gch_count)
2135 status = SILC_STATUS_LIST_END;
2137 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2139 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2140 topic = "*private*";
2141 memset(usercount, 0, sizeof(usercount));
2143 topic = entry->topic;
2144 users = silc_hash_table_count(entry->user_list);
2145 SILC_PUT32_MSB(users, usercount);
2148 /* Send the reply */
2150 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2152 2, idp->data, idp->len,
2153 3, entry->channel_name,
2154 strlen(entry->channel_name),
2155 4, topic, topic ? strlen(topic) : 0,
2157 silc_server_packet_send(cmd->server, cmd->sock,
2158 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2159 packet->len, FALSE);
2160 silc_buffer_free(packet);
2161 silc_buffer_free(idp);
2165 for (i = 0; i < gch_count; i++) {
2171 status = SILC_STATUS_LIST_ITEM;
2172 if (i >= 1 && i == gch_count - 1)
2173 status = SILC_STATUS_LIST_END;
2175 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2177 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2178 topic = "*private*";
2179 memset(usercount, 0, sizeof(usercount));
2181 topic = entry->topic;
2182 users = silc_hash_table_count(entry->user_list);
2183 SILC_PUT32_MSB(users, usercount);
2186 /* Send the reply */
2188 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2190 2, idp->data, idp->len,
2191 3, entry->channel_name,
2192 strlen(entry->channel_name),
2193 4, topic, topic ? strlen(topic) : 0,
2195 silc_server_packet_send(cmd->server, cmd->sock,
2196 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2197 packet->len, FALSE);
2198 silc_buffer_free(packet);
2199 silc_buffer_free(idp);
2203 /* Server side of LIST command. This lists the channel of the requested
2204 server. Secret channels are not listed. */
2206 SILC_SERVER_CMD_FUNC(list)
2208 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2209 SilcServer server = cmd->server;
2210 SilcChannelID *channel_id = NULL;
2213 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2214 uint32 lch_count = 0, gch_count = 0;
2216 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2218 /* If we are normal server, send the command to router, since we
2219 want to know all channels in the network. */
2220 if (!cmd->pending && server->server_type == SILC_SERVER &&
2221 !server->standalone) {
2225 old_ident = silc_command_get_ident(cmd->payload);
2226 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2227 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2228 silc_server_packet_send(server, server->router->connection,
2229 SILC_PACKET_COMMAND, cmd->packet->flags,
2230 tmpbuf->data, tmpbuf->len, TRUE);
2232 /* Reprocess this packet after received reply from router */
2233 silc_server_command_pending(server, SILC_COMMAND_LIST,
2234 silc_command_get_ident(cmd->payload),
2235 silc_server_command_destructor,
2236 silc_server_command_list,
2237 silc_server_command_dup(cmd));
2238 cmd->pending = TRUE;
2239 silc_command_set_ident(cmd->payload, old_ident);
2240 silc_buffer_free(tmpbuf);
2244 /* Get Channel ID */
2245 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2247 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2249 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2250 SILC_STATUS_ERR_NO_CHANNEL_ID);
2255 /* Get the channels from local list */
2256 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2259 /* Get the channels from global list */
2260 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2263 /* Send the reply */
2264 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2265 gchannels, gch_count);
2267 silc_free(lchannels);
2268 silc_free(gchannels);
2271 silc_server_command_free(cmd);
2274 /* Server side of TOPIC command. Sets topic for channel and/or returns
2275 current topic to client. */
2277 SILC_SERVER_CMD_FUNC(topic)
2279 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2280 SilcServer server = cmd->server;
2281 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2282 SilcChannelID *channel_id;
2283 SilcChannelEntry channel;
2284 SilcChannelClientEntry chl;
2285 SilcBuffer packet, idp;
2287 uint32 argc, tmp_len;
2288 uint16 ident = silc_command_get_ident(cmd->payload);
2290 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2292 argc = silc_argument_get_arg_num(cmd->args);
2294 /* Get Channel ID */
2295 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2297 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2298 SILC_STATUS_ERR_NO_CHANNEL_ID);
2301 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2303 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2304 SILC_STATUS_ERR_NO_CHANNEL_ID);
2308 /* Check whether the channel exists */
2309 channel = silc_idlist_find_channel_by_id(server->local_list,
2312 channel = silc_idlist_find_channel_by_id(server->global_list,
2315 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2316 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2323 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2325 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2326 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2330 if (strlen(tmp) > 256) {
2331 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2332 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2336 /* See whether the client is on channel and has rights to change topic */
2337 if (!silc_hash_table_find(channel->user_list, client, NULL,
2339 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2340 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2344 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2345 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2346 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2347 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2352 /* Set the topic for channel */
2353 silc_free(channel->topic);
2354 channel->topic = strdup(tmp);
2356 /* Send TOPIC_SET notify type to the network */
2357 if (!server->standalone)
2358 silc_server_send_notify_topic_set(server, server->router->connection,
2359 server->server_type == SILC_ROUTER ?
2360 TRUE : FALSE, channel,
2361 client->id, SILC_ID_CLIENT,
2364 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2366 /* Send notify about topic change to all clients on the channel */
2367 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2368 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2369 idp->data, idp->len,
2370 channel->topic, strlen(channel->topic));
2371 silc_buffer_free(idp);
2374 /* Send the topic to client as reply packet */
2375 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2376 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2377 SILC_STATUS_OK, ident, 2,
2378 2, idp->data, idp->len,
2381 strlen(channel->topic) : 0);
2382 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2383 0, packet->data, packet->len, FALSE);
2385 silc_buffer_free(packet);
2386 silc_buffer_free(idp);
2387 silc_free(channel_id);
2390 silc_server_command_free(cmd);
2393 /* Server side of INVITE command. Invites some client to join some channel.
2394 This command is also used to manage the invite list of the channel. */
2396 SILC_SERVER_CMD_FUNC(invite)
2398 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2399 SilcServer server = cmd->server;
2400 SilcSocketConnection sock = cmd->sock, dest_sock;
2401 SilcChannelClientEntry chl;
2402 SilcClientEntry sender, dest;
2403 SilcClientID *dest_id = NULL;
2404 SilcChannelEntry channel;
2405 SilcChannelID *channel_id = NULL;
2406 SilcIDListData idata;
2407 SilcBuffer idp, idp2, packet;
2408 unsigned char *tmp, *add, *del;
2410 uint16 ident = silc_command_get_ident(cmd->payload);
2412 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2414 /* Get Channel ID */
2415 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2417 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2418 SILC_STATUS_ERR_NO_CHANNEL_ID);
2421 channel_id = silc_id_payload_parse_id(tmp, len);
2423 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2424 SILC_STATUS_ERR_NO_CHANNEL_ID);
2428 /* Get the channel entry */
2429 channel = silc_idlist_find_channel_by_id(server->local_list,
2432 channel = silc_idlist_find_channel_by_id(server->global_list,
2435 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2436 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2441 /* Check whether the sender of this command is on the channel. */
2442 sender = (SilcClientEntry)sock->user_data;
2443 if (!silc_server_client_on_channel(sender, channel)) {
2444 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2445 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2449 /* Check whether the channel is invite-only channel. If yes then the
2450 sender of this command must be at least channel operator. */
2451 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2452 silc_hash_table_find(channel->user_list, sender, NULL, (void *)&chl);
2453 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2454 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2455 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2460 /* Get destination client ID */
2461 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2465 dest_id = silc_id_payload_parse_id(tmp, len);
2467 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2468 SILC_STATUS_ERR_NO_CLIENT_ID);
2472 /* Get the client entry */
2473 dest = silc_server_get_client_resolve(server, dest_id);
2475 if (server->server_type != SILC_SERVER) {
2476 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2477 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2481 /* The client info is being resolved. Reprocess this packet after
2482 receiving the reply to the query. */
2483 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2485 silc_server_command_destructor,
2486 silc_server_command_invite,
2487 silc_server_command_dup(cmd));
2488 cmd->pending = TRUE;
2489 silc_free(channel_id);
2494 /* Check whether the requested client is already on the channel. */
2495 if (silc_server_client_on_channel(dest, channel)) {
2496 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2497 SILC_STATUS_ERR_USER_ON_CHANNEL);
2501 /* Get route to the client */
2502 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2504 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2505 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2509 memset(invite, 0, sizeof(invite));
2510 strncat(invite, dest->nickname, strlen(dest->nickname));
2511 strncat(invite, "!", 1);
2512 strncat(invite, dest->username, strlen(dest->username));
2513 if (!strchr(dest->username, '@')) {
2514 strncat(invite, "@", 1);
2515 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2518 len = strlen(invite);
2519 if (!channel->invite_list)
2520 channel->invite_list = silc_calloc(len + 2,
2521 sizeof(*channel->invite_list));
2523 channel->invite_list = silc_realloc(channel->invite_list,
2524 sizeof(*channel->invite_list) *
2526 strlen(channel->invite_list) + 2));
2527 strncat(channel->invite_list, invite, len);
2528 strncat(channel->invite_list, ",", 1);
2530 /* Send notify to the client that is invited to the channel */
2531 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2532 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2533 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2535 SILC_NOTIFY_TYPE_INVITE, 3,
2536 idp->data, idp->len,
2537 channel->channel_name,
2538 strlen(channel->channel_name),
2539 idp2->data, idp2->len);
2540 silc_buffer_free(idp);
2541 silc_buffer_free(idp2);
2544 /* Add the client to the invite list of the channel */
2545 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2547 if (!channel->invite_list)
2548 channel->invite_list = silc_calloc(len + 2,
2549 sizeof(*channel->invite_list));
2551 channel->invite_list = silc_realloc(channel->invite_list,
2552 sizeof(*channel->invite_list) *
2554 strlen(channel->invite_list) + 2));
2555 if (add[len - 1] == ',')
2556 add[len - 1] = '\0';
2558 strncat(channel->invite_list, add, len);
2559 strncat(channel->invite_list, ",", 1);
2562 /* Get the invite to be removed and remove it from the list */
2563 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2564 if (del && channel->invite_list) {
2565 char *start, *end, *n;
2567 if (!strncmp(channel->invite_list, del,
2568 strlen(channel->invite_list) - 1)) {
2569 silc_free(channel->invite_list);
2570 channel->invite_list = NULL;
2572 start = strstr(channel->invite_list, del);
2573 if (start && strlen(start) >= len) {
2575 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2576 strncat(n, channel->invite_list, start - channel->invite_list);
2577 strncat(n, end + 1, ((channel->invite_list +
2578 strlen(channel->invite_list)) - end) - 1);
2579 silc_free(channel->invite_list);
2580 channel->invite_list = n;
2585 /* Send notify to the primary router */
2586 if (!server->standalone)
2587 silc_server_send_notify_invite(server, server->router->connection,
2588 server->server_type == SILC_ROUTER ?
2589 TRUE : FALSE, channel,
2590 sender->id, add, del);
2592 /* Send command reply */
2593 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2597 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2598 SILC_STATUS_OK, ident, 2,
2600 3, channel->invite_list,
2601 channel->invite_list ?
2602 strlen(channel->invite_list) : 0);
2605 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2606 SILC_STATUS_OK, ident, 1,
2608 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2609 packet->data, packet->len, FALSE);
2610 silc_buffer_free(packet);
2614 silc_free(channel_id);
2615 silc_server_command_free(cmd);
2620 SilcSocketConnection sock;
2624 /* Quits connection to client. This gets called if client won't
2625 close the connection even when it has issued QUIT command. */
2627 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2629 QuitInternal q = (QuitInternal)context;
2631 /* Free all client specific data, such as client entry and entires
2632 on channels this client may be on. */
2633 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2635 q->sock->user_data = NULL;
2637 /* Close the connection on our side */
2638 silc_server_close_connection(q->server, q->sock);
2640 silc_free(q->signoff);
2644 /* Quits SILC session. This is the normal way to disconnect client. */
2646 SILC_SERVER_CMD_FUNC(quit)
2648 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2649 SilcServer server = cmd->server;
2650 SilcSocketConnection sock = cmd->sock;
2652 unsigned char *tmp = NULL;
2655 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2657 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2660 /* Get destination ID */
2661 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2665 q = silc_calloc(1, sizeof(*q));
2668 q->signoff = tmp ? strdup(tmp) : NULL;
2670 /* We quit the connection with little timeout */
2671 silc_schedule_task_add(server->schedule, sock->sock,
2672 silc_server_command_quit_cb, (void *)q,
2673 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2676 silc_server_command_free(cmd);
2679 /* Server side of command KILL. This command is used by router operator
2680 to remove an client from the SILC Network temporarily. */
2682 SILC_SERVER_CMD_FUNC(kill)
2684 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2685 SilcServer server = cmd->server;
2686 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2687 SilcClientEntry remote_client;
2688 SilcClientID *client_id;
2689 unsigned char *tmp, *comment;
2690 uint32 tmp_len, tmp_len2;
2692 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2694 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2697 /* KILL command works only on router */
2698 if (server->server_type != SILC_ROUTER) {
2699 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2700 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2704 /* Check whether client has the permissions. */
2705 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2706 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2707 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2711 /* Get the client ID */
2712 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2714 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2715 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2718 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2720 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2721 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2725 /* Get the client entry */
2726 remote_client = silc_idlist_find_client_by_id(server->local_list,
2727 client_id, TRUE, NULL);
2728 if (!remote_client) {
2729 remote_client = silc_idlist_find_client_by_id(server->global_list,
2730 client_id, TRUE, NULL);
2731 if (!remote_client) {
2732 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2733 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2739 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2743 /* Send reply to the sender */
2744 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2747 /* Send the KILL notify packets. First send it to the channel, then
2748 to our primary router and then directly to the client who is being
2749 killed right now. */
2751 /* Send KILLED notify to the channels. It is not sent to the client
2752 as it will be sent differently destined directly to the client and not
2754 silc_server_send_notify_on_channels(server, remote_client,
2755 remote_client, SILC_NOTIFY_TYPE_KILLED,
2758 comment, comment ? tmp_len2 : 0);
2760 /* Send KILLED notify to primary route */
2761 if (!server->standalone)
2762 silc_server_send_notify_killed(server, server->router->connection, TRUE,
2763 remote_client->id, comment);
2765 /* Send KILLED notify to the client directly */
2766 silc_server_send_notify_killed(server, remote_client->connection ?
2767 remote_client->connection :
2768 remote_client->router->connection, FALSE,
2769 remote_client->id, comment);
2771 /* Remove the client from all channels. This generates new keys to the
2772 channels as well. */
2773 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2776 /* Remove the client entry, If it is locally connected then we will also
2777 disconnect the client here */
2778 if (remote_client->connection) {
2779 /* Remove locally conneted client */
2780 SilcSocketConnection sock = remote_client->connection;
2781 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2782 silc_server_close_connection(server, sock);
2784 /* Remove remote client */
2785 if (!silc_idlist_del_client(server->global_list, remote_client))
2786 silc_idlist_del_client(server->local_list, remote_client);
2790 silc_server_command_free(cmd);
2793 /* Server side of command INFO. This sends information about us to
2794 the client. If client requested specific server we will send the
2795 command to that server. */
2797 SILC_SERVER_CMD_FUNC(info)
2799 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2800 SilcServer server = cmd->server;
2801 SilcBuffer packet, idp;
2804 char *dest_server, *server_info = NULL, *server_name;
2805 uint16 ident = silc_command_get_ident(cmd->payload);
2806 SilcServerEntry entry = NULL;
2807 SilcServerID *server_id = NULL;
2809 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2811 /* Get server name */
2812 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2815 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2817 server_id = silc_id_payload_parse_id(tmp, tmp_len);
2819 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2820 SILC_STATUS_ERR_NO_SERVER_ID);
2826 /* Check whether we have this server cached */
2827 entry = silc_idlist_find_server_by_id(server->local_list,
2828 server_id, TRUE, NULL);
2830 entry = silc_idlist_find_server_by_id(server->global_list,
2831 server_id, TRUE, NULL);
2832 if (!entry && server->server_type != SILC_SERVER) {
2833 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2834 SILC_STATUS_ERR_NO_SUCH_SERVER);
2840 /* Some buggy servers has sent request to router about themselves. */
2841 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2844 if ((!dest_server && !server_id && !entry) || (entry &&
2845 entry == server->id_entry) ||
2846 (dest_server && !cmd->pending &&
2847 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2848 /* Send our reply */
2849 char info_string[256];
2851 memset(info_string, 0, sizeof(info_string));
2852 snprintf(info_string, sizeof(info_string),
2853 "location: %s server: %s admin: %s <%s>",
2854 server->config->admin_info->location,
2855 server->config->admin_info->server_type,
2856 server->config->admin_info->admin_name,
2857 server->config->admin_info->admin_email);
2859 server_info = info_string;
2860 entry = server->id_entry;
2862 /* Check whether we have this server cached */
2863 if (!entry && dest_server) {
2864 entry = silc_idlist_find_server_by_name(server->global_list,
2865 dest_server, TRUE, NULL);
2867 entry = silc_idlist_find_server_by_name(server->local_list,
2868 dest_server, TRUE, NULL);
2872 if (!cmd->pending &&
2873 server->server_type != SILC_SERVER && entry && !entry->server_info) {
2874 /* Send to the server */
2878 old_ident = silc_command_get_ident(cmd->payload);
2879 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2880 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2882 silc_server_packet_send(server, entry->connection,
2883 SILC_PACKET_COMMAND, cmd->packet->flags,
2884 tmpbuf->data, tmpbuf->len, TRUE);
2886 /* Reprocess this packet after received reply from router */
2887 silc_server_command_pending(server, SILC_COMMAND_INFO,
2888 silc_command_get_ident(cmd->payload),
2889 silc_server_command_destructor,
2890 silc_server_command_info,
2891 silc_server_command_dup(cmd));
2892 cmd->pending = TRUE;
2893 silc_command_set_ident(cmd->payload, old_ident);
2894 silc_buffer_free(tmpbuf);
2898 if (!entry && !cmd->pending && !server->standalone) {
2899 /* Send to the primary router */
2903 old_ident = silc_command_get_ident(cmd->payload);
2904 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2905 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2907 silc_server_packet_send(server, server->router->connection,
2908 SILC_PACKET_COMMAND, cmd->packet->flags,
2909 tmpbuf->data, tmpbuf->len, TRUE);
2911 /* Reprocess this packet after received reply from router */
2912 silc_server_command_pending(server, SILC_COMMAND_INFO,
2913 silc_command_get_ident(cmd->payload),
2914 silc_server_command_destructor,
2915 silc_server_command_info,
2916 silc_server_command_dup(cmd));
2917 cmd->pending = TRUE;
2918 silc_command_set_ident(cmd->payload, old_ident);
2919 silc_buffer_free(tmpbuf);
2924 silc_free(server_id);
2927 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2928 SILC_STATUS_ERR_NO_SUCH_SERVER);
2932 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2934 server_info = entry->server_info;
2935 server_name = entry->server_name;
2937 /* Send the reply */
2938 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2939 SILC_STATUS_OK, ident, 3,
2940 2, idp->data, idp->len,
2942 strlen(server_name),
2945 strlen(server_info) : 0);
2946 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2947 packet->data, packet->len, FALSE);
2949 silc_buffer_free(packet);
2950 silc_buffer_free(idp);
2953 silc_server_command_free(cmd);
2956 /* Server side of command PING. This just replies to the ping. */
2958 SILC_SERVER_CMD_FUNC(ping)
2960 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2961 SilcServer server = cmd->server;
2966 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
2969 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2971 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2972 SILC_STATUS_ERR_NO_SERVER_ID);
2975 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2979 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2980 /* Send our reply */
2981 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2984 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2985 SILC_STATUS_ERR_NO_SUCH_SERVER);
2992 silc_server_command_free(cmd);
2995 /* Internal routine to join channel. The channel sent to this function
2996 has been either created or resolved from ID lists. This joins the sent
2997 client to the channel. */
2999 static void silc_server_command_join_channel(SilcServer server,
3000 SilcServerCommandContext cmd,
3001 SilcChannelEntry channel,
3002 SilcClientID *client_id,
3006 const unsigned char *auth,
3009 SilcSocketConnection sock = cmd->sock;
3011 uint32 tmp_len, user_count;
3012 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
3013 SilcClientEntry client;
3014 SilcChannelClientEntry chl;
3015 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
3016 uint16 ident = silc_command_get_ident(cmd->payload);
3017 char check[512], check2[512];
3018 bool founder = FALSE;
3020 SILC_LOG_DEBUG(("Start"));
3025 /* Get the client entry */
3026 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3027 client = (SilcClientEntry)sock->user_data;
3029 client = silc_server_get_client_resolve(server, client_id);
3034 /* The client info is being resolved. Reprocess this packet after
3035 receiving the reply to the query. */
3036 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
3037 server->cmd_ident, NULL,
3038 silc_server_command_join,
3039 silc_server_command_dup(cmd));
3040 cmd->pending = TRUE;
3044 cmd->pending = FALSE;
3048 * Check founder auth payload if provided. If client can gain founder
3049 * privileges it can override various conditions on joining the channel,
3050 * and can have directly the founder mode set on the channel.
3052 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3053 SilcIDListData idata = (SilcIDListData)client;
3055 if (channel->founder_key && idata->public_key &&
3056 silc_pkcs_public_key_compare(channel->founder_key,
3057 idata->public_key)) {
3058 void *auth_data = (channel->founder_method == SILC_AUTH_PASSWORD ?
3059 (void *)channel->founder_passwd :
3060 (void *)channel->founder_key);
3061 uint32 auth_data_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
3062 channel->founder_passwd_len : 0);
3064 /* Check whether the client is to become founder */
3065 if (silc_auth_verify_data(auth, auth_len, channel->founder_method,
3066 auth_data, auth_data_len,
3067 idata->hash, client->id, SILC_ID_CLIENT)) {
3068 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3075 * Check channel modes
3079 memset(check, 0, sizeof(check));
3080 memset(check2, 0, sizeof(check2));
3081 strncat(check, client->nickname, strlen(client->nickname));
3082 strncat(check, "!", 1);
3083 strncat(check, client->username, strlen(client->username));
3084 if (!strchr(client->username, '@')) {
3085 strncat(check, "@", 1);
3086 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3089 strncat(check2, client->nickname, strlen(client->nickname));
3090 if (!strchr(client->nickname, '@')) {
3091 strncat(check2, "@", 1);
3092 strncat(check2, server->server_name, strlen(server->server_name));
3094 strncat(check2, "!", 1);
3095 strncat(check2, client->username, strlen(client->username));
3096 if (!strchr(client->username, '@')) {
3097 strncat(check2, "@", 1);
3098 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3101 /* Check invite list if channel is invite-only channel */
3102 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3103 if (!channel->invite_list ||
3104 (!silc_string_match(channel->invite_list, check) &&
3105 !silc_string_match(channel->invite_list, check2))) {
3106 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3107 SILC_STATUS_ERR_NOT_INVITED);
3112 /* Check ban list if it exists. If the client's nickname, server,
3113 username and/or hostname is in the ban list the access to the
3114 channel is denied. */
3115 if (channel->ban_list) {
3116 if (!channel->ban_list ||
3117 silc_string_match(channel->ban_list, check) ||
3118 silc_string_match(channel->ban_list, check2)) {
3119 silc_server_command_send_status_reply(
3120 cmd, SILC_COMMAND_JOIN,
3121 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
3126 /* Check user count limit if set. */
3127 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3128 if (silc_hash_table_count(channel->user_list) + 1 >
3129 channel->user_limit) {
3130 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3131 SILC_STATUS_ERR_CHANNEL_IS_FULL);
3137 /* Check the channel passphrase if set. */
3138 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3139 /* Get passphrase */
3140 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3142 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
3143 memcpy(passphrase, tmp, tmp_len);
3146 if (!passphrase || !channel->passphrase ||
3147 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3148 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3149 SILC_STATUS_ERR_BAD_PASSWORD);
3155 * Client is allowed to join to the channel. Make it happen.
3158 /* Check whether the client already is on the channel */
3159 if (silc_server_client_on_channel(client, channel)) {
3160 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3161 SILC_STATUS_ERR_USER_ON_CHANNEL);
3165 /* Generate new channel key as protocol dictates */
3167 if (!silc_server_create_channel_key(server, channel, 0))
3170 /* Send the channel key. This is broadcasted to the channel but is not
3171 sent to the client who is joining to the channel. */
3172 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3173 silc_server_send_channel_key(server, NULL, channel,
3174 server->server_type == SILC_ROUTER ?
3175 FALSE : !server->standalone);
3178 /* Join the client to the channel by adding it to channel's user list.
3179 Add also the channel to client entry's channels list for fast cross-
3181 chl = silc_calloc(1, sizeof(*chl));
3183 chl->client = client;
3184 chl->channel = channel;
3185 silc_hash_table_add(channel->user_list, client, chl);
3186 silc_hash_table_add(client->channels, channel, chl);
3188 /* Get users on the channel */
3189 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3192 /* Encode Client ID Payload of the original client who wants to join */
3193 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3195 /* Encode command reply packet */
3196 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3197 SILC_PUT32_MSB(channel->mode, mode);
3198 SILC_PUT32_MSB(created, tmp2);
3199 SILC_PUT32_MSB(user_count, tmp3);
3201 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3202 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3203 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
3204 strlen(channel->channel_key->
3206 channel->channel_key->cipher->name,
3207 channel->key_len / 8, channel->key);
3212 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3213 SILC_STATUS_OK, ident, 13,
3214 2, channel->channel_name,
3215 strlen(channel->channel_name),
3216 3, chidp->data, chidp->len,
3217 4, clidp->data, clidp->len,
3220 7, keyp ? keyp->data : NULL,
3221 keyp ? keyp->len : 0,
3222 8, channel->ban_list,
3224 strlen(channel->ban_list) : 0,
3225 9, channel->invite_list,
3226 channel->invite_list ?
3227 strlen(channel->invite_list) : 0,
3230 strlen(channel->topic) : 0,
3231 11, silc_hmac_get_name(channel->hmac),
3232 strlen(silc_hmac_get_name(channel->
3235 13, user_list->data, user_list->len,
3236 14, mode_list->data,
3239 /* Send command reply */
3240 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3241 reply->data, reply->len, FALSE);
3243 /* Send JOIN notify to locally connected clients on the channel. If
3244 we are normal server then router will send or have sent JOIN notify
3245 already. However since we've added the client already to our channel
3246 we'll ignore it (in packet_receive.c) so we must send it here. If
3247 we are router then this will send it to local clients and local
3249 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3250 SILC_NOTIFY_TYPE_JOIN, 2,
3251 clidp->data, clidp->len,
3252 chidp->data, chidp->len);
3254 if (!cmd->pending) {
3255 /* Send JOIN notify packet to our primary router */
3256 if (!server->standalone)
3257 silc_server_send_notify_join(server, server->router->connection,
3258 server->server_type == SILC_ROUTER ?
3259 TRUE : FALSE, channel, client->id);
3262 /* Distribute the channel key to all backup routers. */
3263 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3264 keyp->data, keyp->len, FALSE, TRUE);
3266 /* If client became founder by providing correct founder auth data
3267 notify the mode change to the channel. */
3269 SILC_PUT32_MSB(chl->mode, mode);
3270 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3271 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3272 clidp->data, clidp->len,
3273 mode, 4, clidp->data, clidp->len);
3275 /* Set CUMODE notify type to network */
3276 if (!server->standalone)
3277 silc_server_send_notify_cumode(server, server->router->connection,
3278 server->server_type == SILC_ROUTER ?
3279 TRUE : FALSE, channel,
3280 chl->mode, client->id, SILC_ID_CLIENT,
3285 silc_buffer_free(reply);
3286 silc_buffer_free(clidp);
3287 silc_buffer_free(chidp);
3288 silc_buffer_free(keyp);
3289 silc_buffer_free(user_list);
3290 silc_buffer_free(mode_list);
3293 silc_free(passphrase);
3296 /* Server side of command JOIN. Joins client into requested channel. If
3297 the channel does not exist it will be created. */
3299 SILC_SERVER_CMD_FUNC(join)
3301 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3302 SilcServer server = cmd->server;
3303 unsigned char *auth;
3304 uint32 tmp_len, auth_len;
3305 char *tmp, *channel_name = NULL, *cipher, *hmac;
3306 SilcChannelEntry channel;
3308 bool created = FALSE, create_key = TRUE;
3309 SilcClientID *client_id;
3311 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3313 /* Get channel name */
3314 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3316 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3317 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3322 if (strlen(channel_name) > 256)
3323 channel_name[255] = '\0';
3325 if (silc_server_command_bad_chars(channel_name) == TRUE) {
3326 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3327 SILC_STATUS_ERR_BAD_CHANNEL);
3331 /* Get Client ID of the client who is joining to the channel */
3332 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3334 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3335 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3338 client_id = silc_id_payload_parse_id(tmp, tmp_len);
3340 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3341 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3345 /* Get cipher, hmac name and auth payload */
3346 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3347 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3348 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3350 /* See if the channel exists */
3351 channel = silc_idlist_find_channel_by_name(server->local_list,
3352 channel_name, NULL);
3354 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3355 /* If this is coming from client the Client ID in the command packet must
3356 be same as the client's ID. */
3357 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3358 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3359 if (!SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
3360 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3361 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3366 if (!channel || channel->disabled) {
3367 /* Channel not found */
3369 /* If we are standalone server we don't have a router, we just create
3370 the channel by ourselves. */
3371 if (server->standalone) {
3372 channel = silc_server_create_new_channel(server, server->id, cipher,
3373 hmac, channel_name, TRUE);
3375 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3376 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3380 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3386 /* The channel does not exist on our server. If we are normal server
3387 we will send JOIN command to our router which will handle the
3388 joining procedure (either creates the channel if it doesn't exist
3389 or joins the client to it). */
3390 if (server->server_type != SILC_ROUTER) {
3394 /* If this is pending command callback then we've resolved
3395 it and it didn't work, return since we've notified the
3396 client already in the command reply callback. */
3400 old_ident = silc_command_get_ident(cmd->payload);
3401 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3402 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3404 /* Send JOIN command to our router */
3405 silc_server_packet_send(server, (SilcSocketConnection)
3406 server->router->connection,
3407 SILC_PACKET_COMMAND, cmd->packet->flags,
3408 tmpbuf->data, tmpbuf->len, TRUE);
3410 /* Reprocess this packet after received reply from router */
3411 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3412 silc_command_get_ident(cmd->payload),
3413 silc_server_command_destructor,
3414 silc_server_command_join,
3415 silc_server_command_dup(cmd));
3416 cmd->pending = TRUE;
3420 /* We are router and the channel does not seem exist so we will check
3421 our global list as well for the channel. */
3422 channel = silc_idlist_find_channel_by_name(server->global_list,
3423 channel_name, NULL);
3425 /* Channel really does not exist, create it */
3426 channel = silc_server_create_new_channel(server, server->id, cipher,
3427 hmac, channel_name, TRUE);
3429 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3430 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3434 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3442 /* Channel not found */
3444 /* If the command came from router and we are normal server then
3445 something went wrong with the joining as the channel was not found.
3446 We can't do anything else but ignore this. */
3447 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3448 server->server_type != SILC_ROUTER)
3451 /* We are router and the channel does not seem exist so we will check
3452 our global list as well for the channel. */
3453 channel = silc_idlist_find_channel_by_name(server->global_list,
3454 channel_name, NULL);
3456 /* Channel really does not exist, create it */
3457 channel = silc_server_create_new_channel(server, server->id, cipher,
3458 hmac, channel_name, TRUE);
3460 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3461 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3465 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3472 /* Check whether the channel was created by our router */
3473 if (cmd->pending && context2) {
3474 SilcServerCommandReplyContext reply =
3475 (SilcServerCommandReplyContext)context2;
3476 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3477 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3478 SILC_GET32_MSB(created, tmp);
3479 create_key = FALSE; /* Router returned the key already */
3483 /* If the channel does not have global users and is also empty the client
3484 will be the channel founder and operator. */
3485 if (!channel->global_users && !silc_hash_table_count(channel->user_list))
3486 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3488 /* Join to the channel */
3489 silc_server_command_join_channel(server, cmd, channel, client_id,
3490 created, create_key, umode,
3493 silc_free(client_id);
3496 silc_server_command_free(cmd);
3499 /* Server side of command MOTD. Sends server's current "message of the
3500 day" to the client. */
3502 SILC_SERVER_CMD_FUNC(motd)
3504 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3505 SilcServer server = cmd->server;
3506 SilcBuffer packet, idp;
3507 char *motd, *dest_server;
3509 uint16 ident = silc_command_get_ident(cmd->payload);
3511 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3513 /* Get server name */
3514 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3516 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3517 SILC_STATUS_ERR_NO_SUCH_SERVER);
3521 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3524 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3526 if (server->config && server->config->motd &&
3527 server->config->motd->motd_file) {
3529 motd = silc_file_readfile(server->config->motd->motd_file, &motd_len);
3534 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3535 SILC_STATUS_OK, ident, 2,
3540 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3541 SILC_STATUS_OK, ident, 1,
3545 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3546 packet->data, packet->len, FALSE);
3547 silc_buffer_free(packet);
3548 silc_buffer_free(idp);
3550 SilcServerEntry entry;
3552 /* Check whether we have this server cached */
3553 entry = silc_idlist_find_server_by_name(server->global_list,
3554 dest_server, TRUE, NULL);
3556 entry = silc_idlist_find_server_by_name(server->local_list,
3557 dest_server, TRUE, NULL);
3560 if (server->server_type != SILC_SERVER && !cmd->pending &&
3561 entry && !entry->motd) {
3562 /* Send to the server */
3566 old_ident = silc_command_get_ident(cmd->payload);
3567 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3568 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3570 silc_server_packet_send(server, entry->connection,
3571 SILC_PACKET_COMMAND, cmd->packet->flags,
3572 tmpbuf->data, tmpbuf->len, TRUE);
3574 /* Reprocess this packet after received reply from router */
3575 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3576 silc_command_get_ident(cmd->payload),
3577 silc_server_command_destructor,
3578 silc_server_command_motd,
3579 silc_server_command_dup(cmd));
3580 cmd->pending = TRUE;
3581 silc_command_set_ident(cmd->payload, old_ident);
3582 silc_buffer_free(tmpbuf);
3586 if (!entry && !cmd->pending && !server->standalone) {
3587 /* Send to the primary router */
3591 old_ident = silc_command_get_ident(cmd->payload);
3592 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3593 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3595 silc_server_packet_send(server, server->router->connection,
3596 SILC_PACKET_COMMAND, cmd->packet->flags,
3597 tmpbuf->data, tmpbuf->len, TRUE);
3599 /* Reprocess this packet after received reply from router */
3600 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3601 silc_command_get_ident(cmd->payload),
3602 silc_server_command_destructor,
3603 silc_server_command_motd,
3604 silc_server_command_dup(cmd));
3605 cmd->pending = TRUE;
3606 silc_command_set_ident(cmd->payload, old_ident);
3607 silc_buffer_free(tmpbuf);
3612 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3613 SILC_STATUS_ERR_NO_SUCH_SERVER);
3617 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3618 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3619 SILC_STATUS_OK, ident, 2,
3623 strlen(entry->motd) : 0);
3624 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3625 packet->data, packet->len, FALSE);
3626 silc_buffer_free(packet);
3627 silc_buffer_free(idp);
3631 silc_server_command_free(cmd);
3634 /* Server side of command UMODE. Client can use this command to set/unset
3635 user mode. Client actually cannot set itself to be as server/router
3636 operator so this can be used only to unset the modes. */
3638 SILC_SERVER_CMD_FUNC(umode)
3640 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3641 SilcServer server = cmd->server;
3642 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3644 unsigned char *tmp_mask;
3646 uint16 ident = silc_command_get_ident(cmd->payload);
3648 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3651 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 2, 2);
3653 /* Get the client's mode mask */
3654 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3656 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3657 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3660 SILC_GET32_MSB(mask, tmp_mask);
3666 if (mask & SILC_UMODE_SERVER_OPERATOR) {
3667 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR)) {
3668 /* Cannot operator mode */
3669 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3670 SILC_STATUS_ERR_PERM_DENIED);
3674 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
3675 /* Remove the server operator rights */
3676 client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3679 if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3680 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
3681 /* Cannot operator mode */
3682 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3683 SILC_STATUS_ERR_PERM_DENIED);
3687 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
3688 /* Remove the router operator rights */
3689 client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3692 if (mask & SILC_UMODE_GONE) {
3693 client->mode |= SILC_UMODE_GONE;
3695 if (client->mode & SILC_UMODE_GONE)
3696 /* Remove the gone status */
3697 client->mode &= ~SILC_UMODE_GONE;
3700 /* Send UMODE change to primary router */
3701 if (!server->standalone)
3702 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3703 client->id, client->mode);
3705 /* Send command reply to sender */
3706 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3707 SILC_STATUS_OK, ident, 1,
3709 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3710 packet->data, packet->len, FALSE);
3711 silc_buffer_free(packet);
3714 silc_server_command_free(cmd);
3717 /* Checks that client has rights to add or remove channel modes. If any
3718 of the checks fails FALSE is returned. */
3720 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3721 SilcChannelClientEntry client,
3724 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3725 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3727 /* Check whether has rights to change anything */
3728 if (!is_op && !is_fo)
3731 /* Check whether has rights to change everything */
3735 /* We know that client is channel operator, check that they are not
3736 changing anything that requires channel founder rights. Rest of the
3737 modes are available automatically for channel operator. */
3739 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3740 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3741 if (is_op && !is_fo)
3744 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3745 if (is_op && !is_fo)
3750 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3751 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE))
3752 if (is_op && !is_fo)
3755 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3756 if (is_op && !is_fo)
3761 if (mode & SILC_CHANNEL_MODE_CIPHER) {
3762 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER))
3763 if (is_op && !is_fo)
3766 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3767 if (is_op && !is_fo)
3772 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3773 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH))
3774 if (is_op && !is_fo)
3777 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3778 if (is_op && !is_fo)
3786 /* Server side command of CMODE. Changes channel mode */
3788 SILC_SERVER_CMD_FUNC(cmode)
3790 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3791 SilcServer server = cmd->server;
3792 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3793 SilcIDListData idata = (SilcIDListData)client;
3794 SilcChannelID *channel_id;
3795 SilcChannelEntry channel;
3796 SilcChannelClientEntry chl;
3797 SilcBuffer packet, cidp;
3798 unsigned char *tmp, *tmp_id, *tmp_mask;
3799 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3800 uint32 mode_mask, tmp_len, tmp_len2;
3801 uint16 ident = silc_command_get_ident(cmd->payload);
3803 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 2, 7);
3805 /* Get Channel ID */
3806 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3808 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3809 SILC_STATUS_ERR_NO_CHANNEL_ID);
3812 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3814 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3815 SILC_STATUS_ERR_NO_CHANNEL_ID);
3819 /* Get the channel mode mask */
3820 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3822 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3823 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3826 SILC_GET32_MSB(mode_mask, tmp_mask);
3828 /* Get channel entry */
3829 channel = silc_idlist_find_channel_by_id(server->local_list,
3832 channel = silc_idlist_find_channel_by_id(server->global_list,
3835 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3836 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3841 /* Check whether this client is on the channel */
3842 if (!silc_server_client_on_channel(client, channel)) {
3843 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3844 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3848 /* Get entry to the channel user list */
3849 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
3851 /* Check that client has rights to change any requested channel modes */
3852 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3853 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3854 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3859 * Check the modes. Modes that requires nothing special operation are
3863 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3864 /* Channel uses private keys to protect traffic. Client(s) has set the
3865 key locally they want to use, server does not know that key. */
3866 /* Nothing interesting to do here */
3868 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3869 /* The mode is removed and we need to generate and distribute
3870 new channel key. Clients are not using private channel keys
3871 anymore after this. */
3873 /* Re-generate channel key */
3874 if (!silc_server_create_channel_key(server, channel, 0))
3877 /* Send the channel key. This sends it to our local clients and if
3878 we are normal server to our router as well. */
3879 silc_server_send_channel_key(server, NULL, channel,
3880 server->server_type == SILC_ROUTER ?
3881 FALSE : !server->standalone);
3883 cipher = channel->channel_key->cipher->name;
3884 hmac = (char *)silc_hmac_get_name(channel->hmac);
3888 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3889 /* User limit is set on channel */
3892 /* Get user limit */
3893 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3895 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3896 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3897 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3901 SILC_GET32_MSB(user_limit, tmp);
3902 channel->user_limit = user_limit;
3905 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3906 /* User limit mode is unset. Remove user limit */
3907 channel->user_limit = 0;
3910 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3911 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3912 /* Passphrase has been set to channel */
3914 /* Get the passphrase */
3915 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3917 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3918 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3922 /* Save the passphrase */
3923 passphrase = channel->passphrase = strdup(tmp);
3926 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3927 /* Passphrase mode is unset. remove the passphrase */
3928 if (channel->passphrase) {
3929 silc_free(channel->passphrase);
3930 channel->passphrase = NULL;
3935 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3936 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3937 /* Cipher to use protect the traffic */
3938 SilcCipher newkey, oldkey;
3941 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3943 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3944 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3948 /* Delete old cipher and allocate the new one */
3949 if (!silc_cipher_alloc(cipher, &newkey)) {
3950 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3951 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3955 oldkey = channel->channel_key;
3956 channel->channel_key = newkey;
3958 /* Re-generate channel key */
3959 if (!silc_server_create_channel_key(server, channel, 0)) {
3960 /* We don't have new key, revert to old one */
3961 channel->channel_key = oldkey;
3965 /* Remove old channel key for good */
3966 silc_cipher_free(oldkey);
3968 /* Send the channel key. This sends it to our local clients and if
3969 we are normal server to our router as well. */
3970 silc_server_send_channel_key(server, NULL, channel,
3971 server->server_type == SILC_ROUTER ?
3972 FALSE : !server->standalone);
3975 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3976 /* Cipher mode is unset. Remove the cipher and revert back to
3978 SilcCipher newkey, oldkey;
3979 cipher = channel->cipher;
3981 /* Delete old cipher and allocate default one */
3982 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
3983 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3984 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3988 oldkey = channel->channel_key;
3989 channel->channel_key = newkey;
3991 /* Re-generate channel key */
3992 if (!silc_server_create_channel_key(server, channel, 0)) {
3993 /* We don't have new key, revert to old one */
3994 channel->channel_key = oldkey;
3998 /* Remove old channel key for good */
3999 silc_cipher_free(oldkey);
4001 /* Send the channel key. This sends it to our local clients and if
4002 we are normal server to our router as well. */
4003 silc_server_send_channel_key(server, NULL, channel,
4004 server->server_type == SILC_ROUTER ?
4005 FALSE : !server->standalone);
4009 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
4010 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
4011 /* HMAC to use protect the traffic */
4012 unsigned char hash[32];
4016 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4018 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4019 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4023 /* Delete old hmac and allocate the new one */
4024 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4025 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4026 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4030 silc_hmac_free(channel->hmac);
4031 channel->hmac = newhmac;
4033 /* Set the HMAC key out of current channel key. The client must do
4035 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4036 channel->key_len / 8, hash);
4037 silc_hmac_set_key(channel->hmac, hash,
4038 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4039 memset(hash, 0, sizeof(hash));
4042 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4043 /* Hmac mode is unset. Remove the hmac and revert back to
4046 unsigned char hash[32];
4047 hmac = channel->hmac_name;
4049 /* Delete old hmac and allocate default one */
4050 silc_hmac_free(channel->hmac);
4051 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4052 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4053 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4057 silc_hmac_free(channel->hmac);
4058 channel->hmac = newhmac;
4060 /* Set the HMAC key out of current channel key. The client must do
4062 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4063 channel->key_len / 8,
4065 silc_hmac_set_key(channel->hmac, hash,
4066 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4067 memset(hash, 0, sizeof(hash));
4071 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4072 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4073 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4074 /* Set the founder authentication */
4075 SilcAuthPayload auth;
4077 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4079 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4080 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4084 auth = silc_auth_payload_parse(tmp, tmp_len);
4086 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4087 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4091 /* Save the public key */
4092 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
4093 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
4096 channel->founder_method = silc_auth_get_method(auth);
4098 if (channel->founder_method == SILC_AUTH_PASSWORD) {
4099 tmp = silc_auth_get_data(auth, &tmp_len);
4100 channel->founder_passwd =
4101 silc_calloc(tmp_len + 1, sizeof(*channel->founder_passwd));
4102 memcpy(channel->founder_passwd, tmp, tmp_len);
4103 channel->founder_passwd_len = tmp_len;
4105 /* Verify the payload before setting the mode */
4106 if (!silc_auth_verify(auth, channel->founder_method,
4107 channel->founder_key, 0, idata->hash,
4108 client->id, SILC_ID_CLIENT)) {
4109 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4110 SILC_STATUS_ERR_AUTH_FAILED);
4115 silc_auth_payload_free(auth);
4119 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4120 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4121 if (channel->founder_key)
4122 silc_pkcs_public_key_free(channel->founder_key);
4123 if (channel->founder_passwd) {
4124 silc_free(channel->founder_passwd);
4125 channel->founder_passwd = NULL;
4131 /* Finally, set the mode */
4132 channel->mode = mode_mask;
4134 /* Send CMODE_CHANGE notify. */
4135 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4136 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4137 SILC_NOTIFY_TYPE_CMODE_CHANGE, 5,
4138 cidp->data, cidp->len,
4140 cipher, cipher ? strlen(cipher) : 0,
4141 hmac, hmac ? strlen(hmac) : 0,
4142 passphrase, passphrase ?
4143 strlen(passphrase) : 0);
4145 /* Set CMODE notify type to network */
4146 if (!server->standalone)
4147 silc_server_send_notify_cmode(server, server->router->connection,
4148 server->server_type == SILC_ROUTER ?
4149 TRUE : FALSE, channel,
4150 mode_mask, client->id, SILC_ID_CLIENT,
4151 cipher, hmac, passphrase);
4153 /* Send command reply to sender */
4154 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4155 SILC_STATUS_OK, ident, 2,
4156 2, tmp_id, tmp_len2,
4158 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4159 packet->data, packet->len, FALSE);
4161 silc_buffer_free(packet);
4162 silc_free(channel_id);
4163 silc_buffer_free(cidp);
4166 silc_server_command_free(cmd);
4169 /* Server side of CUMODE command. Changes client's mode on a channel. */
4171 SILC_SERVER_CMD_FUNC(cumode)
4173 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4174 SilcServer server = cmd->server;
4175 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4176 SilcIDListData idata = (SilcIDListData)client;
4177 SilcChannelID *channel_id;
4178 SilcClientID *client_id;
4179 SilcChannelEntry channel;
4180 SilcClientEntry target_client;
4181 SilcChannelClientEntry chl;
4182 SilcBuffer packet, idp;
4183 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4184 uint32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4186 uint16 ident = silc_command_get_ident(cmd->payload);
4188 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4190 /* Get Channel ID */
4191 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4193 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4194 SILC_STATUS_ERR_NO_CHANNEL_ID);
4197 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
4199 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4200 SILC_STATUS_ERR_NO_CHANNEL_ID);
4204 /* Get channel entry */
4205 channel = silc_idlist_find_channel_by_id(server->local_list,
4208 channel = silc_idlist_find_channel_by_id(server->global_list,
4211 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4212 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4217 /* Check whether sender is on the channel */
4218 if (!silc_server_client_on_channel(client, channel)) {
4219 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4220 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4224 /* Check that client has rights to change other's rights */
4225 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4226 sender_mask = chl->mode;
4228 /* Get the target client's channel mode mask */
4229 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4231 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4232 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4235 SILC_GET32_MSB(target_mask, tmp_mask);
4237 /* Get target Client ID */
4238 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4240 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4241 SILC_STATUS_ERR_NO_CLIENT_ID);
4244 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
4246 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4247 SILC_STATUS_ERR_NO_CLIENT_ID);
4251 /* Get target client's entry */
4252 target_client = silc_idlist_find_client_by_id(server->local_list,
4253 client_id, TRUE, NULL);
4254 if (!target_client) {
4255 target_client = silc_idlist_find_client_by_id(server->global_list,
4256 client_id, TRUE, NULL);
4259 if (target_client != client &&
4260 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4261 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4262 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4263 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4267 /* Check whether target client is on the channel */
4268 if (target_client != client) {
4269 if (!silc_server_client_on_channel(target_client, channel)) {
4270 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4271 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4275 /* Get entry to the channel user list */
4276 silc_hash_table_find(channel->user_list, target_client, NULL,
4284 /* If the target client is founder, no one else can change their mode
4286 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
4287 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4288 SILC_STATUS_ERR_NOT_YOU);
4292 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4293 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4294 /* The client tries to claim the founder rights. */
4295 unsigned char *tmp_auth;
4296 uint32 tmp_auth_len, auth_len;
4299 if (target_client != client) {
4300 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4301 SILC_STATUS_ERR_NOT_YOU);
4305 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4306 !channel->founder_key || !idata->public_key ||
4307 !silc_pkcs_public_key_compare(channel->founder_key,
4308 idata->public_key)) {
4309 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4310 SILC_STATUS_ERR_NOT_YOU);
4314 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4316 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4317 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4321 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4322 (void *)channel->founder_passwd : (void *)channel->founder_key);
4323 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4324 channel->founder_passwd_len : 0);
4326 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4327 channel->founder_method, auth, auth_len,
4328 idata->hash, client->id, SILC_ID_CLIENT)) {
4329 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4330 SILC_STATUS_ERR_AUTH_FAILED);
4334 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4338 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4339 if (target_client == client) {
4340 /* Remove channel founder rights from itself */
4341 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4344 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4345 SILC_STATUS_ERR_NOT_YOU);
4351 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4352 /* Promote to operator */
4353 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4354 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4355 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4356 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4357 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4361 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4365 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4366 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4367 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4368 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4369 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4373 /* Demote to normal user */
4374 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4379 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4380 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4382 /* Send notify to channel, notify only if mode was actually changed. */
4384 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4385 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4386 idp->data, idp->len,
4390 /* Set CUMODE notify type to network */
4391 if (!server->standalone)
4392 silc_server_send_notify_cumode(server, server->router->connection,
4393 server->server_type == SILC_ROUTER ?
4394 TRUE : FALSE, channel,
4395 target_mask, client->id,
4400 /* Send command reply to sender */
4401 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4402 SILC_STATUS_OK, ident, 3,
4404 3, tmp_ch_id, tmp_ch_len,
4405 4, tmp_id, tmp_len);
4406 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4407 packet->data, packet->len, FALSE);
4409 silc_buffer_free(packet);
4410 silc_free(channel_id);
4411 silc_free(client_id);
4412 silc_buffer_free(idp);
4415 silc_server_command_free(cmd);
4418 /* Server side of KICK command. Kicks client out of channel. */
4420 SILC_SERVER_CMD_FUNC(kick)
4422 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4423 SilcServer server = cmd->server;
4424 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4425 SilcClientEntry target_client;
4426 SilcChannelID *channel_id;
4427 SilcClientID *client_id;
4428 SilcChannelEntry channel;
4429 SilcChannelClientEntry chl;
4431 uint32 tmp_len, target_idp_len;
4432 unsigned char *tmp, *comment, *target_idp;
4434 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4436 /* Get Channel ID */
4437 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4439 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4440 SILC_STATUS_ERR_NO_CHANNEL_ID);
4443 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
4445 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4446 SILC_STATUS_ERR_NO_CHANNEL_ID);
4450 /* Get channel entry */
4451 channel = silc_idlist_find_channel_by_id(server->local_list,
4454 channel = silc_idlist_find_channel_by_id(server->local_list,
4457 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4458 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4463 /* Check whether sender is on the channel */
4464 if (!silc_server_client_on_channel(client, channel)) {
4465 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4466 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4470 /* Check that the kicker is channel operator or channel founder */
4471 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4472 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4473 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4474 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4478 /* Get target Client ID */
4479 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4481 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4482 SILC_STATUS_ERR_NO_CLIENT_ID);
4485 client_id = silc_id_payload_parse_id(target_idp, target_idp_len);
4487 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4488 SILC_STATUS_ERR_NO_CLIENT_ID);
4492 /* Get target client's entry */
4493 target_client = silc_idlist_find_client_by_id(server->local_list,
4494 client_id, TRUE, NULL);
4495 if (!target_client) {
4496 target_client = silc_idlist_find_client_by_id(server->global_list,
4497 client_id, TRUE, NULL);
4500 /* Check that the target client is not channel founder. Channel founder
4501 cannot be kicked from the channel. */
4502 silc_hash_table_find(channel->user_list, target_client, NULL, (void *)&chl);
4503 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4504 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4505 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4509 /* Check whether target client is on the channel */
4510 if (!silc_server_client_on_channel(target_client, channel)) {
4511 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4512 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4518 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4522 /* Send command reply to sender */
4523 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4526 /* Send KICKED notify to local clients on the channel */
4527 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4528 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4529 SILC_NOTIFY_TYPE_KICKED, 3,
4530 target_idp, target_idp_len,
4531 comment, comment ? strlen(comment) : 0,
4532 idp->data, idp->len);
4533 silc_buffer_free(idp);
4535 /* Remove the client from the channel. If the channel does not exist
4536 after removing the client then the client kicked itself off the channel
4537 and we don't have to send anything after that. */
4538 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4539 target_client, FALSE))
4542 /* Send KICKED notify to primary route */
4543 if (!server->standalone)
4544 silc_server_send_notify_kicked(server, server->router->connection,
4545 server->server_type == SILC_ROUTER ?
4546 TRUE : FALSE, channel,
4547 target_client->id, comment);
4549 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4550 /* Re-generate channel key */
4551 if (!silc_server_create_channel_key(server, channel, 0))
4554 /* Send the channel key to the channel. The key of course is not sent
4555 to the client who was kicked off the channel. */
4556 silc_server_send_channel_key(server, target_client->connection, channel,
4557 server->server_type == SILC_ROUTER ?
4558 FALSE : !server->standalone);
4562 silc_server_command_free(cmd);
4565 /* Server side of OPER command. Client uses this comand to obtain server
4566 operator privileges to this server/router. */
4568 SILC_SERVER_CMD_FUNC(oper)
4570 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4571 SilcServer server = cmd->server;
4572 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4573 unsigned char *username, *auth;
4575 SilcServerConfigSectionAdminConnection *admin;
4576 SilcIDListData idata = (SilcIDListData)client;
4578 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4580 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4583 /* Get the username */
4584 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4586 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4587 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4591 /* Get the admin configuration */
4592 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4593 username, client->nickname);
4595 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4596 username, client->nickname);
4598 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4599 SILC_STATUS_ERR_AUTH_FAILED);
4604 /* Get the authentication payload */
4605 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4607 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4608 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4612 /* Verify the authentication data */
4613 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4614 admin->auth_data, admin->auth_data_len,
4615 idata->hash, client->id, SILC_ID_CLIENT)) {
4616 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4617 SILC_STATUS_ERR_AUTH_FAILED);
4621 /* Client is now server operator */
4622 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4624 /* Send UMODE change to primary router */
4625 if (!server->standalone)
4626 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4627 client->id, client->mode);
4629 /* Send reply to the sender */
4630 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4634 silc_server_command_free(cmd);
4637 /* Server side of SILCOPER command. Client uses this comand to obtain router
4638 operator privileges to this router. */
4640 SILC_SERVER_CMD_FUNC(silcoper)
4642 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4643 SilcServer server = cmd->server;
4644 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4645 unsigned char *username, *auth;
4647 SilcServerConfigSectionAdminConnection *admin;
4648 SilcIDListData idata = (SilcIDListData)client;
4650 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4652 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4655 if (server->server_type != SILC_ROUTER) {
4656 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4657 SILC_STATUS_ERR_AUTH_FAILED);
4661 /* Get the username */
4662 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4664 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4665 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4669 /* Get the admin configuration */
4670 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4671 username, client->nickname);
4673 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4674 username, client->nickname);
4676 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4677 SILC_STATUS_ERR_AUTH_FAILED);
4682 /* Get the authentication payload */
4683 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4685 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4686 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4690 /* Verify the authentication data */
4691 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4692 admin->auth_data, admin->auth_data_len,
4693 idata->hash, client->id, SILC_ID_CLIENT)) {
4694 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4695 SILC_STATUS_ERR_AUTH_FAILED);
4699 /* Client is now router operator */
4700 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4702 /* Send UMODE change to primary router */
4703 if (!server->standalone)
4704 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4705 client->id, client->mode);
4707 /* Send reply to the sender */
4708 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4712 silc_server_command_free(cmd);
4715 /* Server side command of CONNECT. Connects us to the specified remote
4716 server or router. */
4718 SILC_SERVER_CMD_FUNC(connect)
4720 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4721 SilcServer server = cmd->server;
4722 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4723 unsigned char *tmp, *host;
4725 uint32 port = SILC_PORT;
4727 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CONNECT, cmd, 1, 2);
4729 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4732 /* Check whether client has the permissions. */
4733 if (client->mode == SILC_UMODE_NONE) {
4734 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4735 SILC_STATUS_ERR_NO_SERVER_PRIV);
4739 if (server->server_type == SILC_ROUTER &&
4740 client->mode & SILC_UMODE_SERVER_OPERATOR) {
4741 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4742 SILC_STATUS_ERR_NO_ROUTER_PRIV);
4746 /* Get the remote server */
4747 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4749 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4750 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4755 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4757 SILC_GET32_MSB(port, tmp);
4759 /* Create the connection. It is done with timeout and is async. */
4760 silc_server_create_connection(server, host, port);
4762 /* Send reply to the sender */
4763 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4767 silc_server_command_free(cmd);
4770 /* Server side of command BAN. This is used to manage the ban list of the
4771 channel. To add clients and remove clients from the ban list. */
4773 SILC_SERVER_CMD_FUNC(ban)
4775 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4776 SilcServer server = cmd->server;
4777 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4779 SilcChannelEntry channel;
4780 SilcChannelClientEntry chl;
4781 SilcChannelID *channel_id = NULL;
4782 unsigned char *id, *add, *del;
4783 uint32 id_len, tmp_len;
4784 uint16 ident = silc_command_get_ident(cmd->payload);
4786 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4789 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4791 /* Get Channel ID */
4792 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4794 channel_id = silc_id_payload_parse_id(id, id_len);
4796 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4797 SILC_STATUS_ERR_NO_CHANNEL_ID);
4802 /* Get channel entry. The server must know about the channel since the
4803 client is expected to be on the channel. */
4804 channel = silc_idlist_find_channel_by_id(server->local_list,
4807 channel = silc_idlist_find_channel_by_id(server->global_list,
4810 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4811 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4816 /* Check whether this client is on the channel */
4817 if (!silc_server_client_on_channel(client, channel)) {
4818 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4819 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4823 /* Get entry to the channel user list */
4824 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4826 /* The client must be at least channel operator. */
4827 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4828 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4829 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4833 /* Get the new ban and add it to the ban list */
4834 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4836 if (!channel->ban_list)
4837 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4839 channel->ban_list = silc_realloc(channel->ban_list,
4840 sizeof(*channel->ban_list) *
4842 strlen(channel->ban_list) + 2));
4843 if (add[tmp_len - 1] == ',')
4844 add[tmp_len - 1] = '\0';
4846 strncat(channel->ban_list, add, tmp_len);
4847 strncat(channel->ban_list, ",", 1);
4850 /* Get the ban to be removed and remove it from the list */
4851 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4852 if (del && channel->ban_list) {
4853 char *start, *end, *n;
4855 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4856 silc_free(channel->ban_list);
4857 channel->ban_list = NULL;
4859 start = strstr(channel->ban_list, del);
4860 if (start && strlen(start) >= tmp_len) {
4861 end = start + tmp_len;
4862 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4863 strncat(n, channel->ban_list, start - channel->ban_list);
4864 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4866 silc_free(channel->ban_list);
4867 channel->ban_list = n;
4872 /* Send the BAN notify type to our primary router. */
4873 if (!server->standalone && (add || del))
4874 silc_server_send_notify_ban(server, server->router->connection,
4875 server->server_type == SILC_ROUTER ?
4876 TRUE : FALSE, channel, add, del);
4878 /* Send the reply back to the client */
4880 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4881 SILC_STATUS_OK, ident, 2,
4883 3, channel->ban_list,
4885 strlen(channel->ban_list) - 1 : 0);
4886 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4887 packet->data, packet->len, FALSE);
4889 silc_buffer_free(packet);
4892 silc_free(channel_id);
4893 silc_server_command_free(cmd);
4896 /* Server side command of CLOSE. Closes connection to a specified server. */
4898 SILC_SERVER_CMD_FUNC(close)
4900 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4901 SilcServer server = cmd->server;
4902 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4903 SilcServerEntry server_entry;
4904 SilcSocketConnection sock;
4907 unsigned char *name;
4908 uint32 port = SILC_PORT;
4910 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CLOSE, cmd, 1, 2);
4912 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4915 /* Check whether client has the permissions. */
4916 if (client->mode == SILC_UMODE_NONE) {
4917 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4918 SILC_STATUS_ERR_NO_SERVER_PRIV);
4922 /* Get the remote server */
4923 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4925 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4926 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4931 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4933 SILC_GET32_MSB(port, tmp);
4935 server_entry = silc_idlist_find_server_by_conn(server->local_list,
4936 name, port, FALSE, NULL);
4938 server_entry = silc_idlist_find_server_by_conn(server->global_list,
4939 name, port, FALSE, NULL);
4940 if (!server_entry) {
4941 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4942 SILC_STATUS_ERR_NO_SERVER_ID);
4946 /* Send reply to the sender */
4947 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4950 /* Close the connection to the server */
4951 sock = (SilcSocketConnection)server_entry->connection;
4953 /* If we shutdown primary router connection manually then don't trigger
4954 any reconnect or backup router connections, by setting the router
4956 if (server->router == server_entry) {
4957 server->id_entry->router = NULL;
4958 server->router = NULL;
4959 server->standalone = TRUE;
4961 silc_server_free_sock_user_data(server, sock);
4962 silc_server_close_connection(server, sock);
4965 silc_server_command_free(cmd);
4968 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4969 active connections. */
4971 SILC_SERVER_CMD_FUNC(shutdown)
4973 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4974 SilcServer server = cmd->server;
4975 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4977 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4979 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4982 /* Check whether client has the permission. */
4983 if (client->mode == SILC_UMODE_NONE) {
4984 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4985 SILC_STATUS_ERR_NO_SERVER_PRIV);
4989 /* Send reply to the sender */
4990 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4993 /* Then, gracefully, or not, bring the server down. */
4994 silc_server_stop(server);
4998 silc_server_command_free(cmd);
5001 /* Server side command of LEAVE. Removes client from a channel. */
5003 SILC_SERVER_CMD_FUNC(leave)
5005 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5006 SilcServer server = cmd->server;
5007 SilcSocketConnection sock = cmd->sock;
5008 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
5009 SilcChannelID *id = NULL;
5010 SilcChannelEntry channel;
5014 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
5016 /* Get Channel ID */
5017 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
5019 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5020 SILC_STATUS_ERR_NO_CHANNEL_ID);
5023 id = silc_id_payload_parse_id(tmp, len);
5025 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5026 SILC_STATUS_ERR_NO_CHANNEL_ID);
5030 /* Get channel entry */
5031 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5033 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5035 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5036 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5041 /* Check whether this client is on the channel */
5042 if (!silc_server_client_on_channel(id_entry, channel)) {
5043 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5044 SILC_STATUS_ERR_NOT_ON_CHANNEL);
5048 /* Notify routers that they should remove this client from their list
5049 of clients on the channel. Send LEAVE notify type. */
5050 if (!server->standalone)
5051 silc_server_send_notify_leave(server, server->router->connection,
5052 server->server_type == SILC_ROUTER ?
5053 TRUE : FALSE, channel, id_entry->id);
5055 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5058 /* Remove client from channel */
5059 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5061 /* If the channel does not exist anymore we won't send anything */
5064 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5065 /* Re-generate channel key */
5066 if (!silc_server_create_channel_key(server, channel, 0))
5069 /* Send the channel key */
5070 silc_server_send_channel_key(server, NULL, channel,
5071 server->server_type == SILC_ROUTER ?
5072 FALSE : !server->standalone);
5077 silc_server_command_free(cmd);
5080 /* Server side of command USERS. Resolves clients and their USERS currently
5081 joined on the requested channel. The list of Client ID's and their modes
5082 on the channel is sent back. */
5084 SILC_SERVER_CMD_FUNC(users)
5086 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5087 SilcServer server = cmd->server;
5088 SilcChannelEntry channel;
5089 SilcChannelID *id = NULL;
5090 SilcBuffer packet, idp;
5091 unsigned char *channel_id;
5092 uint32 channel_id_len;
5093 SilcBuffer client_id_list;
5094 SilcBuffer client_mode_list;
5095 unsigned char lc[4];
5096 uint32 list_count = 0;
5097 uint16 ident = silc_command_get_ident(cmd->payload);
5100 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5102 /* Get Channel ID */
5103 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5105 /* Get channel name */
5106 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5108 if (!channel_id && !channel_name) {
5109 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5110 SILC_STATUS_ERR_NO_CHANNEL_ID);
5115 id = silc_id_payload_parse_id(channel_id, channel_id_len);
5117 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5118 SILC_STATUS_ERR_NO_CHANNEL_ID);
5123 /* If we are server and we don't know about this channel we will send
5124 the command to our router. If we know about the channel then we also
5125 have the list of users already. */
5127 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5129 channel = silc_idlist_find_channel_by_name(server->local_list,
5130 channel_name, NULL);
5132 if (!channel || channel->disabled) {
5133 if (server->server_type != SILC_ROUTER && !server->standalone &&
5137 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5138 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5140 /* Send USERS command */
5141 silc_server_packet_send(server, server->router->connection,
5142 SILC_PACKET_COMMAND, cmd->packet->flags,
5143 tmpbuf->data, tmpbuf->len, TRUE);
5145 /* Reprocess this packet after received reply */
5146 silc_server_command_pending(server, SILC_COMMAND_USERS,
5147 silc_command_get_ident(cmd->payload),
5148 silc_server_command_destructor,
5149 silc_server_command_users,
5150 silc_server_command_dup(cmd));
5151 cmd->pending = TRUE;
5152 silc_command_set_ident(cmd->payload, ident);
5154 silc_buffer_free(tmpbuf);
5159 /* Check the global list as well. */
5161 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5163 channel = silc_idlist_find_channel_by_name(server->global_list,
5164 channel_name, NULL);
5166 /* Channel really does not exist */
5167 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5168 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5173 /* If the channel is private or secret do not send anything, unless the
5174 user requesting this command is on the channel. */
5175 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5176 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5177 && !silc_server_client_on_channel(cmd->sock->user_data, channel)) {
5178 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5179 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5184 (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
5185 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5186 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5191 /* Get the users list */
5192 silc_server_get_users_on_channel(server, channel, &client_id_list,
5193 &client_mode_list, &list_count);
5196 SILC_PUT32_MSB(list_count, lc);
5199 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5200 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5201 SILC_STATUS_OK, ident, 4,
5202 2, idp->data, idp->len,
5204 4, client_id_list->data,
5205 client_id_list->len,
5206 5, client_mode_list->data,
5207 client_mode_list->len);
5208 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5209 packet->data, packet->len, FALSE);
5211 silc_buffer_free(idp);
5212 silc_buffer_free(packet);
5213 silc_buffer_free(client_id_list);
5214 silc_buffer_free(client_mode_list);
5218 silc_server_command_free(cmd);
5221 /* Server side of command GETKEY. This fetches the client's public key
5222 from the server where to the client is connected. */
5224 SILC_SERVER_CMD_FUNC(getkey)
5226 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5227 SilcServer server = cmd->server;
5229 SilcClientEntry client;
5230 SilcServerEntry server_entry;
5231 SilcClientID *client_id = NULL;
5232 SilcServerID *server_id = NULL;
5233 SilcIDPayload idp = NULL;
5234 uint16 ident = silc_command_get_ident(cmd->payload);
5235 unsigned char *tmp, *pkdata;
5236 uint32 tmp_len, pklen;
5237 SilcBuffer pk = NULL;
5240 SILC_LOG_DEBUG(("Start"));
5242 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5244 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5245 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5248 idp = silc_id_payload_parse(tmp, tmp_len);
5250 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5251 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5255 id_type = silc_id_payload_get_type(idp);
5256 if (id_type == SILC_ID_CLIENT) {
5257 client_id = silc_id_payload_get_id(idp);
5259 /* If the client is not found from local list there is no chance it
5260 would be locally connected client so send the command further. */
5261 client = silc_idlist_find_client_by_id(server->local_list,
5262 client_id, TRUE, NULL);
5264 client = silc_idlist_find_client_by_id(server->global_list,
5265 client_id, TRUE, NULL);
5267 if ((!client && !cmd->pending && !server->standalone) ||
5268 (client && !client->connection && !cmd->pending) ||
5269 (client && !client->data.public_key && !cmd->pending)) {
5272 SilcSocketConnection dest_sock;
5274 dest_sock = silc_server_get_client_route(server, NULL, 0,
5279 old_ident = silc_command_get_ident(cmd->payload);
5280 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5281 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5283 silc_server_packet_send(server, dest_sock,
5284 SILC_PACKET_COMMAND, cmd->packet->flags,
5285 tmpbuf->data, tmpbuf->len, TRUE);
5287 /* Reprocess this packet after received reply from router */
5288 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5289 silc_command_get_ident(cmd->payload),
5290 silc_server_command_destructor,
5291 silc_server_command_getkey,
5292 silc_server_command_dup(cmd));
5293 cmd->pending = TRUE;
5295 silc_command_set_ident(cmd->payload, old_ident);
5296 silc_buffer_free(tmpbuf);
5301 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5302 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5306 /* The client is locally connected, just get the public key and
5307 send it back. If they key does not exist then do not send it,
5308 send just OK reply */
5309 if (!client->data.public_key) {
5313 tmp = silc_pkcs_public_key_encode(client->data.public_key, &tmp_len);
5314 pk = silc_buffer_alloc(4 + tmp_len);
5315 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5316 silc_buffer_format(pk,
5317 SILC_STR_UI_SHORT(tmp_len),
5318 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5319 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5325 } else if (id_type == SILC_ID_SERVER) {
5326 server_id = silc_id_payload_get_id(idp);
5328 /* If the server is not found from local list there is no chance it
5329 would be locally connected server so send the command further. */
5330 server_entry = silc_idlist_find_server_by_id(server->local_list,
5331 server_id, TRUE, NULL);
5333 server_entry = silc_idlist_find_server_by_id(server->global_list,
5334 server_id, TRUE, NULL);
5336 if (server_entry != server->id_entry &&
5337 ((!server_entry && !cmd->pending && !server->standalone) ||
5338 (server_entry && !server_entry->connection && !cmd->pending &&
5339 !server->standalone) ||
5340 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5341 !server->standalone))) {
5345 old_ident = silc_command_get_ident(cmd->payload);
5346 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5347 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5349 silc_server_packet_send(server, server->router->connection,
5350 SILC_PACKET_COMMAND, cmd->packet->flags,
5351 tmpbuf->data, tmpbuf->len, TRUE);
5353 /* Reprocess this packet after received reply from router */
5354 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5355 silc_command_get_ident(cmd->payload),
5356 silc_server_command_destructor,
5357 silc_server_command_getkey,
5358 silc_server_command_dup(cmd));
5359 cmd->pending = TRUE;
5361 silc_command_set_ident(cmd->payload, old_ident);
5362 silc_buffer_free(tmpbuf);
5366 if (!server_entry) {
5367 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5368 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5372 /* If they key does not exist then do not send it, send just OK reply */
5373 if (!server_entry->data.public_key) {
5377 tmp = silc_pkcs_public_key_encode(server_entry->data.public_key,
5379 pk = silc_buffer_alloc(4 + tmp_len);
5380 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5381 silc_buffer_format(pk,
5382 SILC_STR_UI_SHORT(tmp_len),
5383 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5384 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5394 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5395 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5396 SILC_STATUS_OK, ident,
5400 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5401 packet->data, packet->len, FALSE);
5402 silc_buffer_free(packet);
5405 silc_buffer_free(pk);
5409 silc_id_payload_free(idp);
5410 silc_free(client_id);
5411 silc_free(server_id);
5412 silc_server_command_free(cmd);