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++) {
755 /* Sanity check, however these should never fail. However, as
756 this sanity check has been added here they have failed. */
757 if (!entry->nickname || !entry->username || !entry->userinfo) {
758 SILC_LOG_ERROR(("********* if (!entry->nickname || !entry->username "
759 "|| !entry->userinfo) triggered: should have not!"));
765 status = SILC_STATUS_LIST_ITEM;
766 if (valid_count > 1 && k == valid_count - 1)
767 status = SILC_STATUS_LIST_END;
768 if (count && k - 1 == count)
769 status = SILC_STATUS_LIST_END;
771 /* Send WHOIS reply */
772 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
773 tmp = silc_argument_get_first_arg(cmd->args, NULL);
775 memset(uh, 0, sizeof(uh));
776 memset(nh, 0, sizeof(nh));
777 memset(idle, 0, sizeof(idle));
779 strncat(nh, entry->nickname, strlen(entry->nickname));
780 if (!strchr(entry->nickname, '@')) {
782 if (entry->servername) {
783 strncat(nh, entry->servername, strlen(entry->servername));
785 len = entry->router ? strlen(entry->router->server_name) :
786 strlen(server->server_name);
787 strncat(nh, entry->router ? entry->router->server_name :
788 server->server_name, len);
792 strncat(uh, entry->username, strlen(entry->username));
793 if (!strchr(entry->username, '@')) {
795 hsock = (SilcSocketConnection)entry->connection;
796 len = strlen(hsock->hostname);
797 strncat(uh, hsock->hostname, len);
800 channels = silc_server_get_client_channel_list(server, entry);
802 if (entry->data.fingerprint[0] != 0 && entry->data.fingerprint[1] != 0)
803 fingerprint = entry->data.fingerprint;
807 SILC_PUT32_MSB(entry->mode, mode);
809 if (entry->connection) {
810 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
814 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
816 2, idp->data, idp->len,
820 strlen(entry->userinfo),
821 6, channels ? channels->data : NULL,
822 channels ? channels->len : 0,
826 fingerprint ? 20 : 0);
828 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
829 0, packet->data, packet->len, FALSE);
831 silc_buffer_free(packet);
832 silc_buffer_free(idp);
834 silc_buffer_free(channels);
841 silc_server_command_whois_send_router(SilcServerCommandContext cmd)
843 SilcServer server = cmd->server;
847 old_ident = silc_command_get_ident(cmd->payload);
848 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
849 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
851 /* Send WHOIS command to our router */
852 silc_server_packet_send(server, (SilcSocketConnection)
853 server->router->connection,
854 SILC_PACKET_COMMAND, cmd->packet->flags,
855 tmpbuf->data, tmpbuf->len, TRUE);
857 /* Reprocess this packet after received reply from router */
858 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
859 silc_command_get_ident(cmd->payload),
860 silc_server_command_destructor,
861 silc_server_command_whois,
862 silc_server_command_dup(cmd));
864 silc_command_set_ident(cmd->payload, old_ident);
865 silc_buffer_free(tmpbuf);
869 silc_server_command_whois_process(SilcServerCommandContext cmd)
871 SilcServer server = cmd->server;
872 char *nick = NULL, *server_name = NULL;
874 SilcClientEntry *clients = NULL, entry;
875 SilcClientID **client_id = NULL;
876 uint32 client_id_count = 0, clients_count = 0;
878 bool check_global = FALSE;
880 /* Parse the whois request */
881 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
882 &nick, &server_name, &count,
886 /* Send the WHOIS request to the router only if it included nickname.
887 Since nicknames can be expanded into many clients we need to send it
888 to router. If the WHOIS included only client ID's we will check them
889 first locally since we just might have them. */
890 if (nick && !client_id_count && cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
891 server->server_type == SILC_SERVER && !cmd->pending &&
892 !server->standalone) {
893 silc_server_command_whois_send_router(cmd);
898 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
900 else if (server->server_type != SILC_SERVER)
903 /* Get all clients matching that ID or nickname from local list */
904 if (client_id_count) {
905 /* Check all Client ID's received in the command packet */
906 for (i = 0; i < client_id_count; i++) {
907 entry = silc_idlist_find_client_by_id(server->local_list,
908 client_id[i], TRUE, NULL);
909 if (!entry && check_global)
910 entry = silc_idlist_find_client_by_id(server->global_list,
911 client_id[i], TRUE, NULL);
913 clients = silc_realloc(clients, sizeof(*clients) *
914 (clients_count + 1));
915 clients[clients_count++] = entry;
917 /* If we are normal server and did not send the request first to router
918 do it now, since we do not have the Client ID information. */
919 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
920 server->server_type == SILC_SERVER && !cmd->pending &&
921 !server->standalone) {
922 silc_server_command_whois_send_router(cmd);
929 /* Find by nickname */
930 if (!silc_idlist_get_clients_by_hash(server->local_list,
931 nick, server->md5hash,
932 &clients, &clients_count))
933 silc_idlist_get_clients_by_nickname(server->local_list,
935 &clients, &clients_count);
937 if (!silc_idlist_get_clients_by_hash(server->global_list,
938 nick, server->md5hash,
939 &clients, &clients_count))
940 silc_idlist_get_clients_by_nickname(server->global_list,
942 &clients, &clients_count);
947 /* If we are normal server and did not send the request first to router
948 do it now, since we do not have the information. */
949 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
950 server->server_type == SILC_SERVER && !cmd->pending &&
951 !server->standalone) {
952 silc_server_command_whois_send_router(cmd);
957 /* Such client(s) really does not exist in the SILC network. */
958 if (!client_id_count) {
959 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
960 SILC_STATUS_ERR_NO_SUCH_NICK,
961 3, nick, strlen(nick));
963 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
964 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
965 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
966 2, idp->data, idp->len);
967 silc_buffer_free(idp);
972 /* Router always finds the client entry if it exists in the SILC network.
973 However, it might be incomplete entry and does not include all the
974 mandatory fields that WHOIS command reply requires. Check for these and
975 make query from the server who owns the client if some fields are
977 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
982 /* Send the command reply */
983 silc_server_command_whois_send_reply(cmd, clients, clients_count,
984 count, nick, client_id);
987 if (client_id_count) {
988 for (i = 0; i < client_id_count; i++)
989 silc_free(client_id[i]);
990 silc_free(client_id);
994 silc_free(server_name);
999 /* Server side of command WHOIS. Processes user's query and sends found
1000 results as command replies back to the client. */
1002 SILC_SERVER_CMD_FUNC(whois)
1004 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1007 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 3328);
1009 ret = silc_server_command_whois_process(cmd);
1012 silc_server_command_free(cmd);
1015 /******************************************************************************
1019 ******************************************************************************/
1022 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
1030 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1032 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
1033 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1037 /* Get the nickname@server string and parse it. */
1038 silc_parse_userfqdn(tmp, nickname, server_name);
1040 /* Get the max count of reply messages allowed */
1041 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1051 silc_server_command_whowas_check(SilcServerCommandContext cmd,
1052 SilcClientEntry *clients,
1053 uint32 clients_count)
1055 SilcServer server = cmd->server;
1057 SilcClientEntry entry;
1059 for (i = 0; i < clients_count; i++) {
1062 if (!entry->nickname || !entry->username) {
1069 old_ident = silc_command_get_ident(cmd->payload);
1070 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1071 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1073 /* Send WHOWAS command */
1074 silc_server_packet_send(server, entry->router->connection,
1075 SILC_PACKET_COMMAND, cmd->packet->flags,
1076 tmpbuf->data, tmpbuf->len, TRUE);
1078 /* Reprocess this packet after received reply */
1079 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1080 silc_command_get_ident(cmd->payload),
1081 silc_server_command_destructor,
1082 silc_server_command_whowas,
1083 silc_server_command_dup(cmd));
1084 cmd->pending = TRUE;
1086 silc_command_set_ident(cmd->payload, old_ident);
1088 silc_buffer_free(tmpbuf);
1097 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1098 SilcClientEntry *clients,
1099 uint32 clients_count)
1101 SilcServer server = cmd->server;
1103 int i, count = 0, len;
1104 SilcBuffer packet, idp;
1105 SilcClientEntry entry = NULL;
1106 SilcCommandStatus status;
1107 uint16 ident = silc_command_get_ident(cmd->payload);
1109 char nh[256], uh[256];
1111 status = SILC_STATUS_OK;
1112 if (clients_count > 1)
1113 status = SILC_STATUS_LIST_START;
1115 for (i = 0; i < clients_count; i++) {
1118 /* We will take only clients that are not valid anymore. They are the
1119 ones that are not registered anymore but still have a ID. They
1120 have disconnected us, and thus valid for WHOWAS. */
1121 if (entry->data.status & SILC_IDLIST_STATUS_REGISTERED || !entry->id)
1124 if (count && i - 1 == count)
1129 if (clients_count > 2)
1130 status = SILC_STATUS_LIST_ITEM;
1131 if (clients_count > 1 && i == clients_count - 1)
1132 status = SILC_STATUS_LIST_END;
1134 /* Sanity check, however these should never fail. However, as
1135 this sanity check has been added here they have failed. */
1136 if (!entry->nickname || !entry->username || !entry->userinfo) {
1137 SILC_LOG_ERROR(("********* if (!entry->nickname || !entry->username "
1138 "|| !entry->userinfo) triggered: should have not!"));
1144 /* Sanity check, however these should never fail. However, as
1145 this sanity check has been added here they have failed. */
1146 if (!entry->nickname || !entry->username) {
1147 SILC_LOG_ERROR(("********* if (!entry->nickname || !entry->username) "
1148 "triggered: should have not!"));
1153 /* Send WHOWAS reply */
1154 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1155 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1156 memset(uh, 0, sizeof(uh));
1157 memset(nh, 0, sizeof(nh));
1159 strncat(nh, entry->nickname, strlen(entry->nickname));
1160 if (!strchr(entry->nickname, '@')) {
1161 strncat(nh, "@", 1);
1162 if (entry->servername) {
1163 strncat(nh, entry->servername, strlen(entry->servername));
1165 len = entry->router ? strlen(entry->router->server_name) :
1166 strlen(server->server_name);
1167 strncat(nh, entry->router ? entry->router->server_name :
1168 server->server_name, len);
1172 strncat(uh, entry->username, strlen(entry->username));
1173 if (!strchr(entry->username, '@')) {
1174 strncat(uh, "@", 1);
1175 strcat(uh, "*private*");
1179 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1181 2, idp->data, idp->len,
1186 strlen(entry->userinfo) : 0);
1187 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1188 0, packet->data, packet->len, FALSE);
1190 silc_buffer_free(packet);
1191 silc_buffer_free(idp);
1194 if (found == FALSE && entry)
1195 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1196 SILC_STATUS_ERR_NO_SUCH_NICK,
1198 strlen(entry->nickname));
1202 silc_server_command_whowas_process(SilcServerCommandContext cmd)
1204 SilcServer server = cmd->server;
1205 char *nick = NULL, *server_name = NULL;
1207 SilcClientEntry *clients = NULL;
1208 uint32 clients_count = 0;
1210 bool check_global = FALSE;
1212 /* Protocol dictates that we must always send the received WHOWAS request
1213 to our router if we are normal server, so let's do it now unless we
1214 are standalone. We will not send any replies to the client until we
1215 have received reply from the router. */
1216 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1217 server->server_type == SILC_SERVER && !cmd->pending &&
1218 !server->standalone) {
1222 old_ident = silc_command_get_ident(cmd->payload);
1223 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1224 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1226 /* Send WHOWAS command to our router */
1227 silc_server_packet_send(server, (SilcSocketConnection)
1228 server->router->connection,
1229 SILC_PACKET_COMMAND, cmd->packet->flags,
1230 tmpbuf->data, tmpbuf->len, TRUE);
1232 /* Reprocess this packet after received reply from router */
1233 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1234 silc_command_get_ident(cmd->payload),
1235 silc_server_command_destructor,
1236 silc_server_command_whowas,
1237 silc_server_command_dup(cmd));
1238 cmd->pending = TRUE;
1240 silc_command_set_ident(cmd->payload, old_ident);
1242 silc_buffer_free(tmpbuf);
1247 /* We are ready to process the command request. Let's search for the
1248 requested client and send reply to the requesting client. */
1250 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1251 check_global = TRUE;
1252 else if (server->server_type != SILC_SERVER)
1253 check_global = TRUE;
1255 /* Parse the whowas request */
1256 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1259 /* Get all clients matching that nickname from local list */
1260 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1262 &clients, &clients_count))
1263 silc_idlist_get_clients_by_hash(server->local_list,
1264 nick, server->md5hash,
1265 &clients, &clients_count);
1267 /* Check global list as well */
1269 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1271 &clients, &clients_count))
1272 silc_idlist_get_clients_by_hash(server->global_list,
1273 nick, server->md5hash,
1274 &clients, &clients_count);
1278 /* Such a client really does not exist in the SILC network. */
1279 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1280 SILC_STATUS_ERR_NO_SUCH_NICK,
1281 3, nick, strlen(nick));
1285 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1290 /* Send the command reply to the client */
1291 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1296 silc_free(server_name);
1301 /* Server side of command WHOWAS. */
1303 SILC_SERVER_CMD_FUNC(whowas)
1305 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1308 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1310 ret = silc_server_command_whowas_process(cmd);
1313 silc_server_command_free(cmd);
1316 /******************************************************************************
1320 ******************************************************************************/
1323 silc_server_command_identify_send_router(SilcServerCommandContext cmd)
1325 SilcServer server = cmd->server;
1329 old_ident = silc_command_get_ident(cmd->payload);
1330 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1331 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1333 /* Send IDENTIFY command to our router */
1334 silc_server_packet_send(server, (SilcSocketConnection)
1335 server->router->connection,
1336 SILC_PACKET_COMMAND, cmd->packet->flags,
1337 tmpbuf->data, tmpbuf->len, TRUE);
1339 /* Reprocess this packet after received reply from router */
1340 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1341 silc_command_get_ident(cmd->payload),
1342 silc_server_command_destructor,
1343 silc_server_command_identify,
1344 silc_server_command_dup(cmd));
1345 cmd->pending = TRUE;
1346 silc_command_set_ident(cmd->payload, old_ident);
1347 silc_buffer_free(tmpbuf);
1351 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1352 SilcClientEntry **clients,
1353 uint32 *clients_count,
1354 SilcServerEntry **servers,
1355 uint32 *servers_count,
1356 SilcChannelEntry **channels,
1357 uint32 *channels_count,
1360 SilcServer server = cmd->server;
1363 uint32 argc = silc_argument_get_arg_num(cmd->args);
1365 bool check_global = FALSE;
1370 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1371 check_global = TRUE;
1372 else if (server->server_type != SILC_SERVER)
1373 check_global = TRUE;
1375 /* If ID Payload is in the command it must be used instead of names */
1376 tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1378 /* No ID, get the names. */
1380 /* If we are normal server and have not resolved information from
1381 router yet, do so now. */
1382 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1383 server->server_type == SILC_SERVER && !cmd->pending &&
1384 !server->standalone) {
1385 silc_server_command_identify_send_router(cmd);
1389 /* Try to get nickname@server. */
1390 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1393 char *nick_server = NULL;
1395 silc_parse_userfqdn(tmp, &nick, &nick_server);
1397 if (!silc_idlist_get_clients_by_hash(server->local_list,
1398 nick, server->md5hash,
1399 clients, clients_count))
1400 silc_idlist_get_clients_by_nickname(server->local_list,
1402 clients, clients_count);
1404 if (!silc_idlist_get_clients_by_hash(server->global_list,
1405 nick, server->md5hash,
1406 clients, clients_count))
1407 silc_idlist_get_clients_by_nickname(server->global_list,
1409 clients, clients_count);
1413 silc_free(nick_server);
1416 /* the nickname does not exist, send error reply */
1417 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1418 SILC_STATUS_ERR_NO_SUCH_NICK,
1419 3, tmp, strlen(tmp));
1424 /* Try to get server name */
1425 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1427 entry = silc_idlist_find_server_by_name(server->local_list,
1429 if (!entry && check_global)
1430 entry = silc_idlist_find_server_by_name(server->global_list,
1433 *servers = silc_realloc(*servers, sizeof(**servers) *
1434 (*servers_count + 1));
1435 (*servers)[(*servers_count)++] = entry;
1439 /* the server does not exist, send error reply */
1440 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1441 SILC_STATUS_ERR_NO_SUCH_SERVER,
1442 3, tmp, strlen(tmp));
1447 /* Try to get channel name */
1448 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1450 entry = silc_idlist_find_channel_by_name(server->local_list,
1452 if (!entry && check_global)
1453 entry = silc_idlist_find_channel_by_name(server->global_list,
1456 *channels = silc_realloc(*channels, sizeof(**channels) *
1457 (*channels_count + 1));
1458 (*channels)[(*channels_count)++] = entry;
1462 /* The channel does not exist, send error reply */
1463 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1464 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1465 3, tmp, strlen(tmp));
1470 if (!(*clients) && !(*servers) && !(*channels)) {
1471 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1472 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1476 /* Command includes ID, we must use that. Also check whether the command
1477 has more than one ID set - take them all. */
1479 /* Take all ID's from the command packet */
1480 for (i = 0; i < argc; i++) {
1483 tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
1487 idp = silc_id_payload_parse(tmp, len);
1489 silc_free(*clients);
1490 silc_free(*servers);
1491 silc_free(*channels);
1492 silc_server_command_send_status_reply(
1493 cmd, SILC_COMMAND_IDENTIFY,
1494 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1498 id = silc_id_payload_get_id(idp);
1500 switch (silc_id_payload_get_type(idp)) {
1502 case SILC_ID_CLIENT:
1503 entry = (void *)silc_idlist_find_client_by_id(server->local_list,
1505 if (!entry && check_global)
1506 entry = (void *)silc_idlist_find_client_by_id(server->global_list,
1509 *clients = silc_realloc(*clients, sizeof(**clients) *
1510 (*clients_count + 1));
1511 (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
1513 /* If we are normal server and have not resolved information from
1514 router yet, do so now. */
1515 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1516 server->server_type == SILC_SERVER && !cmd->pending &&
1517 !server->standalone) {
1518 silc_server_command_identify_send_router(cmd);
1519 silc_free(*clients);
1520 silc_free(*servers);
1521 silc_free(*channels);
1524 silc_server_command_send_status_data(
1525 cmd, SILC_COMMAND_IDENTIFY,
1526 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1534 case SILC_ID_SERVER:
1535 entry = (void *)silc_idlist_find_server_by_id(server->local_list,
1537 if (!entry && check_global)
1538 entry = (void *)silc_idlist_find_server_by_id(server->global_list,
1541 *servers = silc_realloc(*servers, sizeof(**servers) *
1542 (*servers_count + 1));
1543 (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
1545 /* If we are normal server and have not resolved information from
1546 router yet, do so now. */
1547 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1548 server->server_type == SILC_SERVER && !cmd->pending &&
1549 !server->standalone) {
1550 silc_server_command_identify_send_router(cmd);
1551 silc_free(*clients);
1552 silc_free(*servers);
1553 silc_free(*channels);
1556 silc_server_command_send_status_data(
1557 cmd, SILC_COMMAND_IDENTIFY,
1558 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
1565 case SILC_ID_CHANNEL:
1566 entry = (void *)silc_idlist_find_channel_by_id(server->local_list,
1568 if (!entry && check_global)
1569 entry = (void *)silc_idlist_find_channel_by_id(server->global_list,
1572 *channels = silc_realloc(*channels, sizeof(**channels) *
1573 (*channels_count + 1));
1574 (*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
1576 /* If we are normal server and have not resolved information from
1577 router yet, do so now. */
1578 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1579 server->server_type == SILC_SERVER && !cmd->pending &&
1580 !server->standalone) {
1581 silc_server_command_identify_send_router(cmd);
1582 silc_free(*clients);
1583 silc_free(*servers);
1584 silc_free(*channels);
1587 silc_server_command_send_status_data(
1588 cmd, SILC_COMMAND_IDENTIFY,
1589 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
1602 silc_free(*clients);
1603 silc_free(*servers);
1604 silc_free(*channels);
1608 /* Get the max count of reply messages allowed */
1609 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1618 /* Checks that all mandatory fields in client entry are present. If not
1619 then send WHOIS request to the server who owns the client. We use
1620 WHOIS because we want to get as much information as possible at once. */
1623 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1624 SilcClientEntry *clients,
1625 uint32 clients_count)
1627 SilcServer server = cmd->server;
1628 SilcClientEntry entry;
1629 SilcServerResolveContext resolve = NULL, r = NULL;
1630 uint32 resolve_count = 0;
1634 for (i = 0; i < clients_count; i++) {
1639 if (entry->nickname ||
1640 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1644 /* If we are normal server, and we've not resolved this client from
1645 router and it is global client, we'll check whether it is on some
1646 channel. If not then we cannot be sure about its validity, and
1647 we'll resolve it from router. */
1648 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
1649 entry->connection || silc_hash_table_count(entry->channels))
1653 /* We need to resolve this entry since it is not complete */
1655 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1656 /* The entry is being resolved (and we are not the resolver) so attach
1657 to the command reply and we're done with this one. */
1658 silc_server_command_pending(server, SILC_COMMAND_NONE,
1659 entry->resolve_cmd_ident,
1660 silc_server_command_destructor,
1661 silc_server_command_identify,
1662 silc_server_command_dup(cmd));
1665 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1666 /* We've resolved this and it still is not ready. We'll return
1667 and are that this will be handled again after it is resolved. */
1668 for (i = 0; i < resolve_count; i++) {
1669 for (k = 0; k < r->res_argc; k++)
1670 silc_free(r->res_argv[k]);
1671 silc_free(r->res_argv);
1672 silc_free(r->res_argv_lens);
1673 silc_free(r->res_argv_types);
1678 /* We'll resolve this client */
1682 for (k = 0; k < resolve_count; k++) {
1683 if (resolve[k].router == entry->router) {
1690 resolve = silc_realloc(resolve, sizeof(*resolve) *
1691 (resolve_count + 1));
1692 r = &resolve[resolve_count];
1693 memset(r, 0, sizeof(*r));
1694 r->router = entry->router;
1695 r->ident = ++server->cmd_ident;
1699 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1701 r->res_argv_lens = silc_realloc(r->res_argv_lens,
1702 sizeof(*r->res_argv_lens) *
1704 r->res_argv_types = silc_realloc(r->res_argv_types,
1705 sizeof(*r->res_argv_types) *
1707 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1708 r->res_argv[r->res_argc] = silc_calloc(idp->len,
1709 sizeof(**r->res_argv));
1710 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1711 r->res_argv_lens[r->res_argc] = idp->len;
1712 r->res_argv_types[r->res_argc] = r->res_argc + 3;
1714 silc_buffer_free(idp);
1716 entry->resolve_cmd_ident = r->ident;
1717 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1718 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1723 /* Do the resolving */
1724 for (i = 0; i < resolve_count; i++) {
1729 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1730 now anyway so make it a good one. */
1731 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1732 r->res_argc, r->res_argv,
1736 silc_server_packet_send(server, r->router->connection,
1737 SILC_PACKET_COMMAND, cmd->packet->flags,
1738 res_cmd->data, res_cmd->len, FALSE);
1740 /* Reprocess this packet after received reply */
1741 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1743 silc_server_command_destructor,
1744 silc_server_command_identify,
1745 silc_server_command_dup(cmd));
1746 cmd->pending = TRUE;
1748 silc_buffer_free(res_cmd);
1749 for (k = 0; k < r->res_argc; k++)
1750 silc_free(r->res_argv[k]);
1751 silc_free(r->res_argv);
1752 silc_free(r->res_argv_lens);
1753 silc_free(r->res_argv_types);
1762 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1763 SilcClientEntry *clients,
1764 uint32 clients_count,
1765 SilcServerEntry *servers,
1766 uint32 servers_count,
1767 SilcChannelEntry *channels,
1768 uint32 channels_count,
1771 SilcServer server = cmd->server;
1772 int i, k, len, valid_count;
1773 SilcBuffer packet, idp;
1774 SilcCommandStatus status;
1775 uint16 ident = silc_command_get_ident(cmd->payload);
1776 char nh[256], uh[256];
1777 SilcSocketConnection hsock;
1779 status = SILC_STATUS_OK;
1782 SilcClientEntry entry;
1784 /* Process only valid entries. */
1786 for (i = 0; i < clients_count; i++) {
1787 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1794 /* No valid entries found at all, just send error */
1797 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1799 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1800 SILC_STATUS_ERR_NO_SUCH_NICK,
1801 3, tmp, strlen(tmp));
1803 tmp = silc_argument_get_arg_type(cmd->args, 5, (uint32 *)&len);
1804 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1805 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1811 /* Process all valid client entries and send command replies */
1813 if (valid_count > 1)
1814 status = SILC_STATUS_LIST_START;
1816 for (i = 0, k = 0; i < clients_count; i++) {
1822 status = SILC_STATUS_LIST_ITEM;
1823 if (valid_count > 1 && k == valid_count - 1
1824 && !servers_count && !channels_count)
1825 status = SILC_STATUS_LIST_END;
1826 if (count && k - 1 == count)
1827 status = SILC_STATUS_LIST_END;
1828 if (count && k - 1 > count)
1831 /* Send IDENTIFY reply */
1833 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1834 memset(uh, 0, sizeof(uh));
1835 memset(nh, 0, sizeof(nh));
1836 strncat(nh, entry->nickname, strlen(entry->nickname));
1837 if (!strchr(entry->nickname, '@')) {
1838 strncat(nh, "@", 1);
1839 if (entry->servername) {
1840 strncat(nh, entry->servername, strlen(entry->servername));
1842 len = entry->router ? strlen(entry->router->server_name) :
1843 strlen(server->server_name);
1844 strncat(nh, entry->router ? entry->router->server_name :
1845 server->server_name, len);
1849 if (!entry->username) {
1850 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1852 2, idp->data, idp->len,
1855 strncat(uh, entry->username, strlen(entry->username));
1856 if (!strchr(entry->username, '@')) {
1857 strncat(uh, "@", 1);
1858 hsock = (SilcSocketConnection)entry->connection;
1859 len = strlen(hsock->hostname);
1860 strncat(uh, hsock->hostname, len);
1863 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1865 2, idp->data, idp->len,
1870 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1871 0, packet->data, packet->len, FALSE);
1873 silc_buffer_free(packet);
1874 silc_buffer_free(idp);
1881 SilcServerEntry entry;
1883 if (status == SILC_STATUS_OK && servers_count > 1)
1884 status = SILC_STATUS_LIST_START;
1886 for (i = 0, k = 0; i < servers_count; i++) {
1890 status = SILC_STATUS_LIST_ITEM;
1891 if (servers_count > 1 && k == servers_count - 1 && !channels_count)
1892 status = SILC_STATUS_LIST_END;
1893 if (count && k - 1 == count)
1894 status = SILC_STATUS_LIST_END;
1895 if (count && k - 1 > count)
1898 /* Send IDENTIFY reply */
1899 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1901 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1903 2, idp->data, idp->len,
1904 3, entry->server_name,
1905 entry->server_name ?
1906 strlen(entry->server_name) : 0);
1907 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1908 0, packet->data, packet->len, FALSE);
1910 silc_buffer_free(packet);
1911 silc_buffer_free(idp);
1918 SilcChannelEntry entry;
1920 if (status == SILC_STATUS_OK && channels_count > 1)
1921 status = SILC_STATUS_LIST_START;
1923 for (i = 0, k = 0; i < channels_count; i++) {
1924 entry = channels[i];
1927 status = SILC_STATUS_LIST_ITEM;
1928 if (channels_count > 1 && k == channels_count - 1)
1929 status = SILC_STATUS_LIST_END;
1930 if (count && k - 1 == count)
1931 status = SILC_STATUS_LIST_END;
1932 if (count && k - 1 > count)
1935 /* Send IDENTIFY reply */
1936 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1938 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1940 2, idp->data, idp->len,
1941 3, entry->channel_name,
1942 entry->channel_name ?
1943 strlen(entry->channel_name): 0);
1944 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1945 0, packet->data, packet->len, FALSE);
1947 silc_buffer_free(packet);
1948 silc_buffer_free(idp);
1956 silc_server_command_identify_process(SilcServerCommandContext cmd)
1960 SilcClientEntry *clients = NULL;
1961 SilcServerEntry *servers = NULL;
1962 SilcChannelEntry *channels = NULL;
1963 uint32 clients_count = 0, servers_count = 0, channels_count = 0;
1965 /* Parse the IDENTIFY request */
1966 ret = silc_server_command_identify_parse(cmd,
1967 &clients, &clients_count,
1968 &servers, &servers_count,
1969 &channels, &channels_count,
1975 /* Check that all mandatory fields are present and request those data
1976 from the server who owns the client if necessary. */
1977 if (clients && !silc_server_command_identify_check_client(cmd, clients,
1983 /* Send the command reply to the client */
1984 silc_server_command_identify_send_reply(cmd,
1985 clients, clients_count,
1986 servers, servers_count,
1987 channels, channels_count,
1993 silc_free(channels);
1997 SILC_SERVER_CMD_FUNC(identify)
1999 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2002 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
2004 ret = silc_server_command_identify_process(cmd);
2007 silc_server_command_free(cmd);
2010 /* Checks string for bad characters and returns TRUE if they are found. */
2012 static int silc_server_command_bad_chars(char *nick)
2016 for (i = 0; i < strlen(nick); i++) {
2017 if (!isascii(nick[i]))
2019 if (nick[i] <= 32) return TRUE;
2020 if (nick[i] == ' ') return TRUE;
2021 if (nick[i] == '*') return TRUE;
2022 if (nick[i] == '?') return TRUE;
2023 if (nick[i] == ',') return TRUE;
2029 /* Server side of command NICK. Sets nickname for user. Setting
2030 nickname causes generation of a new client ID for the client. The
2031 new client ID is sent to the client after changing the nickname. */
2033 SILC_SERVER_CMD_FUNC(nick)
2035 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2036 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2037 SilcServer server = cmd->server;
2038 SilcBuffer packet, nidp, oidp = NULL;
2039 SilcClientID *new_id;
2041 uint16 ident = silc_command_get_ident(cmd->payload);
2044 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2047 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
2049 /* Check nickname */
2050 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
2051 if (silc_server_command_bad_chars(nick) == TRUE) {
2052 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2053 SILC_STATUS_ERR_BAD_NICKNAME);
2057 if (strlen(nick) > 128)
2060 /* Check for same nickname */
2061 if (!strcmp(client->nickname, nick)) {
2062 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2066 /* Create new Client ID */
2067 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
2069 cmd->server->md5hash, nick,
2072 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2075 /* Send notify about nickname change to our router. We send the new
2076 ID and ask to replace it with the old one. If we are router the
2077 packet is broadcasted. Send NICK_CHANGE notify. */
2078 if (!server->standalone)
2079 silc_server_send_notify_nick_change(server, server->router->connection,
2080 server->server_type == SILC_SERVER ?
2081 FALSE : TRUE, client->id,
2084 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2086 /* Remove old cache entry */
2087 silc_idcache_del_by_context(server->local_list->clients, client);
2090 silc_free(client->id);
2092 /* Save the nickname as this client is our local client */
2093 silc_free(client->nickname);
2095 client->nickname = strdup(nick);
2096 client->id = new_id;
2098 /* Update client cache */
2099 silc_idcache_add(server->local_list->clients, client->nickname,
2100 client->id, (void *)client, 0, NULL);
2102 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2104 /* Send NICK_CHANGE notify to the client's channels */
2105 silc_server_send_notify_on_channels(server, NULL, client,
2106 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
2107 oidp->data, oidp->len,
2108 nidp->data, nidp->len);
2111 /* Send the new Client ID as reply command back to client */
2112 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
2113 SILC_STATUS_OK, ident, 1,
2114 2, nidp->data, nidp->len);
2115 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2116 0, packet->data, packet->len, FALSE);
2118 silc_buffer_free(packet);
2119 silc_buffer_free(nidp);
2121 silc_buffer_free(oidp);
2124 silc_server_command_free(cmd);
2127 /* Sends the LIST command reply */
2130 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2131 SilcChannelEntry *lch,
2133 SilcChannelEntry *gch,
2137 SilcBuffer packet, idp;
2138 SilcChannelEntry entry;
2139 SilcCommandStatus status;
2140 uint16 ident = silc_command_get_ident(cmd->payload);
2142 unsigned char usercount[4];
2145 for (i = 0; i < lch_count; i++)
2146 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2148 for (i = 0; i < gch_count; i++)
2149 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2152 status = SILC_STATUS_OK;
2153 if ((lch_count + gch_count) > 1)
2154 status = SILC_STATUS_LIST_START;
2157 for (i = 0; i < lch_count; i++) {
2163 status = SILC_STATUS_LIST_ITEM;
2164 if (i >= 1 && i == lch_count - 1 && !gch_count)
2165 status = SILC_STATUS_LIST_END;
2167 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2169 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2170 topic = "*private*";
2171 memset(usercount, 0, sizeof(usercount));
2173 topic = entry->topic;
2174 users = silc_hash_table_count(entry->user_list);
2175 SILC_PUT32_MSB(users, usercount);
2178 /* Send the reply */
2180 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2182 2, idp->data, idp->len,
2183 3, entry->channel_name,
2184 strlen(entry->channel_name),
2185 4, topic, topic ? strlen(topic) : 0,
2187 silc_server_packet_send(cmd->server, cmd->sock,
2188 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2189 packet->len, FALSE);
2190 silc_buffer_free(packet);
2191 silc_buffer_free(idp);
2195 for (i = 0; i < gch_count; i++) {
2201 status = SILC_STATUS_LIST_ITEM;
2202 if (i >= 1 && i == gch_count - 1)
2203 status = SILC_STATUS_LIST_END;
2205 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2207 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2208 topic = "*private*";
2209 memset(usercount, 0, sizeof(usercount));
2211 topic = entry->topic;
2212 users = silc_hash_table_count(entry->user_list);
2213 SILC_PUT32_MSB(users, usercount);
2216 /* Send the reply */
2218 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2220 2, idp->data, idp->len,
2221 3, entry->channel_name,
2222 strlen(entry->channel_name),
2223 4, topic, topic ? strlen(topic) : 0,
2225 silc_server_packet_send(cmd->server, cmd->sock,
2226 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2227 packet->len, FALSE);
2228 silc_buffer_free(packet);
2229 silc_buffer_free(idp);
2233 /* Server side of LIST command. This lists the channel of the requested
2234 server. Secret channels are not listed. */
2236 SILC_SERVER_CMD_FUNC(list)
2238 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2239 SilcServer server = cmd->server;
2240 SilcChannelID *channel_id = NULL;
2243 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2244 uint32 lch_count = 0, gch_count = 0;
2246 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2248 /* If we are normal server, send the command to router, since we
2249 want to know all channels in the network. */
2250 if (!cmd->pending && server->server_type == SILC_SERVER &&
2251 !server->standalone) {
2255 old_ident = silc_command_get_ident(cmd->payload);
2256 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2257 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2258 silc_server_packet_send(server, server->router->connection,
2259 SILC_PACKET_COMMAND, cmd->packet->flags,
2260 tmpbuf->data, tmpbuf->len, TRUE);
2262 /* Reprocess this packet after received reply from router */
2263 silc_server_command_pending(server, SILC_COMMAND_LIST,
2264 silc_command_get_ident(cmd->payload),
2265 silc_server_command_destructor,
2266 silc_server_command_list,
2267 silc_server_command_dup(cmd));
2268 cmd->pending = TRUE;
2269 silc_command_set_ident(cmd->payload, old_ident);
2270 silc_buffer_free(tmpbuf);
2274 /* Get Channel ID */
2275 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2277 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2279 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2280 SILC_STATUS_ERR_NO_CHANNEL_ID);
2285 /* Get the channels from local list */
2286 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2289 /* Get the channels from global list */
2290 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2293 /* Send the reply */
2294 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2295 gchannels, gch_count);
2297 silc_free(lchannels);
2298 silc_free(gchannels);
2301 silc_server_command_free(cmd);
2304 /* Server side of TOPIC command. Sets topic for channel and/or returns
2305 current topic to client. */
2307 SILC_SERVER_CMD_FUNC(topic)
2309 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2310 SilcServer server = cmd->server;
2311 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2312 SilcChannelID *channel_id;
2313 SilcChannelEntry channel;
2314 SilcChannelClientEntry chl;
2315 SilcBuffer packet, idp;
2317 uint32 argc, tmp_len;
2318 uint16 ident = silc_command_get_ident(cmd->payload);
2320 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2322 argc = silc_argument_get_arg_num(cmd->args);
2324 /* Get Channel ID */
2325 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2327 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2328 SILC_STATUS_ERR_NO_CHANNEL_ID);
2331 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2333 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2334 SILC_STATUS_ERR_NO_CHANNEL_ID);
2338 /* Check whether the channel exists */
2339 channel = silc_idlist_find_channel_by_id(server->local_list,
2342 channel = silc_idlist_find_channel_by_id(server->global_list,
2345 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2346 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2353 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2355 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2356 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2360 if (strlen(tmp) > 256) {
2361 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2362 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2366 /* See whether the client is on channel and has rights to change topic */
2367 if (!silc_hash_table_find(channel->user_list, client, NULL,
2369 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2370 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2374 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2375 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2376 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2377 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2382 /* Set the topic for channel */
2383 silc_free(channel->topic);
2384 channel->topic = strdup(tmp);
2386 /* Send TOPIC_SET notify type to the network */
2387 if (!server->standalone)
2388 silc_server_send_notify_topic_set(server, server->router->connection,
2389 server->server_type == SILC_ROUTER ?
2390 TRUE : FALSE, channel,
2391 client->id, SILC_ID_CLIENT,
2394 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2396 /* Send notify about topic change to all clients on the channel */
2397 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2398 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2399 idp->data, idp->len,
2400 channel->topic, strlen(channel->topic));
2401 silc_buffer_free(idp);
2404 /* Send the topic to client as reply packet */
2405 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2406 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2407 SILC_STATUS_OK, ident, 2,
2408 2, idp->data, idp->len,
2411 strlen(channel->topic) : 0);
2412 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2413 0, packet->data, packet->len, FALSE);
2415 silc_buffer_free(packet);
2416 silc_buffer_free(idp);
2417 silc_free(channel_id);
2420 silc_server_command_free(cmd);
2423 /* Server side of INVITE command. Invites some client to join some channel.
2424 This command is also used to manage the invite list of the channel. */
2426 SILC_SERVER_CMD_FUNC(invite)
2428 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2429 SilcServer server = cmd->server;
2430 SilcSocketConnection sock = cmd->sock, dest_sock;
2431 SilcChannelClientEntry chl;
2432 SilcClientEntry sender, dest;
2433 SilcClientID *dest_id = NULL;
2434 SilcChannelEntry channel;
2435 SilcChannelID *channel_id = NULL;
2436 SilcIDListData idata;
2437 SilcBuffer idp, idp2, packet;
2438 unsigned char *tmp, *add, *del;
2440 uint16 ident = silc_command_get_ident(cmd->payload);
2442 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2444 /* Get Channel ID */
2445 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2447 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2448 SILC_STATUS_ERR_NO_CHANNEL_ID);
2451 channel_id = silc_id_payload_parse_id(tmp, len);
2453 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2454 SILC_STATUS_ERR_NO_CHANNEL_ID);
2458 /* Get the channel entry */
2459 channel = silc_idlist_find_channel_by_id(server->local_list,
2462 channel = silc_idlist_find_channel_by_id(server->global_list,
2465 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2466 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2471 /* Check whether the sender of this command is on the channel. */
2472 sender = (SilcClientEntry)sock->user_data;
2473 if (!silc_server_client_on_channel(sender, channel)) {
2474 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2475 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2479 /* Check whether the channel is invite-only channel. If yes then the
2480 sender of this command must be at least channel operator. */
2481 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2482 silc_hash_table_find(channel->user_list, sender, NULL, (void *)&chl);
2483 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2484 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2485 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2490 /* Get destination client ID */
2491 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2495 dest_id = silc_id_payload_parse_id(tmp, len);
2497 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2498 SILC_STATUS_ERR_NO_CLIENT_ID);
2502 /* Get the client entry */
2503 dest = silc_server_get_client_resolve(server, dest_id);
2505 if (server->server_type != SILC_SERVER) {
2506 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2507 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2511 /* The client info is being resolved. Reprocess this packet after
2512 receiving the reply to the query. */
2513 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2515 silc_server_command_destructor,
2516 silc_server_command_invite,
2517 silc_server_command_dup(cmd));
2518 cmd->pending = TRUE;
2519 silc_free(channel_id);
2524 /* Check whether the requested client is already on the channel. */
2525 if (silc_server_client_on_channel(dest, channel)) {
2526 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2527 SILC_STATUS_ERR_USER_ON_CHANNEL);
2531 /* Get route to the client */
2532 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2534 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2535 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2539 memset(invite, 0, sizeof(invite));
2540 strncat(invite, dest->nickname, strlen(dest->nickname));
2541 strncat(invite, "!", 1);
2542 strncat(invite, dest->username, strlen(dest->username));
2543 if (!strchr(dest->username, '@')) {
2544 strncat(invite, "@", 1);
2545 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2548 len = strlen(invite);
2549 if (!channel->invite_list)
2550 channel->invite_list = silc_calloc(len + 2,
2551 sizeof(*channel->invite_list));
2553 channel->invite_list = silc_realloc(channel->invite_list,
2554 sizeof(*channel->invite_list) *
2556 strlen(channel->invite_list) + 2));
2557 strncat(channel->invite_list, invite, len);
2558 strncat(channel->invite_list, ",", 1);
2560 /* Send notify to the client that is invited to the channel */
2561 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2562 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2563 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2565 SILC_NOTIFY_TYPE_INVITE, 3,
2566 idp->data, idp->len,
2567 channel->channel_name,
2568 strlen(channel->channel_name),
2569 idp2->data, idp2->len);
2570 silc_buffer_free(idp);
2571 silc_buffer_free(idp2);
2574 /* Add the client to the invite list of the channel */
2575 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2577 if (!channel->invite_list)
2578 channel->invite_list = silc_calloc(len + 2,
2579 sizeof(*channel->invite_list));
2581 channel->invite_list = silc_realloc(channel->invite_list,
2582 sizeof(*channel->invite_list) *
2584 strlen(channel->invite_list) + 2));
2585 if (add[len - 1] == ',')
2586 add[len - 1] = '\0';
2588 strncat(channel->invite_list, add, len);
2589 strncat(channel->invite_list, ",", 1);
2592 /* Get the invite to be removed and remove it from the list */
2593 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2594 if (del && channel->invite_list) {
2595 char *start, *end, *n;
2597 if (!strncmp(channel->invite_list, del,
2598 strlen(channel->invite_list) - 1)) {
2599 silc_free(channel->invite_list);
2600 channel->invite_list = NULL;
2602 start = strstr(channel->invite_list, del);
2603 if (start && strlen(start) >= len) {
2605 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2606 strncat(n, channel->invite_list, start - channel->invite_list);
2607 strncat(n, end + 1, ((channel->invite_list +
2608 strlen(channel->invite_list)) - end) - 1);
2609 silc_free(channel->invite_list);
2610 channel->invite_list = n;
2615 /* Send notify to the primary router */
2616 if (!server->standalone)
2617 silc_server_send_notify_invite(server, server->router->connection,
2618 server->server_type == SILC_ROUTER ?
2619 TRUE : FALSE, channel,
2620 sender->id, add, del);
2622 /* Send command reply */
2623 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2627 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2628 SILC_STATUS_OK, ident, 2,
2630 3, channel->invite_list,
2631 channel->invite_list ?
2632 strlen(channel->invite_list) : 0);
2635 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2636 SILC_STATUS_OK, ident, 1,
2638 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2639 packet->data, packet->len, FALSE);
2640 silc_buffer_free(packet);
2644 silc_free(channel_id);
2645 silc_server_command_free(cmd);
2650 SilcSocketConnection sock;
2654 /* Quits connection to client. This gets called if client won't
2655 close the connection even when it has issued QUIT command. */
2657 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2659 QuitInternal q = (QuitInternal)context;
2661 /* Free all client specific data, such as client entry and entires
2662 on channels this client may be on. */
2663 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2665 q->sock->user_data = NULL;
2667 /* Close the connection on our side */
2668 silc_server_close_connection(q->server, q->sock);
2670 silc_free(q->signoff);
2674 /* Quits SILC session. This is the normal way to disconnect client. */
2676 SILC_SERVER_CMD_FUNC(quit)
2678 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2679 SilcServer server = cmd->server;
2680 SilcSocketConnection sock = cmd->sock;
2682 unsigned char *tmp = NULL;
2685 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2687 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2690 /* Get destination ID */
2691 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2695 q = silc_calloc(1, sizeof(*q));
2698 q->signoff = tmp ? strdup(tmp) : NULL;
2700 /* We quit the connection with little timeout */
2701 silc_schedule_task_add(server->schedule, sock->sock,
2702 silc_server_command_quit_cb, (void *)q,
2703 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2706 silc_server_command_free(cmd);
2709 /* Server side of command KILL. This command is used by router operator
2710 to remove an client from the SILC Network temporarily. */
2712 SILC_SERVER_CMD_FUNC(kill)
2714 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2715 SilcServer server = cmd->server;
2716 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2717 SilcClientEntry remote_client;
2718 SilcClientID *client_id;
2719 unsigned char *tmp, *comment;
2720 uint32 tmp_len, tmp_len2;
2722 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2724 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2727 /* KILL command works only on router */
2728 if (server->server_type != SILC_ROUTER) {
2729 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2730 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2734 /* Check whether client has the permissions. */
2735 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2736 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2737 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2741 /* Get the client ID */
2742 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2744 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2745 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2748 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2750 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2751 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2755 /* Get the client entry */
2756 remote_client = silc_idlist_find_client_by_id(server->local_list,
2757 client_id, TRUE, NULL);
2758 if (!remote_client) {
2759 remote_client = silc_idlist_find_client_by_id(server->global_list,
2760 client_id, TRUE, NULL);
2761 if (!remote_client) {
2762 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2763 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2769 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2773 /* Send reply to the sender */
2774 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2777 /* Send the KILL notify packets. First send it to the channel, then
2778 to our primary router and then directly to the client who is being
2779 killed right now. */
2781 /* Send KILLED notify to the channels. It is not sent to the client
2782 as it will be sent differently destined directly to the client and not
2784 silc_server_send_notify_on_channels(server, remote_client,
2785 remote_client, SILC_NOTIFY_TYPE_KILLED,
2788 comment, comment ? tmp_len2 : 0);
2790 /* Send KILLED notify to primary route */
2791 if (!server->standalone)
2792 silc_server_send_notify_killed(server, server->router->connection, TRUE,
2793 remote_client->id, comment);
2795 /* Send KILLED notify to the client directly */
2796 silc_server_send_notify_killed(server, remote_client->connection ?
2797 remote_client->connection :
2798 remote_client->router->connection, FALSE,
2799 remote_client->id, comment);
2801 /* Remove the client from all channels. This generates new keys to the
2802 channels as well. */
2803 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2806 /* Remove the client entry, If it is locally connected then we will also
2807 disconnect the client here */
2808 if (remote_client->connection) {
2809 /* Remove locally conneted client */
2810 SilcSocketConnection sock = remote_client->connection;
2811 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2812 silc_server_close_connection(server, sock);
2814 /* Remove remote client */
2815 if (!silc_idlist_del_client(server->global_list, remote_client))
2816 silc_idlist_del_client(server->local_list, remote_client);
2820 silc_server_command_free(cmd);
2823 /* Server side of command INFO. This sends information about us to
2824 the client. If client requested specific server we will send the
2825 command to that server. */
2827 SILC_SERVER_CMD_FUNC(info)
2829 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2830 SilcServer server = cmd->server;
2831 SilcBuffer packet, idp;
2834 char *dest_server, *server_info = NULL, *server_name;
2835 uint16 ident = silc_command_get_ident(cmd->payload);
2836 SilcServerEntry entry = NULL;
2837 SilcServerID *server_id = NULL;
2839 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2841 /* Get server name */
2842 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2845 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2847 server_id = silc_id_payload_parse_id(tmp, tmp_len);
2849 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2850 SILC_STATUS_ERR_NO_SERVER_ID);
2856 /* Check whether we have this server cached */
2857 entry = silc_idlist_find_server_by_id(server->local_list,
2858 server_id, TRUE, NULL);
2860 entry = silc_idlist_find_server_by_id(server->global_list,
2861 server_id, TRUE, NULL);
2862 if (!entry && server->server_type != SILC_SERVER) {
2863 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2864 SILC_STATUS_ERR_NO_SUCH_SERVER);
2870 /* Some buggy servers has sent request to router about themselves. */
2871 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2874 if ((!dest_server && !server_id && !entry) || (entry &&
2875 entry == server->id_entry) ||
2876 (dest_server && !cmd->pending &&
2877 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2878 /* Send our reply */
2879 char info_string[256];
2881 memset(info_string, 0, sizeof(info_string));
2882 snprintf(info_string, sizeof(info_string),
2883 "location: %s server: %s admin: %s <%s>",
2884 server->config->admin_info->location,
2885 server->config->admin_info->server_type,
2886 server->config->admin_info->admin_name,
2887 server->config->admin_info->admin_email);
2889 server_info = info_string;
2890 entry = server->id_entry;
2892 /* Check whether we have this server cached */
2893 if (!entry && dest_server) {
2894 entry = silc_idlist_find_server_by_name(server->global_list,
2895 dest_server, TRUE, NULL);
2897 entry = silc_idlist_find_server_by_name(server->local_list,
2898 dest_server, TRUE, NULL);
2902 if (!cmd->pending &&
2903 server->server_type != SILC_SERVER && entry && !entry->server_info) {
2904 /* Send to the server */
2908 old_ident = silc_command_get_ident(cmd->payload);
2909 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2910 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2912 silc_server_packet_send(server, entry->connection,
2913 SILC_PACKET_COMMAND, cmd->packet->flags,
2914 tmpbuf->data, tmpbuf->len, TRUE);
2916 /* Reprocess this packet after received reply from router */
2917 silc_server_command_pending(server, SILC_COMMAND_INFO,
2918 silc_command_get_ident(cmd->payload),
2919 silc_server_command_destructor,
2920 silc_server_command_info,
2921 silc_server_command_dup(cmd));
2922 cmd->pending = TRUE;
2923 silc_command_set_ident(cmd->payload, old_ident);
2924 silc_buffer_free(tmpbuf);
2928 if (!entry && !cmd->pending && !server->standalone) {
2929 /* Send to the primary router */
2933 old_ident = silc_command_get_ident(cmd->payload);
2934 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2935 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2937 silc_server_packet_send(server, server->router->connection,
2938 SILC_PACKET_COMMAND, cmd->packet->flags,
2939 tmpbuf->data, tmpbuf->len, TRUE);
2941 /* Reprocess this packet after received reply from router */
2942 silc_server_command_pending(server, SILC_COMMAND_INFO,
2943 silc_command_get_ident(cmd->payload),
2944 silc_server_command_destructor,
2945 silc_server_command_info,
2946 silc_server_command_dup(cmd));
2947 cmd->pending = TRUE;
2948 silc_command_set_ident(cmd->payload, old_ident);
2949 silc_buffer_free(tmpbuf);
2954 silc_free(server_id);
2957 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2958 SILC_STATUS_ERR_NO_SUCH_SERVER);
2962 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2964 server_info = entry->server_info;
2965 server_name = entry->server_name;
2967 /* Send the reply */
2968 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2969 SILC_STATUS_OK, ident, 3,
2970 2, idp->data, idp->len,
2972 strlen(server_name),
2975 strlen(server_info) : 0);
2976 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2977 packet->data, packet->len, FALSE);
2979 silc_buffer_free(packet);
2980 silc_buffer_free(idp);
2983 silc_server_command_free(cmd);
2986 /* Server side of command PING. This just replies to the ping. */
2988 SILC_SERVER_CMD_FUNC(ping)
2990 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2991 SilcServer server = cmd->server;
2996 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
2999 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
3001 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3002 SILC_STATUS_ERR_NO_SERVER_ID);
3005 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
3009 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
3010 /* Send our reply */
3011 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3014 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3015 SILC_STATUS_ERR_NO_SUCH_SERVER);
3022 silc_server_command_free(cmd);
3025 /* Internal routine to join channel. The channel sent to this function
3026 has been either created or resolved from ID lists. This joins the sent
3027 client to the channel. */
3029 static void silc_server_command_join_channel(SilcServer server,
3030 SilcServerCommandContext cmd,
3031 SilcChannelEntry channel,
3032 SilcClientID *client_id,
3036 const unsigned char *auth,
3039 SilcSocketConnection sock = cmd->sock;
3041 uint32 tmp_len, user_count;
3042 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
3043 SilcClientEntry client;
3044 SilcChannelClientEntry chl;
3045 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
3046 uint16 ident = silc_command_get_ident(cmd->payload);
3047 char check[512], check2[512];
3048 bool founder = FALSE;
3050 SILC_LOG_DEBUG(("Start"));
3055 /* Get the client entry */
3056 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3057 client = (SilcClientEntry)sock->user_data;
3059 client = silc_server_get_client_resolve(server, client_id);
3064 /* The client info is being resolved. Reprocess this packet after
3065 receiving the reply to the query. */
3066 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
3067 server->cmd_ident, NULL,
3068 silc_server_command_join,
3069 silc_server_command_dup(cmd));
3070 cmd->pending = TRUE;
3074 cmd->pending = FALSE;
3078 * Check founder auth payload if provided. If client can gain founder
3079 * privileges it can override various conditions on joining the channel,
3080 * and can have directly the founder mode set on the channel.
3082 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3083 SilcIDListData idata = (SilcIDListData)client;
3085 if (channel->founder_key && idata->public_key &&
3086 silc_pkcs_public_key_compare(channel->founder_key,
3087 idata->public_key)) {
3088 void *auth_data = (channel->founder_method == SILC_AUTH_PASSWORD ?
3089 (void *)channel->founder_passwd :
3090 (void *)channel->founder_key);
3091 uint32 auth_data_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
3092 channel->founder_passwd_len : 0);
3094 /* Check whether the client is to become founder */
3095 if (silc_auth_verify_data(auth, auth_len, channel->founder_method,
3096 auth_data, auth_data_len,
3097 idata->hash, client->id, SILC_ID_CLIENT)) {
3098 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3105 * Check channel modes
3109 memset(check, 0, sizeof(check));
3110 memset(check2, 0, sizeof(check2));
3111 strncat(check, client->nickname, strlen(client->nickname));
3112 strncat(check, "!", 1);
3113 strncat(check, client->username, strlen(client->username));
3114 if (!strchr(client->username, '@')) {
3115 strncat(check, "@", 1);
3116 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3119 strncat(check2, client->nickname, strlen(client->nickname));
3120 if (!strchr(client->nickname, '@')) {
3121 strncat(check2, "@", 1);
3122 strncat(check2, server->server_name, strlen(server->server_name));
3124 strncat(check2, "!", 1);
3125 strncat(check2, client->username, strlen(client->username));
3126 if (!strchr(client->username, '@')) {
3127 strncat(check2, "@", 1);
3128 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3131 /* Check invite list if channel is invite-only channel */
3132 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3133 if (!channel->invite_list ||
3134 (!silc_string_match(channel->invite_list, check) &&
3135 !silc_string_match(channel->invite_list, check2))) {
3136 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3137 SILC_STATUS_ERR_NOT_INVITED);
3142 /* Check ban list if it exists. If the client's nickname, server,
3143 username and/or hostname is in the ban list the access to the
3144 channel is denied. */
3145 if (channel->ban_list) {
3146 if (!channel->ban_list ||
3147 silc_string_match(channel->ban_list, check) ||
3148 silc_string_match(channel->ban_list, check2)) {
3149 silc_server_command_send_status_reply(
3150 cmd, SILC_COMMAND_JOIN,
3151 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
3156 /* Check user count limit if set. */
3157 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3158 if (silc_hash_table_count(channel->user_list) + 1 >
3159 channel->user_limit) {
3160 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3161 SILC_STATUS_ERR_CHANNEL_IS_FULL);
3167 /* Check the channel passphrase if set. */
3168 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3169 /* Get passphrase */
3170 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3172 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
3173 memcpy(passphrase, tmp, tmp_len);
3176 if (!passphrase || !channel->passphrase ||
3177 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3178 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3179 SILC_STATUS_ERR_BAD_PASSWORD);
3185 * Client is allowed to join to the channel. Make it happen.
3188 /* Check whether the client already is on the channel */
3189 if (silc_server_client_on_channel(client, channel)) {
3190 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3191 SILC_STATUS_ERR_USER_ON_CHANNEL);
3195 /* Generate new channel key as protocol dictates */
3197 if (!silc_server_create_channel_key(server, channel, 0))
3200 /* Send the channel key. This is broadcasted to the channel but is not
3201 sent to the client who is joining to the channel. */
3202 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3203 silc_server_send_channel_key(server, NULL, channel,
3204 server->server_type == SILC_ROUTER ?
3205 FALSE : !server->standalone);
3208 /* Join the client to the channel by adding it to channel's user list.
3209 Add also the channel to client entry's channels list for fast cross-
3211 chl = silc_calloc(1, sizeof(*chl));
3213 chl->client = client;
3214 chl->channel = channel;
3215 silc_hash_table_add(channel->user_list, client, chl);
3216 silc_hash_table_add(client->channels, channel, chl);
3218 /* Get users on the channel */
3219 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3222 /* Encode Client ID Payload of the original client who wants to join */
3223 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3225 /* Encode command reply packet */
3226 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3227 SILC_PUT32_MSB(channel->mode, mode);
3228 SILC_PUT32_MSB(created, tmp2);
3229 SILC_PUT32_MSB(user_count, tmp3);
3231 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3232 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3233 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
3234 strlen(channel->channel_key->
3236 channel->channel_key->cipher->name,
3237 channel->key_len / 8, channel->key);
3242 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3243 SILC_STATUS_OK, ident, 13,
3244 2, channel->channel_name,
3245 strlen(channel->channel_name),
3246 3, chidp->data, chidp->len,
3247 4, clidp->data, clidp->len,
3250 7, keyp ? keyp->data : NULL,
3251 keyp ? keyp->len : 0,
3252 8, channel->ban_list,
3254 strlen(channel->ban_list) : 0,
3255 9, channel->invite_list,
3256 channel->invite_list ?
3257 strlen(channel->invite_list) : 0,
3260 strlen(channel->topic) : 0,
3261 11, silc_hmac_get_name(channel->hmac),
3262 strlen(silc_hmac_get_name(channel->
3265 13, user_list->data, user_list->len,
3266 14, mode_list->data,
3269 /* Send command reply */
3270 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3271 reply->data, reply->len, FALSE);
3273 /* Send JOIN notify to locally connected clients on the channel. If
3274 we are normal server then router will send or have sent JOIN notify
3275 already. However since we've added the client already to our channel
3276 we'll ignore it (in packet_receive.c) so we must send it here. If
3277 we are router then this will send it to local clients and local
3279 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3280 SILC_NOTIFY_TYPE_JOIN, 2,
3281 clidp->data, clidp->len,
3282 chidp->data, chidp->len);
3284 if (!cmd->pending) {
3285 /* Send JOIN notify packet to our primary router */
3286 if (!server->standalone)
3287 silc_server_send_notify_join(server, server->router->connection,
3288 server->server_type == SILC_ROUTER ?
3289 TRUE : FALSE, channel, client->id);
3292 /* Distribute the channel key to all backup routers. */
3293 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3294 keyp->data, keyp->len, FALSE, TRUE);
3296 /* If client became founder by providing correct founder auth data
3297 notify the mode change to the channel. */
3299 SILC_PUT32_MSB(chl->mode, mode);
3300 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3301 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3302 clidp->data, clidp->len,
3303 mode, 4, clidp->data, clidp->len);
3305 /* Set CUMODE notify type to network */
3306 if (!server->standalone)
3307 silc_server_send_notify_cumode(server, server->router->connection,
3308 server->server_type == SILC_ROUTER ?
3309 TRUE : FALSE, channel,
3310 chl->mode, client->id, SILC_ID_CLIENT,
3315 silc_buffer_free(reply);
3316 silc_buffer_free(clidp);
3317 silc_buffer_free(chidp);
3318 silc_buffer_free(keyp);
3319 silc_buffer_free(user_list);
3320 silc_buffer_free(mode_list);
3323 silc_free(passphrase);
3326 /* Server side of command JOIN. Joins client into requested channel. If
3327 the channel does not exist it will be created. */
3329 SILC_SERVER_CMD_FUNC(join)
3331 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3332 SilcServer server = cmd->server;
3333 unsigned char *auth;
3334 uint32 tmp_len, auth_len;
3335 char *tmp, *channel_name = NULL, *cipher, *hmac;
3336 SilcChannelEntry channel;
3338 bool created = FALSE, create_key = TRUE;
3339 SilcClientID *client_id;
3341 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3343 /* Get channel name */
3344 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3346 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3347 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3352 if (strlen(channel_name) > 256)
3353 channel_name[255] = '\0';
3355 if (silc_server_command_bad_chars(channel_name) == TRUE) {
3356 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3357 SILC_STATUS_ERR_BAD_CHANNEL);
3361 /* Get Client ID of the client who is joining to the channel */
3362 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3364 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3365 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3368 client_id = silc_id_payload_parse_id(tmp, tmp_len);
3370 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3371 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3375 /* Get cipher, hmac name and auth payload */
3376 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3377 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3378 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3380 /* See if the channel exists */
3381 channel = silc_idlist_find_channel_by_name(server->local_list,
3382 channel_name, NULL);
3384 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3385 /* If this is coming from client the Client ID in the command packet must
3386 be same as the client's ID. */
3387 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3388 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3389 if (!SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
3390 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3391 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3396 if (!channel || channel->disabled) {
3397 /* Channel not found */
3399 /* If we are standalone server we don't have a router, we just create
3400 the channel by ourselves. */
3401 if (server->standalone) {
3402 channel = silc_server_create_new_channel(server, server->id, cipher,
3403 hmac, channel_name, TRUE);
3405 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3406 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3410 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3416 /* The channel does not exist on our server. If we are normal server
3417 we will send JOIN command to our router which will handle the
3418 joining procedure (either creates the channel if it doesn't exist
3419 or joins the client to it). */
3420 if (server->server_type != SILC_ROUTER) {
3424 /* If this is pending command callback then we've resolved
3425 it and it didn't work, return since we've notified the
3426 client already in the command reply callback. */
3430 old_ident = silc_command_get_ident(cmd->payload);
3431 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3432 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3434 /* Send JOIN command to our router */
3435 silc_server_packet_send(server, (SilcSocketConnection)
3436 server->router->connection,
3437 SILC_PACKET_COMMAND, cmd->packet->flags,
3438 tmpbuf->data, tmpbuf->len, TRUE);
3440 /* Reprocess this packet after received reply from router */
3441 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3442 silc_command_get_ident(cmd->payload),
3443 silc_server_command_destructor,
3444 silc_server_command_join,
3445 silc_server_command_dup(cmd));
3446 cmd->pending = TRUE;
3450 /* We are router and the channel does not seem exist so we will check
3451 our global list as well for the channel. */
3452 channel = silc_idlist_find_channel_by_name(server->global_list,
3453 channel_name, NULL);
3455 /* Channel really does not exist, create it */
3456 channel = silc_server_create_new_channel(server, server->id, cipher,
3457 hmac, channel_name, TRUE);
3459 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3460 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3464 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3472 /* Channel not found */
3474 /* If the command came from router and we are normal server then
3475 something went wrong with the joining as the channel was not found.
3476 We can't do anything else but ignore this. */
3477 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3478 server->server_type != SILC_ROUTER)
3481 /* We are router and the channel does not seem exist so we will check
3482 our global list as well for the channel. */
3483 channel = silc_idlist_find_channel_by_name(server->global_list,
3484 channel_name, NULL);
3486 /* Channel really does not exist, create it */
3487 channel = silc_server_create_new_channel(server, server->id, cipher,
3488 hmac, channel_name, TRUE);
3490 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3491 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3495 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3502 /* Check whether the channel was created by our router */
3503 if (cmd->pending && context2) {
3504 SilcServerCommandReplyContext reply =
3505 (SilcServerCommandReplyContext)context2;
3506 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3507 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3508 SILC_GET32_MSB(created, tmp);
3509 create_key = FALSE; /* Router returned the key already */
3513 /* If the channel does not have global users and is also empty the client
3514 will be the channel founder and operator. */
3515 if (!channel->global_users && !silc_hash_table_count(channel->user_list))
3516 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3518 /* Join to the channel */
3519 silc_server_command_join_channel(server, cmd, channel, client_id,
3520 created, create_key, umode,
3523 silc_free(client_id);
3526 silc_server_command_free(cmd);
3529 /* Server side of command MOTD. Sends server's current "message of the
3530 day" to the client. */
3532 SILC_SERVER_CMD_FUNC(motd)
3534 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3535 SilcServer server = cmd->server;
3536 SilcBuffer packet, idp;
3537 char *motd, *dest_server;
3539 uint16 ident = silc_command_get_ident(cmd->payload);
3541 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3543 /* Get server name */
3544 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3546 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3547 SILC_STATUS_ERR_NO_SUCH_SERVER);
3551 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3554 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3556 if (server->config && server->config->motd &&
3557 server->config->motd->motd_file) {
3559 motd = silc_file_readfile(server->config->motd->motd_file, &motd_len);
3564 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3565 SILC_STATUS_OK, ident, 2,
3570 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3571 SILC_STATUS_OK, ident, 1,
3575 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3576 packet->data, packet->len, FALSE);
3577 silc_buffer_free(packet);
3578 silc_buffer_free(idp);
3580 SilcServerEntry entry;
3582 /* Check whether we have this server cached */
3583 entry = silc_idlist_find_server_by_name(server->global_list,
3584 dest_server, TRUE, NULL);
3586 entry = silc_idlist_find_server_by_name(server->local_list,
3587 dest_server, TRUE, NULL);
3590 if (server->server_type != SILC_SERVER && !cmd->pending &&
3591 entry && !entry->motd) {
3592 /* Send to the server */
3596 old_ident = silc_command_get_ident(cmd->payload);
3597 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3598 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3600 silc_server_packet_send(server, entry->connection,
3601 SILC_PACKET_COMMAND, cmd->packet->flags,
3602 tmpbuf->data, tmpbuf->len, TRUE);
3604 /* Reprocess this packet after received reply from router */
3605 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3606 silc_command_get_ident(cmd->payload),
3607 silc_server_command_destructor,
3608 silc_server_command_motd,
3609 silc_server_command_dup(cmd));
3610 cmd->pending = TRUE;
3611 silc_command_set_ident(cmd->payload, old_ident);
3612 silc_buffer_free(tmpbuf);
3616 if (!entry && !cmd->pending && !server->standalone) {
3617 /* Send to the primary router */
3621 old_ident = silc_command_get_ident(cmd->payload);
3622 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3623 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3625 silc_server_packet_send(server, server->router->connection,
3626 SILC_PACKET_COMMAND, cmd->packet->flags,
3627 tmpbuf->data, tmpbuf->len, TRUE);
3629 /* Reprocess this packet after received reply from router */
3630 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3631 silc_command_get_ident(cmd->payload),
3632 silc_server_command_destructor,
3633 silc_server_command_motd,
3634 silc_server_command_dup(cmd));
3635 cmd->pending = TRUE;
3636 silc_command_set_ident(cmd->payload, old_ident);
3637 silc_buffer_free(tmpbuf);
3642 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3643 SILC_STATUS_ERR_NO_SUCH_SERVER);
3647 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3648 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3649 SILC_STATUS_OK, ident, 2,
3653 strlen(entry->motd) : 0);
3654 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3655 packet->data, packet->len, FALSE);
3656 silc_buffer_free(packet);
3657 silc_buffer_free(idp);
3661 silc_server_command_free(cmd);
3664 /* Server side of command UMODE. Client can use this command to set/unset
3665 user mode. Client actually cannot set itself to be as server/router
3666 operator so this can be used only to unset the modes. */
3668 SILC_SERVER_CMD_FUNC(umode)
3670 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3671 SilcServer server = cmd->server;
3672 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3674 unsigned char *tmp_mask;
3676 uint16 ident = silc_command_get_ident(cmd->payload);
3678 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3681 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 2, 2);
3683 /* Get the client's mode mask */
3684 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3686 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3687 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3690 SILC_GET32_MSB(mask, tmp_mask);
3696 if (mask & SILC_UMODE_SERVER_OPERATOR) {
3697 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR)) {
3698 /* Cannot operator mode */
3699 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3700 SILC_STATUS_ERR_PERM_DENIED);
3704 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
3705 /* Remove the server operator rights */
3706 client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3709 if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3710 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
3711 /* Cannot operator mode */
3712 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3713 SILC_STATUS_ERR_PERM_DENIED);
3717 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
3718 /* Remove the router operator rights */
3719 client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3722 if (mask & SILC_UMODE_GONE) {
3723 client->mode |= SILC_UMODE_GONE;
3725 if (client->mode & SILC_UMODE_GONE)
3726 /* Remove the gone status */
3727 client->mode &= ~SILC_UMODE_GONE;
3730 /* Send UMODE change to primary router */
3731 if (!server->standalone)
3732 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3733 client->id, client->mode);
3735 /* Send command reply to sender */
3736 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3737 SILC_STATUS_OK, ident, 1,
3739 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3740 packet->data, packet->len, FALSE);
3741 silc_buffer_free(packet);
3744 silc_server_command_free(cmd);
3747 /* Checks that client has rights to add or remove channel modes. If any
3748 of the checks fails FALSE is returned. */
3750 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3751 SilcChannelClientEntry client,
3754 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3755 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3757 /* Check whether has rights to change anything */
3758 if (!is_op && !is_fo)
3761 /* Check whether has rights to change everything */
3765 /* We know that client is channel operator, check that they are not
3766 changing anything that requires channel founder rights. Rest of the
3767 modes are available automatically for channel operator. */
3769 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3770 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3771 if (is_op && !is_fo)
3774 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3775 if (is_op && !is_fo)
3780 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3781 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE))
3782 if (is_op && !is_fo)
3785 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3786 if (is_op && !is_fo)
3791 if (mode & SILC_CHANNEL_MODE_CIPHER) {
3792 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER))
3793 if (is_op && !is_fo)
3796 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3797 if (is_op && !is_fo)
3802 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3803 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH))
3804 if (is_op && !is_fo)
3807 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3808 if (is_op && !is_fo)
3816 /* Server side command of CMODE. Changes channel mode */
3818 SILC_SERVER_CMD_FUNC(cmode)
3820 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3821 SilcServer server = cmd->server;
3822 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3823 SilcIDListData idata = (SilcIDListData)client;
3824 SilcChannelID *channel_id;
3825 SilcChannelEntry channel;
3826 SilcChannelClientEntry chl;
3827 SilcBuffer packet, cidp;
3828 unsigned char *tmp, *tmp_id, *tmp_mask;
3829 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3830 uint32 mode_mask, tmp_len, tmp_len2;
3831 uint16 ident = silc_command_get_ident(cmd->payload);
3833 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 2, 7);
3835 /* Get Channel ID */
3836 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3838 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3839 SILC_STATUS_ERR_NO_CHANNEL_ID);
3842 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3844 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3845 SILC_STATUS_ERR_NO_CHANNEL_ID);
3849 /* Get the channel mode mask */
3850 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3852 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3853 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3856 SILC_GET32_MSB(mode_mask, tmp_mask);
3858 /* Get channel entry */
3859 channel = silc_idlist_find_channel_by_id(server->local_list,
3862 channel = silc_idlist_find_channel_by_id(server->global_list,
3865 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3866 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3871 /* Check whether this client is on the channel */
3872 if (!silc_server_client_on_channel(client, channel)) {
3873 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3874 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3878 /* Get entry to the channel user list */
3879 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
3881 /* Check that client has rights to change any requested channel modes */
3882 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3883 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3884 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3889 * Check the modes. Modes that requires nothing special operation are
3893 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3894 /* Channel uses private keys to protect traffic. Client(s) has set the
3895 key locally they want to use, server does not know that key. */
3896 /* Nothing interesting to do here */
3898 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3899 /* The mode is removed and we need to generate and distribute
3900 new channel key. Clients are not using private channel keys
3901 anymore after this. */
3903 /* Re-generate channel key */
3904 if (!silc_server_create_channel_key(server, channel, 0))
3907 /* Send the channel key. This sends it to our local clients and if
3908 we are normal server to our router as well. */
3909 silc_server_send_channel_key(server, NULL, channel,
3910 server->server_type == SILC_ROUTER ?
3911 FALSE : !server->standalone);
3913 cipher = channel->channel_key->cipher->name;
3914 hmac = (char *)silc_hmac_get_name(channel->hmac);
3918 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3919 /* User limit is set on channel */
3922 /* Get user limit */
3923 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3925 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3926 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3927 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3931 SILC_GET32_MSB(user_limit, tmp);
3932 channel->user_limit = user_limit;
3935 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3936 /* User limit mode is unset. Remove user limit */
3937 channel->user_limit = 0;
3940 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3941 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3942 /* Passphrase has been set to channel */
3944 /* Get the passphrase */
3945 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3947 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3948 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3952 /* Save the passphrase */
3953 passphrase = channel->passphrase = strdup(tmp);
3956 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3957 /* Passphrase mode is unset. remove the passphrase */
3958 if (channel->passphrase) {
3959 silc_free(channel->passphrase);
3960 channel->passphrase = NULL;
3965 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3966 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3967 /* Cipher to use protect the traffic */
3968 SilcCipher newkey, oldkey;
3971 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3973 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3974 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3978 /* Delete old cipher and allocate the new one */
3979 if (!silc_cipher_alloc(cipher, &newkey)) {
3980 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3981 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3985 oldkey = channel->channel_key;
3986 channel->channel_key = newkey;
3988 /* Re-generate channel key */
3989 if (!silc_server_create_channel_key(server, channel, 0)) {
3990 /* We don't have new key, revert to old one */
3991 channel->channel_key = oldkey;
3995 /* Remove old channel key for good */
3996 silc_cipher_free(oldkey);
3998 /* Send the channel key. This sends it to our local clients and if
3999 we are normal server to our router as well. */
4000 silc_server_send_channel_key(server, NULL, channel,
4001 server->server_type == SILC_ROUTER ?
4002 FALSE : !server->standalone);
4005 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
4006 /* Cipher mode is unset. Remove the cipher and revert back to
4008 SilcCipher newkey, oldkey;
4009 cipher = channel->cipher;
4011 /* Delete old cipher and allocate default one */
4012 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
4013 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4014 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4018 oldkey = channel->channel_key;
4019 channel->channel_key = newkey;
4021 /* Re-generate channel key */
4022 if (!silc_server_create_channel_key(server, channel, 0)) {
4023 /* We don't have new key, revert to old one */
4024 channel->channel_key = oldkey;
4028 /* Remove old channel key for good */
4029 silc_cipher_free(oldkey);
4031 /* Send the channel key. This sends it to our local clients and if
4032 we are normal server to our router as well. */
4033 silc_server_send_channel_key(server, NULL, channel,
4034 server->server_type == SILC_ROUTER ?
4035 FALSE : !server->standalone);
4039 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
4040 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
4041 /* HMAC to use protect the traffic */
4042 unsigned char hash[32];
4046 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4048 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4049 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4053 /* Delete old hmac and allocate the new one */
4054 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4055 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4056 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4060 silc_hmac_free(channel->hmac);
4061 channel->hmac = newhmac;
4063 /* Set the HMAC key out of current channel key. The client must do
4065 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4066 channel->key_len / 8, hash);
4067 silc_hmac_set_key(channel->hmac, hash,
4068 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4069 memset(hash, 0, sizeof(hash));
4072 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4073 /* Hmac mode is unset. Remove the hmac and revert back to
4076 unsigned char hash[32];
4077 hmac = channel->hmac_name;
4079 /* Delete old hmac and allocate default one */
4080 silc_hmac_free(channel->hmac);
4081 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4082 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4083 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4087 silc_hmac_free(channel->hmac);
4088 channel->hmac = newhmac;
4090 /* Set the HMAC key out of current channel key. The client must do
4092 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4093 channel->key_len / 8,
4095 silc_hmac_set_key(channel->hmac, hash,
4096 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4097 memset(hash, 0, sizeof(hash));
4101 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4102 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4103 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4104 /* Set the founder authentication */
4105 SilcAuthPayload auth;
4107 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4109 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4110 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4114 auth = silc_auth_payload_parse(tmp, tmp_len);
4116 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4117 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4121 /* Save the public key */
4122 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
4123 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
4126 channel->founder_method = silc_auth_get_method(auth);
4128 if (channel->founder_method == SILC_AUTH_PASSWORD) {
4129 tmp = silc_auth_get_data(auth, &tmp_len);
4130 channel->founder_passwd =
4131 silc_calloc(tmp_len + 1, sizeof(*channel->founder_passwd));
4132 memcpy(channel->founder_passwd, tmp, tmp_len);
4133 channel->founder_passwd_len = tmp_len;
4135 /* Verify the payload before setting the mode */
4136 if (!silc_auth_verify(auth, channel->founder_method,
4137 channel->founder_key, 0, idata->hash,
4138 client->id, SILC_ID_CLIENT)) {
4139 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4140 SILC_STATUS_ERR_AUTH_FAILED);
4145 silc_auth_payload_free(auth);
4149 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4150 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4151 if (channel->founder_key)
4152 silc_pkcs_public_key_free(channel->founder_key);
4153 if (channel->founder_passwd) {
4154 silc_free(channel->founder_passwd);
4155 channel->founder_passwd = NULL;
4161 /* Finally, set the mode */
4162 channel->mode = mode_mask;
4164 /* Send CMODE_CHANGE notify. */
4165 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4166 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4167 SILC_NOTIFY_TYPE_CMODE_CHANGE, 5,
4168 cidp->data, cidp->len,
4170 cipher, cipher ? strlen(cipher) : 0,
4171 hmac, hmac ? strlen(hmac) : 0,
4172 passphrase, passphrase ?
4173 strlen(passphrase) : 0);
4175 /* Set CMODE notify type to network */
4176 if (!server->standalone)
4177 silc_server_send_notify_cmode(server, server->router->connection,
4178 server->server_type == SILC_ROUTER ?
4179 TRUE : FALSE, channel,
4180 mode_mask, client->id, SILC_ID_CLIENT,
4181 cipher, hmac, passphrase);
4183 /* Send command reply to sender */
4184 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4185 SILC_STATUS_OK, ident, 2,
4186 2, tmp_id, tmp_len2,
4188 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4189 packet->data, packet->len, FALSE);
4191 silc_buffer_free(packet);
4192 silc_free(channel_id);
4193 silc_buffer_free(cidp);
4196 silc_server_command_free(cmd);
4199 /* Server side of CUMODE command. Changes client's mode on a channel. */
4201 SILC_SERVER_CMD_FUNC(cumode)
4203 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4204 SilcServer server = cmd->server;
4205 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4206 SilcIDListData idata = (SilcIDListData)client;
4207 SilcChannelID *channel_id;
4208 SilcClientID *client_id;
4209 SilcChannelEntry channel;
4210 SilcClientEntry target_client;
4211 SilcChannelClientEntry chl;
4212 SilcBuffer packet, idp;
4213 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4214 uint32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4216 uint16 ident = silc_command_get_ident(cmd->payload);
4218 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4220 /* Get Channel ID */
4221 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4223 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4224 SILC_STATUS_ERR_NO_CHANNEL_ID);
4227 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
4229 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4230 SILC_STATUS_ERR_NO_CHANNEL_ID);
4234 /* Get channel entry */
4235 channel = silc_idlist_find_channel_by_id(server->local_list,
4238 channel = silc_idlist_find_channel_by_id(server->global_list,
4241 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4242 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4247 /* Check whether sender is on the channel */
4248 if (!silc_server_client_on_channel(client, channel)) {
4249 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4250 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4254 /* Check that client has rights to change other's rights */
4255 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4256 sender_mask = chl->mode;
4258 /* Get the target client's channel mode mask */
4259 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4261 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4262 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4265 SILC_GET32_MSB(target_mask, tmp_mask);
4267 /* Get target Client ID */
4268 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4270 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4271 SILC_STATUS_ERR_NO_CLIENT_ID);
4274 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
4276 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4277 SILC_STATUS_ERR_NO_CLIENT_ID);
4281 /* Get target client's entry */
4282 target_client = silc_idlist_find_client_by_id(server->local_list,
4283 client_id, TRUE, NULL);
4284 if (!target_client) {
4285 target_client = silc_idlist_find_client_by_id(server->global_list,
4286 client_id, TRUE, NULL);
4289 if (target_client != client &&
4290 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4291 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4292 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4293 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4297 /* Check whether target client is on the channel */
4298 if (target_client != client) {
4299 if (!silc_server_client_on_channel(target_client, channel)) {
4300 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4301 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4305 /* Get entry to the channel user list */
4306 silc_hash_table_find(channel->user_list, target_client, NULL,
4314 /* If the target client is founder, no one else can change their mode
4316 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
4317 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4318 SILC_STATUS_ERR_NOT_YOU);
4322 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4323 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4324 /* The client tries to claim the founder rights. */
4325 unsigned char *tmp_auth;
4326 uint32 tmp_auth_len, auth_len;
4329 if (target_client != client) {
4330 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4331 SILC_STATUS_ERR_NOT_YOU);
4335 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4336 !channel->founder_key || !idata->public_key ||
4337 !silc_pkcs_public_key_compare(channel->founder_key,
4338 idata->public_key)) {
4339 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4340 SILC_STATUS_ERR_NOT_YOU);
4344 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4346 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4347 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4351 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4352 (void *)channel->founder_passwd : (void *)channel->founder_key);
4353 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4354 channel->founder_passwd_len : 0);
4356 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4357 channel->founder_method, auth, auth_len,
4358 idata->hash, client->id, SILC_ID_CLIENT)) {
4359 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4360 SILC_STATUS_ERR_AUTH_FAILED);
4364 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4368 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4369 if (target_client == client) {
4370 /* Remove channel founder rights from itself */
4371 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4374 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4375 SILC_STATUS_ERR_NOT_YOU);
4381 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4382 /* Promote to operator */
4383 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4384 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4385 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4386 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4387 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4391 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4395 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4396 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4397 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4398 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4399 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4403 /* Demote to normal user */
4404 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4409 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4410 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4412 /* Send notify to channel, notify only if mode was actually changed. */
4414 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4415 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4416 idp->data, idp->len,
4420 /* Set CUMODE notify type to network */
4421 if (!server->standalone)
4422 silc_server_send_notify_cumode(server, server->router->connection,
4423 server->server_type == SILC_ROUTER ?
4424 TRUE : FALSE, channel,
4425 target_mask, client->id,
4430 /* Send command reply to sender */
4431 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4432 SILC_STATUS_OK, ident, 3,
4434 3, tmp_ch_id, tmp_ch_len,
4435 4, tmp_id, tmp_len);
4436 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4437 packet->data, packet->len, FALSE);
4439 silc_buffer_free(packet);
4440 silc_free(channel_id);
4441 silc_free(client_id);
4442 silc_buffer_free(idp);
4445 silc_server_command_free(cmd);
4448 /* Server side of KICK command. Kicks client out of channel. */
4450 SILC_SERVER_CMD_FUNC(kick)
4452 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4453 SilcServer server = cmd->server;
4454 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4455 SilcClientEntry target_client;
4456 SilcChannelID *channel_id;
4457 SilcClientID *client_id;
4458 SilcChannelEntry channel;
4459 SilcChannelClientEntry chl;
4461 uint32 tmp_len, target_idp_len;
4462 unsigned char *tmp, *comment, *target_idp;
4464 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4466 /* Get Channel ID */
4467 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4469 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4470 SILC_STATUS_ERR_NO_CHANNEL_ID);
4473 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
4475 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4476 SILC_STATUS_ERR_NO_CHANNEL_ID);
4480 /* Get channel entry */
4481 channel = silc_idlist_find_channel_by_id(server->local_list,
4484 channel = silc_idlist_find_channel_by_id(server->local_list,
4487 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4488 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4493 /* Check whether sender is on the channel */
4494 if (!silc_server_client_on_channel(client, channel)) {
4495 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4496 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4500 /* Check that the kicker is channel operator or channel founder */
4501 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4502 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4503 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4504 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4508 /* Get target Client ID */
4509 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4511 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4512 SILC_STATUS_ERR_NO_CLIENT_ID);
4515 client_id = silc_id_payload_parse_id(target_idp, target_idp_len);
4517 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4518 SILC_STATUS_ERR_NO_CLIENT_ID);
4522 /* Get target client's entry */
4523 target_client = silc_idlist_find_client_by_id(server->local_list,
4524 client_id, TRUE, NULL);
4525 if (!target_client) {
4526 target_client = silc_idlist_find_client_by_id(server->global_list,
4527 client_id, TRUE, NULL);
4530 /* Check that the target client is not channel founder. Channel founder
4531 cannot be kicked from the channel. */
4532 silc_hash_table_find(channel->user_list, target_client, NULL, (void *)&chl);
4533 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4534 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4535 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4539 /* Check whether target client is on the channel */
4540 if (!silc_server_client_on_channel(target_client, channel)) {
4541 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4542 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4548 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4552 /* Send command reply to sender */
4553 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4556 /* Send KICKED notify to local clients on the channel */
4557 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4558 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4559 SILC_NOTIFY_TYPE_KICKED, 3,
4560 target_idp, target_idp_len,
4561 comment, comment ? strlen(comment) : 0,
4562 idp->data, idp->len);
4563 silc_buffer_free(idp);
4565 /* Remove the client from the channel. If the channel does not exist
4566 after removing the client then the client kicked itself off the channel
4567 and we don't have to send anything after that. */
4568 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4569 target_client, FALSE))
4572 /* Send KICKED notify to primary route */
4573 if (!server->standalone)
4574 silc_server_send_notify_kicked(server, server->router->connection,
4575 server->server_type == SILC_ROUTER ?
4576 TRUE : FALSE, channel,
4577 target_client->id, comment);
4579 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4580 /* Re-generate channel key */
4581 if (!silc_server_create_channel_key(server, channel, 0))
4584 /* Send the channel key to the channel. The key of course is not sent
4585 to the client who was kicked off the channel. */
4586 silc_server_send_channel_key(server, target_client->connection, channel,
4587 server->server_type == SILC_ROUTER ?
4588 FALSE : !server->standalone);
4592 silc_server_command_free(cmd);
4595 /* Server side of OPER command. Client uses this comand to obtain server
4596 operator privileges to this server/router. */
4598 SILC_SERVER_CMD_FUNC(oper)
4600 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4601 SilcServer server = cmd->server;
4602 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4603 unsigned char *username, *auth;
4605 SilcServerConfigSectionAdminConnection *admin;
4606 SilcIDListData idata = (SilcIDListData)client;
4608 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4610 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4613 /* Get the username */
4614 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4616 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4617 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4621 /* Get the admin configuration */
4622 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4623 username, client->nickname);
4625 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4626 username, client->nickname);
4628 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4629 SILC_STATUS_ERR_AUTH_FAILED);
4634 /* Get the authentication payload */
4635 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4637 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4638 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4642 /* Verify the authentication data */
4643 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4644 admin->auth_data, admin->auth_data_len,
4645 idata->hash, client->id, SILC_ID_CLIENT)) {
4646 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4647 SILC_STATUS_ERR_AUTH_FAILED);
4651 /* Client is now server operator */
4652 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4654 /* Send UMODE change to primary router */
4655 if (!server->standalone)
4656 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4657 client->id, client->mode);
4659 /* Send reply to the sender */
4660 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4664 silc_server_command_free(cmd);
4667 /* Server side of SILCOPER command. Client uses this comand to obtain router
4668 operator privileges to this router. */
4670 SILC_SERVER_CMD_FUNC(silcoper)
4672 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4673 SilcServer server = cmd->server;
4674 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4675 unsigned char *username, *auth;
4677 SilcServerConfigSectionAdminConnection *admin;
4678 SilcIDListData idata = (SilcIDListData)client;
4680 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4682 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4685 if (server->server_type != SILC_ROUTER) {
4686 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4687 SILC_STATUS_ERR_AUTH_FAILED);
4691 /* Get the username */
4692 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4694 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4695 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4699 /* Get the admin configuration */
4700 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4701 username, client->nickname);
4703 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4704 username, client->nickname);
4706 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4707 SILC_STATUS_ERR_AUTH_FAILED);
4712 /* Get the authentication payload */
4713 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4715 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4716 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4720 /* Verify the authentication data */
4721 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4722 admin->auth_data, admin->auth_data_len,
4723 idata->hash, client->id, SILC_ID_CLIENT)) {
4724 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4725 SILC_STATUS_ERR_AUTH_FAILED);
4729 /* Client is now router operator */
4730 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4732 /* Send UMODE change to primary router */
4733 if (!server->standalone)
4734 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4735 client->id, client->mode);
4737 /* Send reply to the sender */
4738 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4742 silc_server_command_free(cmd);
4745 /* Server side command of CONNECT. Connects us to the specified remote
4746 server or router. */
4748 SILC_SERVER_CMD_FUNC(connect)
4750 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4751 SilcServer server = cmd->server;
4752 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4753 unsigned char *tmp, *host;
4755 uint32 port = SILC_PORT;
4757 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CONNECT, cmd, 1, 2);
4759 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4762 /* Check whether client has the permissions. */
4763 if (client->mode == SILC_UMODE_NONE) {
4764 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4765 SILC_STATUS_ERR_NO_SERVER_PRIV);
4769 if (server->server_type == SILC_ROUTER &&
4770 client->mode & SILC_UMODE_SERVER_OPERATOR) {
4771 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4772 SILC_STATUS_ERR_NO_ROUTER_PRIV);
4776 /* Get the remote server */
4777 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4779 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4780 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4785 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4787 SILC_GET32_MSB(port, tmp);
4789 /* Create the connection. It is done with timeout and is async. */
4790 silc_server_create_connection(server, host, port);
4792 /* Send reply to the sender */
4793 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4797 silc_server_command_free(cmd);
4800 /* Server side of command BAN. This is used to manage the ban list of the
4801 channel. To add clients and remove clients from the ban list. */
4803 SILC_SERVER_CMD_FUNC(ban)
4805 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4806 SilcServer server = cmd->server;
4807 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4809 SilcChannelEntry channel;
4810 SilcChannelClientEntry chl;
4811 SilcChannelID *channel_id = NULL;
4812 unsigned char *id, *add, *del;
4813 uint32 id_len, tmp_len;
4814 uint16 ident = silc_command_get_ident(cmd->payload);
4816 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4819 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4821 /* Get Channel ID */
4822 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4824 channel_id = silc_id_payload_parse_id(id, id_len);
4826 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4827 SILC_STATUS_ERR_NO_CHANNEL_ID);
4832 /* Get channel entry. The server must know about the channel since the
4833 client is expected to be on the channel. */
4834 channel = silc_idlist_find_channel_by_id(server->local_list,
4837 channel = silc_idlist_find_channel_by_id(server->global_list,
4840 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4841 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4846 /* Check whether this client is on the channel */
4847 if (!silc_server_client_on_channel(client, channel)) {
4848 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4849 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4853 /* Get entry to the channel user list */
4854 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4856 /* The client must be at least channel operator. */
4857 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4858 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4859 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4863 /* Get the new ban and add it to the ban list */
4864 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4866 if (!channel->ban_list)
4867 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4869 channel->ban_list = silc_realloc(channel->ban_list,
4870 sizeof(*channel->ban_list) *
4872 strlen(channel->ban_list) + 2));
4873 if (add[tmp_len - 1] == ',')
4874 add[tmp_len - 1] = '\0';
4876 strncat(channel->ban_list, add, tmp_len);
4877 strncat(channel->ban_list, ",", 1);
4880 /* Get the ban to be removed and remove it from the list */
4881 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4882 if (del && channel->ban_list) {
4883 char *start, *end, *n;
4885 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4886 silc_free(channel->ban_list);
4887 channel->ban_list = NULL;
4889 start = strstr(channel->ban_list, del);
4890 if (start && strlen(start) >= tmp_len) {
4891 end = start + tmp_len;
4892 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4893 strncat(n, channel->ban_list, start - channel->ban_list);
4894 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4896 silc_free(channel->ban_list);
4897 channel->ban_list = n;
4902 /* Send the BAN notify type to our primary router. */
4903 if (!server->standalone && (add || del))
4904 silc_server_send_notify_ban(server, server->router->connection,
4905 server->server_type == SILC_ROUTER ?
4906 TRUE : FALSE, channel, add, del);
4908 /* Send the reply back to the client */
4910 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4911 SILC_STATUS_OK, ident, 2,
4913 3, channel->ban_list,
4915 strlen(channel->ban_list) - 1 : 0);
4916 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4917 packet->data, packet->len, FALSE);
4919 silc_buffer_free(packet);
4922 silc_free(channel_id);
4923 silc_server_command_free(cmd);
4926 /* Server side command of CLOSE. Closes connection to a specified server. */
4928 SILC_SERVER_CMD_FUNC(close)
4930 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4931 SilcServer server = cmd->server;
4932 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4933 SilcServerEntry server_entry;
4934 SilcSocketConnection sock;
4937 unsigned char *name;
4938 uint32 port = SILC_PORT;
4940 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CLOSE, cmd, 1, 2);
4942 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4945 /* Check whether client has the permissions. */
4946 if (client->mode == SILC_UMODE_NONE) {
4947 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4948 SILC_STATUS_ERR_NO_SERVER_PRIV);
4952 /* Get the remote server */
4953 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4955 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4956 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4961 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4963 SILC_GET32_MSB(port, tmp);
4965 server_entry = silc_idlist_find_server_by_conn(server->local_list,
4966 name, port, FALSE, NULL);
4968 server_entry = silc_idlist_find_server_by_conn(server->global_list,
4969 name, port, FALSE, NULL);
4970 if (!server_entry) {
4971 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4972 SILC_STATUS_ERR_NO_SERVER_ID);
4976 /* Send reply to the sender */
4977 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4980 /* Close the connection to the server */
4981 sock = (SilcSocketConnection)server_entry->connection;
4983 /* If we shutdown primary router connection manually then don't trigger
4984 any reconnect or backup router connections, by setting the router
4986 if (server->router == server_entry) {
4987 server->id_entry->router = NULL;
4988 server->router = NULL;
4989 server->standalone = TRUE;
4991 silc_server_free_sock_user_data(server, sock);
4992 silc_server_close_connection(server, sock);
4995 silc_server_command_free(cmd);
4998 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4999 active connections. */
5001 SILC_SERVER_CMD_FUNC(shutdown)
5003 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5004 SilcServer server = cmd->server;
5005 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5007 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
5009 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5012 /* Check whether client has the permission. */
5013 if (client->mode == SILC_UMODE_NONE) {
5014 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
5015 SILC_STATUS_ERR_NO_SERVER_PRIV);
5019 /* Send reply to the sender */
5020 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
5023 /* Then, gracefully, or not, bring the server down. */
5024 silc_server_stop(server);
5028 silc_server_command_free(cmd);
5031 /* Server side command of LEAVE. Removes client from a channel. */
5033 SILC_SERVER_CMD_FUNC(leave)
5035 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5036 SilcServer server = cmd->server;
5037 SilcSocketConnection sock = cmd->sock;
5038 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
5039 SilcChannelID *id = NULL;
5040 SilcChannelEntry channel;
5044 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
5046 /* Get Channel ID */
5047 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
5049 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5050 SILC_STATUS_ERR_NO_CHANNEL_ID);
5053 id = silc_id_payload_parse_id(tmp, len);
5055 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5056 SILC_STATUS_ERR_NO_CHANNEL_ID);
5060 /* Get channel entry */
5061 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5063 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5065 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5066 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5071 /* Check whether this client is on the channel */
5072 if (!silc_server_client_on_channel(id_entry, channel)) {
5073 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5074 SILC_STATUS_ERR_NOT_ON_CHANNEL);
5078 /* Notify routers that they should remove this client from their list
5079 of clients on the channel. Send LEAVE notify type. */
5080 if (!server->standalone)
5081 silc_server_send_notify_leave(server, server->router->connection,
5082 server->server_type == SILC_ROUTER ?
5083 TRUE : FALSE, channel, id_entry->id);
5085 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5088 /* Remove client from channel */
5089 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5091 /* If the channel does not exist anymore we won't send anything */
5094 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5095 /* Re-generate channel key */
5096 if (!silc_server_create_channel_key(server, channel, 0))
5099 /* Send the channel key */
5100 silc_server_send_channel_key(server, NULL, channel,
5101 server->server_type == SILC_ROUTER ?
5102 FALSE : !server->standalone);
5107 silc_server_command_free(cmd);
5110 /* Server side of command USERS. Resolves clients and their USERS currently
5111 joined on the requested channel. The list of Client ID's and their modes
5112 on the channel is sent back. */
5114 SILC_SERVER_CMD_FUNC(users)
5116 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5117 SilcServer server = cmd->server;
5118 SilcChannelEntry channel;
5119 SilcChannelID *id = NULL;
5120 SilcBuffer packet, idp;
5121 unsigned char *channel_id;
5122 uint32 channel_id_len;
5123 SilcBuffer client_id_list;
5124 SilcBuffer client_mode_list;
5125 unsigned char lc[4];
5126 uint32 list_count = 0;
5127 uint16 ident = silc_command_get_ident(cmd->payload);
5130 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5132 /* Get Channel ID */
5133 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5135 /* Get channel name */
5136 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5138 if (!channel_id && !channel_name) {
5139 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5140 SILC_STATUS_ERR_NO_CHANNEL_ID);
5145 id = silc_id_payload_parse_id(channel_id, channel_id_len);
5147 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5148 SILC_STATUS_ERR_NO_CHANNEL_ID);
5153 /* If we are server and we don't know about this channel we will send
5154 the command to our router. If we know about the channel then we also
5155 have the list of users already. */
5157 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5159 channel = silc_idlist_find_channel_by_name(server->local_list,
5160 channel_name, NULL);
5162 if (!channel || channel->disabled) {
5163 if (server->server_type != SILC_ROUTER && !server->standalone &&
5167 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5168 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5170 /* Send USERS command */
5171 silc_server_packet_send(server, server->router->connection,
5172 SILC_PACKET_COMMAND, cmd->packet->flags,
5173 tmpbuf->data, tmpbuf->len, TRUE);
5175 /* Reprocess this packet after received reply */
5176 silc_server_command_pending(server, SILC_COMMAND_USERS,
5177 silc_command_get_ident(cmd->payload),
5178 silc_server_command_destructor,
5179 silc_server_command_users,
5180 silc_server_command_dup(cmd));
5181 cmd->pending = TRUE;
5182 silc_command_set_ident(cmd->payload, ident);
5184 silc_buffer_free(tmpbuf);
5189 /* Check the global list as well. */
5191 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5193 channel = silc_idlist_find_channel_by_name(server->global_list,
5194 channel_name, NULL);
5196 /* Channel really does not exist */
5197 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5198 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5203 /* If the channel is private or secret do not send anything, unless the
5204 user requesting this command is on the channel. */
5205 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5206 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5207 && !silc_server_client_on_channel(cmd->sock->user_data, channel)) {
5208 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5209 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5214 (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
5215 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5216 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5221 /* Get the users list */
5222 silc_server_get_users_on_channel(server, channel, &client_id_list,
5223 &client_mode_list, &list_count);
5226 SILC_PUT32_MSB(list_count, lc);
5229 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5230 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5231 SILC_STATUS_OK, ident, 4,
5232 2, idp->data, idp->len,
5234 4, client_id_list->data,
5235 client_id_list->len,
5236 5, client_mode_list->data,
5237 client_mode_list->len);
5238 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5239 packet->data, packet->len, FALSE);
5241 silc_buffer_free(idp);
5242 silc_buffer_free(packet);
5243 silc_buffer_free(client_id_list);
5244 silc_buffer_free(client_mode_list);
5248 silc_server_command_free(cmd);
5251 /* Server side of command GETKEY. This fetches the client's public key
5252 from the server where to the client is connected. */
5254 SILC_SERVER_CMD_FUNC(getkey)
5256 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5257 SilcServer server = cmd->server;
5259 SilcClientEntry client;
5260 SilcServerEntry server_entry;
5261 SilcClientID *client_id = NULL;
5262 SilcServerID *server_id = NULL;
5263 SilcIDPayload idp = NULL;
5264 uint16 ident = silc_command_get_ident(cmd->payload);
5265 unsigned char *tmp, *pkdata;
5266 uint32 tmp_len, pklen;
5267 SilcBuffer pk = NULL;
5270 SILC_LOG_DEBUG(("Start"));
5272 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5274 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5275 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5278 idp = silc_id_payload_parse(tmp, tmp_len);
5280 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5281 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5285 id_type = silc_id_payload_get_type(idp);
5286 if (id_type == SILC_ID_CLIENT) {
5287 client_id = silc_id_payload_get_id(idp);
5289 /* If the client is not found from local list there is no chance it
5290 would be locally connected client so send the command further. */
5291 client = silc_idlist_find_client_by_id(server->local_list,
5292 client_id, TRUE, NULL);
5294 client = silc_idlist_find_client_by_id(server->global_list,
5295 client_id, TRUE, NULL);
5297 if ((!client && !cmd->pending && !server->standalone) ||
5298 (client && !client->connection && !cmd->pending) ||
5299 (client && !client->data.public_key && !cmd->pending)) {
5302 SilcSocketConnection dest_sock;
5304 dest_sock = silc_server_get_client_route(server, NULL, 0,
5309 old_ident = silc_command_get_ident(cmd->payload);
5310 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5311 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5313 silc_server_packet_send(server, dest_sock,
5314 SILC_PACKET_COMMAND, cmd->packet->flags,
5315 tmpbuf->data, tmpbuf->len, TRUE);
5317 /* Reprocess this packet after received reply from router */
5318 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5319 silc_command_get_ident(cmd->payload),
5320 silc_server_command_destructor,
5321 silc_server_command_getkey,
5322 silc_server_command_dup(cmd));
5323 cmd->pending = TRUE;
5325 silc_command_set_ident(cmd->payload, old_ident);
5326 silc_buffer_free(tmpbuf);
5331 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5332 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5336 /* The client is locally connected, just get the public key and
5337 send it back. If they key does not exist then do not send it,
5338 send just OK reply */
5339 if (!client->data.public_key) {
5343 tmp = silc_pkcs_public_key_encode(client->data.public_key, &tmp_len);
5344 pk = silc_buffer_alloc(4 + tmp_len);
5345 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5346 silc_buffer_format(pk,
5347 SILC_STR_UI_SHORT(tmp_len),
5348 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5349 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5355 } else if (id_type == SILC_ID_SERVER) {
5356 server_id = silc_id_payload_get_id(idp);
5358 /* If the server is not found from local list there is no chance it
5359 would be locally connected server so send the command further. */
5360 server_entry = silc_idlist_find_server_by_id(server->local_list,
5361 server_id, TRUE, NULL);
5363 server_entry = silc_idlist_find_server_by_id(server->global_list,
5364 server_id, TRUE, NULL);
5366 if (server_entry != server->id_entry &&
5367 ((!server_entry && !cmd->pending && !server->standalone) ||
5368 (server_entry && !server_entry->connection && !cmd->pending &&
5369 !server->standalone) ||
5370 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5371 !server->standalone))) {
5375 old_ident = silc_command_get_ident(cmd->payload);
5376 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5377 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5379 silc_server_packet_send(server, server->router->connection,
5380 SILC_PACKET_COMMAND, cmd->packet->flags,
5381 tmpbuf->data, tmpbuf->len, TRUE);
5383 /* Reprocess this packet after received reply from router */
5384 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5385 silc_command_get_ident(cmd->payload),
5386 silc_server_command_destructor,
5387 silc_server_command_getkey,
5388 silc_server_command_dup(cmd));
5389 cmd->pending = TRUE;
5391 silc_command_set_ident(cmd->payload, old_ident);
5392 silc_buffer_free(tmpbuf);
5396 if (!server_entry) {
5397 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5398 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5402 /* If they key does not exist then do not send it, send just OK reply */
5403 if (!server_entry->data.public_key) {
5407 tmp = silc_pkcs_public_key_encode(server_entry->data.public_key,
5409 pk = silc_buffer_alloc(4 + tmp_len);
5410 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5411 silc_buffer_format(pk,
5412 SILC_STR_UI_SHORT(tmp_len),
5413 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5414 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5424 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5425 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5426 SILC_STATUS_OK, ident,
5430 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5431 packet->data, packet->len, FALSE);
5432 silc_buffer_free(packet);
5435 silc_buffer_free(pk);
5439 silc_id_payload_free(idp);
5440 silc_free(client_id);
5441 silc_free(server_id);
5442 silc_server_command_free(cmd);