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);
137 /* Internal context to hold data when executed command with timeout. */
139 SilcServerCommandContext ctx;
140 SilcServerCommand *cmd;
141 } *SilcServerCommandTimeout;
143 /* Timeout callback to process commands with timeout for client. Client's
144 commands are always executed with timeout. */
146 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
148 SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
149 SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data;
152 silc_server_command_free(timeout->ctx);
156 /* Update access time */
157 client->last_command = time(NULL);
159 if (!(timeout->cmd->flags & SILC_CF_REG))
160 timeout->cmd->cb(timeout->ctx, NULL);
161 else if (silc_server_is_registered(timeout->ctx->server,
165 timeout->cmd->cb(timeout->ctx, NULL);
167 silc_server_command_free(timeout->ctx);
172 /* Processes received command packet. */
174 void silc_server_command_process(SilcServer server,
175 SilcSocketConnection sock,
176 SilcPacketContext *packet)
178 SilcServerCommandContext ctx;
179 SilcServerCommand *cmd;
182 /* Allocate command context. This must be free'd by the
183 command routine receiving it. */
184 ctx = silc_server_command_alloc();
185 ctx->server = server;
186 ctx->sock = silc_socket_dup(sock);
187 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
189 /* Parse the command payload in the packet */
190 ctx->payload = silc_command_payload_parse(packet->buffer->data,
191 packet->buffer->len);
193 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
194 silc_buffer_free(packet->buffer);
195 silc_packet_context_free(packet);
196 silc_socket_free(ctx->sock);
200 ctx->args = silc_command_get_args(ctx->payload);
202 /* Get the command */
203 command = silc_command_get(ctx->payload);
204 for (cmd = silc_command_list; cmd->cb; cmd++)
205 if (cmd->cmd == command)
209 silc_server_command_send_status_reply(ctx, command,
210 SILC_STATUS_ERR_UNKNOWN_COMMAND);
211 silc_server_command_free(ctx);
215 /* Execute client's commands always with timeout. Normally they are
216 executed with zero (0) timeout but if client is sending command more
217 frequently than once in 2 seconds, then the timeout may be 0 to 2
219 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
220 SilcClientEntry client = (SilcClientEntry)sock->user_data;
221 SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
227 if (client->last_command && (time(NULL) - client->last_command) < 2) {
228 client->fast_command++;
231 client->fast_command = ((client->fast_command - 1) <= 0 ? 0 :
232 client->fast_command--);
236 if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
237 (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
238 silc_schedule_task_add(server->schedule, sock->sock,
239 silc_server_command_process_timeout,
241 2 - (time(NULL) - client->last_command), 0,
242 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
244 silc_schedule_task_add(server->schedule, sock->sock,
245 silc_server_command_process_timeout,
246 (void *)timeout, 0, 1,
247 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
251 /* Execute for server */
253 if (!(cmd->flags & SILC_CF_REG))
255 else if (silc_server_is_registered(server, sock, ctx, cmd->cmd))
258 silc_server_command_free(ctx);
261 /* Allocate Command Context */
263 SilcServerCommandContext silc_server_command_alloc()
265 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
270 /* Free's the command context allocated before executing the command */
272 void silc_server_command_free(SilcServerCommandContext ctx)
275 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
277 if (ctx->users < 1) {
279 silc_command_payload_free(ctx->payload);
281 silc_packet_context_free(ctx->packet);
283 silc_socket_free(ctx->sock); /* Decrease reference counter */
288 /* Duplicate Command Context by adding reference counter. The context won't
289 be free'd untill it hits zero. */
291 SilcServerCommandContext
292 silc_server_command_dup(SilcServerCommandContext ctx)
295 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
300 /* Add new pending command to be executed when reply to a command has been
301 received. The `reply_cmd' is the command that will call the `callback'
302 with `context' when reply has been received. It can be SILC_COMMAND_NONE
303 to match any command with the `ident'. If `ident' is non-zero
304 the `callback' will be executed when received reply with command
305 identifier `ident'. If there already exists pending command for the
306 specified command, ident, callback and context this function has no
309 bool silc_server_command_pending(SilcServer server,
310 SilcCommand reply_cmd,
312 SilcCommandCb callback,
315 SilcServerCommandPending *reply;
317 /* Check whether identical pending already exists for same command,
318 ident, callback and callback context. If it does then it would be
319 error to register it again. */
320 silc_dlist_start(server->pending_commands);
321 while ((reply = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
322 if (reply->reply_cmd == reply_cmd && reply->ident == ident &&
323 reply->callback == callback && reply->context == context)
327 reply = silc_calloc(1, sizeof(*reply));
328 reply->reply_cmd = reply_cmd;
329 reply->ident = ident;
330 reply->context = context;
331 reply->callback = callback;
332 silc_dlist_add(server->pending_commands, reply);
337 /* Deletes pending command by reply command type. */
339 void silc_server_command_pending_del(SilcServer server,
340 SilcCommand reply_cmd,
343 SilcServerCommandPending *r;
345 silc_dlist_start(server->pending_commands);
346 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
347 if (r->reply_cmd == reply_cmd && r->ident == ident) {
348 silc_dlist_del(server->pending_commands, r);
354 /* Checks for pending commands and marks callbacks to be called from
355 the command reply function. Returns TRUE if there were pending command. */
357 SilcServerCommandPendingCallbacks
358 silc_server_command_pending_check(SilcServer server,
359 SilcServerCommandReplyContext ctx,
362 uint32 *callbacks_count)
364 SilcServerCommandPending *r;
365 SilcServerCommandPendingCallbacks callbacks = NULL;
368 silc_dlist_start(server->pending_commands);
369 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
370 if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE)
371 && r->ident == ident) {
372 callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
373 callbacks[i].context = r->context;
374 callbacks[i].callback = r->callback;
380 *callbacks_count = i;
384 /* Sends simple status message as command reply packet */
387 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
389 SilcCommandStatus status)
393 SILC_LOG_DEBUG(("Sending command status %d", status));
396 silc_command_reply_payload_encode_va(command, status,
397 silc_command_get_ident(cmd->payload),
399 silc_server_packet_send(cmd->server, cmd->sock,
400 SILC_PACKET_COMMAND_REPLY, 0,
401 buffer->data, buffer->len, FALSE);
402 silc_buffer_free(buffer);
405 /* Sends command status reply with one extra argument. The argument
406 type must be sent as argument. */
409 silc_server_command_send_status_data(SilcServerCommandContext cmd,
411 SilcCommandStatus status,
413 const unsigned char *arg,
418 SILC_LOG_DEBUG(("Sending command status %d", status));
421 silc_command_reply_payload_encode_va(command, status,
422 silc_command_get_ident(cmd->payload),
423 1, arg_type, arg, arg_len);
424 silc_server_packet_send(cmd->server, cmd->sock,
425 SILC_PACKET_COMMAND_REPLY, 0,
426 buffer->data, buffer->len, FALSE);
427 silc_buffer_free(buffer);
430 /* This function can be called to check whether in the command reply
431 an error occurred. This function has no effect if this is called
432 when the command function was not called as pending command callback.
433 This returns TRUE if error had occurred. */
436 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
437 SilcServerCommandReplyContext cmdr,
440 SilcCommandStatus status;
442 if (!cmd->pending || !cmdr)
445 SILC_GET16_MSB(status, silc_argument_get_arg_type(cmdr->args, 1, NULL));
446 if (status != SILC_STATUS_OK &&
447 status != SILC_STATUS_LIST_START &&
448 status != SILC_STATUS_LIST_ITEM &&
449 status != SILC_STATUS_LIST_END) {
452 /* Send the same command reply payload */
453 silc_command_set_ident(cmdr->payload,
454 silc_command_get_ident(cmd->payload));
455 buffer = silc_command_payload_encode_payload(cmdr->payload);
456 silc_server_packet_send(cmd->server, cmd->sock,
457 SILC_PACKET_COMMAND_REPLY, 0,
458 buffer->data, buffer->len, FALSE);
459 silc_buffer_free(buffer);
466 /******************************************************************************
470 ******************************************************************************/
473 silc_server_command_whois_parse(SilcServerCommandContext cmd,
474 SilcClientID ***client_id,
475 uint32 *client_id_count,
483 uint32 argc = silc_argument_get_arg_num(cmd->args);
486 /* If client ID is in the command it must be used instead of nickname */
487 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
489 /* No ID, get the nickname@server string and parse it. */
490 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
492 silc_parse_userfqdn(tmp, nickname, server_name);
494 silc_server_command_send_status_reply(cmd, command,
495 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
499 /* Command includes ID, we must use that. Also check whether the command
500 has more than one ID set - take them all. */
502 *client_id = silc_calloc(1, sizeof(**client_id));
503 (*client_id)[0] = silc_id_payload_parse_id(tmp, len);
504 if ((*client_id)[0] == NULL) {
505 silc_free(*client_id);
506 silc_server_command_send_status_reply(cmd, command,
507 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
510 *client_id_count = 1;
512 /* Take all ID's from the command packet */
514 for (k = 1, i = 1; i < argc; i++) {
515 tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
517 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
518 (*client_id_count + 1));
519 (*client_id)[k] = silc_id_payload_parse_id(tmp, len);
520 if ((*client_id)[k] == NULL) {
521 /* Cleanup all and fail */
522 for (i = 0; i < *client_id_count; i++)
523 silc_free((*client_id)[i]);
524 silc_free(*client_id);
525 silc_server_command_send_status_reply(
527 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
530 (*client_id_count)++;
537 /* Get the max count of reply messages allowed */
538 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
547 /* Resolve context used by both WHOIS and IDENTIFY commands */
549 SilcServerEntry router;
551 unsigned char **res_argv;
552 uint32 *res_argv_lens;
553 uint32 *res_argv_types;
555 } *SilcServerResolveContext;
558 silc_server_command_whois_check(SilcServerCommandContext cmd,
559 SilcClientEntry *clients,
560 uint32 clients_count)
562 SilcServer server = cmd->server;
563 SilcClientEntry entry;
564 SilcServerResolveContext resolve = NULL, r = NULL;
565 uint32 resolve_count = 0;
569 SILC_LOG_DEBUG(("Start"));
571 for (i = 0; i < clients_count; i++) {
576 if ((entry->nickname && entry->username && entry->userinfo) ||
577 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
581 /* If we are normal server, and we've not resolved this client from
582 router and it is global client, we'll check whether it is on some
583 channel. If not then we cannot be sure about its validity, and
584 we'll resolve it from router. */
585 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
586 entry->connection || silc_hash_table_count(entry->channels))
590 /* We need to resolve this entry since it is not complete */
592 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
593 /* The entry is being resolved (and we are not the resolver) so attach
594 to the command reply and we're done with this one. */
595 silc_server_command_pending(server, SILC_COMMAND_NONE,
596 entry->resolve_cmd_ident,
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_whois,
680 silc_server_command_dup(cmd));
683 silc_buffer_free(res_cmd);
684 for (k = 0; k < r->res_argc; k++)
685 silc_free(r->res_argv[k]);
686 silc_free(r->res_argv);
687 silc_free(r->res_argv_lens);
688 silc_free(r->res_argv_types);
697 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
698 SilcClientEntry *clients,
699 uint32 clients_count,
701 const char *nickname,
702 SilcClientID **client_ids)
704 SilcServer server = cmd->server;
706 int i, k, len, valid_count;
707 SilcBuffer packet, idp, channels;
708 SilcClientEntry entry;
709 SilcCommandStatus status;
710 uint16 ident = silc_command_get_ident(cmd->payload);
711 char nh[256], uh[256];
712 unsigned char idle[4], mode[4];
713 unsigned char *fingerprint;
714 SilcSocketConnection hsock;
716 /* Process only valid clients and ignore those that are not registered. */
718 for (i = 0; i < clients_count; i++) {
719 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
726 /* No valid clients found, send error reply */
728 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
729 SILC_STATUS_ERR_NO_SUCH_NICK,
730 3, nickname, strlen(nickname));
731 } else if (client_ids && client_ids[0]) {
732 SilcBuffer idp = silc_id_payload_encode(client_ids[0], SILC_ID_CLIENT);
733 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
734 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
735 2, idp->data, idp->len);
736 silc_buffer_free(idp);
741 /* Start processing found clients. */
743 status = SILC_STATUS_LIST_START;
745 status = SILC_STATUS_OK;
747 for (i = 0, k = 0; i < clients_count; i++) {
753 status = SILC_STATUS_LIST_ITEM;
754 if (valid_count > 1 && k == valid_count - 1)
755 status = SILC_STATUS_LIST_END;
756 if (count && k - 1 == count)
757 status = SILC_STATUS_LIST_END;
759 /* Send WHOIS reply */
760 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
761 tmp = silc_argument_get_first_arg(cmd->args, NULL);
763 memset(uh, 0, sizeof(uh));
764 memset(nh, 0, sizeof(nh));
765 memset(idle, 0, sizeof(idle));
767 strncat(nh, entry->nickname, strlen(entry->nickname));
768 if (!strchr(entry->nickname, '@')) {
770 if (entry->servername) {
771 strncat(nh, entry->servername, strlen(entry->servername));
773 len = entry->router ? strlen(entry->router->server_name) :
774 strlen(server->server_name);
775 strncat(nh, entry->router ? entry->router->server_name :
776 server->server_name, len);
780 strncat(uh, entry->username, strlen(entry->username));
781 if (!strchr(entry->username, '@')) {
783 hsock = (SilcSocketConnection)entry->connection;
784 len = strlen(hsock->hostname);
785 strncat(uh, hsock->hostname, len);
788 channels = silc_server_get_client_channel_list(server, entry);
790 if (entry->data.fingerprint[0] != 0 && entry->data.fingerprint[1] != 0)
791 fingerprint = entry->data.fingerprint;
795 SILC_PUT32_MSB(entry->mode, mode);
797 if (entry->connection) {
798 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
802 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
804 2, idp->data, idp->len,
808 strlen(entry->userinfo),
809 6, channels ? channels->data : NULL,
810 channels ? channels->len : 0,
814 fingerprint ? 20 : 0);
816 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
817 0, packet->data, packet->len, FALSE);
819 silc_buffer_free(packet);
820 silc_buffer_free(idp);
822 silc_buffer_free(channels);
829 silc_server_command_whois_send_router(SilcServerCommandContext cmd)
831 SilcServer server = cmd->server;
835 old_ident = silc_command_get_ident(cmd->payload);
836 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
837 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
839 /* Send WHOIS command to our router */
840 silc_server_packet_send(server, (SilcSocketConnection)
841 server->router->connection,
842 SILC_PACKET_COMMAND, cmd->packet->flags,
843 tmpbuf->data, tmpbuf->len, TRUE);
845 /* Reprocess this packet after received reply from router */
846 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
847 silc_command_get_ident(cmd->payload),
848 silc_server_command_whois,
849 silc_server_command_dup(cmd));
851 silc_command_set_ident(cmd->payload, old_ident);
852 silc_buffer_free(tmpbuf);
856 silc_server_command_whois_process(SilcServerCommandContext cmd)
858 SilcServer server = cmd->server;
859 char *nick = NULL, *server_name = NULL;
861 SilcClientEntry *clients = NULL, entry;
862 SilcClientID **client_id = NULL;
863 uint32 client_id_count = 0, clients_count = 0;
865 bool check_global = FALSE;
867 /* Parse the whois request */
868 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
869 &nick, &server_name, &count,
873 /* Send the WHOIS request to the router only if it included nickname.
874 Since nicknames can be expanded into many clients we need to send it
875 to router. If the WHOIS included only client ID's we will check them
876 first locally since we just might have them. */
877 if (nick && !client_id_count && cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
878 server->server_type == SILC_SERVER && !cmd->pending &&
879 !server->standalone) {
880 silc_server_command_whois_send_router(cmd);
885 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
887 else if (server->server_type != SILC_SERVER)
890 /* Get all clients matching that ID or nickname from local list */
891 if (client_id_count) {
892 /* Check all Client ID's received in the command packet */
893 for (i = 0; i < client_id_count; i++) {
894 entry = silc_idlist_find_client_by_id(server->local_list,
895 client_id[i], TRUE, NULL);
896 if (!entry && check_global)
897 entry = silc_idlist_find_client_by_id(server->global_list,
898 client_id[i], TRUE, NULL);
900 clients = silc_realloc(clients, sizeof(*clients) *
901 (clients_count + 1));
902 clients[clients_count++] = entry;
904 /* If we are normal server and did not send the request first to router
905 do it now, since we do not have the Client ID information. */
906 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
907 server->server_type == SILC_SERVER && !cmd->pending &&
908 !server->standalone) {
909 silc_server_command_whois_send_router(cmd);
916 /* Find by nickname */
917 if (!silc_idlist_get_clients_by_hash(server->local_list,
918 nick, server->md5hash,
919 &clients, &clients_count))
920 silc_idlist_get_clients_by_nickname(server->local_list,
922 &clients, &clients_count);
924 if (!silc_idlist_get_clients_by_hash(server->global_list,
925 nick, server->md5hash,
926 &clients, &clients_count))
927 silc_idlist_get_clients_by_nickname(server->global_list,
929 &clients, &clients_count);
934 /* If we are normal server and did not send the request first to router
935 do it now, since we do not have the information. */
936 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
937 server->server_type == SILC_SERVER && !cmd->pending &&
938 !server->standalone) {
939 silc_server_command_whois_send_router(cmd);
944 /* Such client(s) really does not exist in the SILC network. */
945 if (!client_id_count) {
946 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
947 SILC_STATUS_ERR_NO_SUCH_NICK,
948 3, nick, strlen(nick));
950 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
951 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
952 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
953 2, idp->data, idp->len);
954 silc_buffer_free(idp);
959 /* Router always finds the client entry if it exists in the SILC network.
960 However, it might be incomplete entry and does not include all the
961 mandatory fields that WHOIS command reply requires. Check for these and
962 make query from the server who owns the client if some fields are
964 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
969 /* Send the command reply */
970 silc_server_command_whois_send_reply(cmd, clients, clients_count,
971 count, nick, client_id);
974 if (client_id_count) {
975 for (i = 0; i < client_id_count; i++)
976 silc_free(client_id[i]);
977 silc_free(client_id);
981 silc_free(server_name);
986 /* Server side of command WHOIS. Processes user's query and sends found
987 results as command replies back to the client. */
989 SILC_SERVER_CMD_FUNC(whois)
991 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
994 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 3328);
996 ret = silc_server_command_whois_process(cmd);
997 silc_server_command_free(cmd);
1000 /******************************************************************************
1004 ******************************************************************************/
1007 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
1015 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1017 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
1018 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1022 /* Get the nickname@server string and parse it. */
1023 silc_parse_userfqdn(tmp, nickname, server_name);
1025 /* Get the max count of reply messages allowed */
1026 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1036 silc_server_command_whowas_check(SilcServerCommandContext cmd,
1037 SilcClientEntry *clients,
1038 uint32 clients_count)
1040 SilcServer server = cmd->server;
1042 SilcClientEntry entry;
1044 for (i = 0; i < clients_count; i++) {
1047 if (!entry->nickname || !entry->username) {
1054 old_ident = silc_command_get_ident(cmd->payload);
1055 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1056 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1058 /* Send WHOWAS command */
1059 silc_server_packet_send(server, entry->router->connection,
1060 SILC_PACKET_COMMAND, cmd->packet->flags,
1061 tmpbuf->data, tmpbuf->len, TRUE);
1063 /* Reprocess this packet after received reply */
1064 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1065 silc_command_get_ident(cmd->payload),
1066 silc_server_command_whowas,
1067 silc_server_command_dup(cmd));
1068 cmd->pending = TRUE;
1069 silc_command_set_ident(cmd->payload, old_ident);
1071 silc_buffer_free(tmpbuf);
1080 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1081 SilcClientEntry *clients,
1082 uint32 clients_count)
1084 SilcServer server = cmd->server;
1086 int i, count = 0, len;
1087 SilcBuffer packet, idp;
1088 SilcClientEntry entry = NULL;
1089 SilcCommandStatus status;
1090 uint16 ident = silc_command_get_ident(cmd->payload);
1092 char nh[256], uh[256];
1094 status = SILC_STATUS_OK;
1095 if (clients_count > 1)
1096 status = SILC_STATUS_LIST_START;
1098 for (i = 0; i < clients_count; i++) {
1101 /* We will take only clients that are not valid anymore. They are the
1102 ones that are not registered anymore but still have a ID. They
1103 have disconnected us, and thus valid for WHOWAS. */
1104 if (entry->data.status & SILC_IDLIST_STATUS_REGISTERED || !entry->id)
1107 if (count && i - 1 == count)
1112 if (clients_count > 2)
1113 status = SILC_STATUS_LIST_ITEM;
1114 if (clients_count > 1 && i == clients_count - 1)
1115 status = SILC_STATUS_LIST_END;
1117 /* Send WHOWAS reply */
1118 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1119 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1120 memset(uh, 0, sizeof(uh));
1121 memset(nh, 0, sizeof(nh));
1123 strncat(nh, entry->nickname, strlen(entry->nickname));
1124 if (!strchr(entry->nickname, '@')) {
1125 strncat(nh, "@", 1);
1126 if (entry->servername) {
1127 strncat(nh, entry->servername, strlen(entry->servername));
1129 len = entry->router ? strlen(entry->router->server_name) :
1130 strlen(server->server_name);
1131 strncat(nh, entry->router ? entry->router->server_name :
1132 server->server_name, len);
1136 strncat(uh, entry->username, strlen(entry->username));
1137 if (!strchr(entry->username, '@')) {
1138 strncat(uh, "@", 1);
1139 strcat(uh, "*private*");
1143 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1145 2, idp->data, idp->len,
1150 strlen(entry->userinfo) : 0);
1151 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1152 0, packet->data, packet->len, FALSE);
1154 silc_buffer_free(packet);
1155 silc_buffer_free(idp);
1158 if (found == FALSE && entry)
1159 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1160 SILC_STATUS_ERR_NO_SUCH_NICK,
1162 strlen(entry->nickname));
1166 silc_server_command_whowas_process(SilcServerCommandContext cmd)
1168 SilcServer server = cmd->server;
1169 char *nick = NULL, *server_name = NULL;
1171 SilcClientEntry *clients = NULL;
1172 uint32 clients_count = 0;
1174 bool check_global = FALSE;
1176 /* Protocol dictates that we must always send the received WHOWAS request
1177 to our router if we are normal server, so let's do it now unless we
1178 are standalone. We will not send any replies to the client until we
1179 have received reply from the router. */
1180 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1181 server->server_type == SILC_SERVER && !cmd->pending &&
1182 !server->standalone) {
1186 old_ident = silc_command_get_ident(cmd->payload);
1187 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1188 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1190 /* Send WHOWAS command to our router */
1191 silc_server_packet_send(server, (SilcSocketConnection)
1192 server->router->connection,
1193 SILC_PACKET_COMMAND, cmd->packet->flags,
1194 tmpbuf->data, tmpbuf->len, TRUE);
1196 /* Reprocess this packet after received reply from router */
1197 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1198 silc_command_get_ident(cmd->payload),
1199 silc_server_command_whowas,
1200 silc_server_command_dup(cmd));
1201 cmd->pending = TRUE;
1202 silc_command_set_ident(cmd->payload, old_ident);
1204 silc_buffer_free(tmpbuf);
1209 /* We are ready to process the command request. Let's search for the
1210 requested client and send reply to the requesting client. */
1212 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1213 check_global = TRUE;
1214 else if (server->server_type != SILC_SERVER)
1215 check_global = TRUE;
1217 /* Parse the whowas request */
1218 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1221 /* Get all clients matching that nickname from local list */
1222 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1224 &clients, &clients_count))
1225 silc_idlist_get_clients_by_hash(server->local_list,
1226 nick, server->md5hash,
1227 &clients, &clients_count);
1229 /* Check global list as well */
1231 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1233 &clients, &clients_count))
1234 silc_idlist_get_clients_by_hash(server->global_list,
1235 nick, server->md5hash,
1236 &clients, &clients_count);
1240 /* Such a client really does not exist in the SILC network. */
1241 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1242 SILC_STATUS_ERR_NO_SUCH_NICK,
1243 3, nick, strlen(nick));
1247 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1252 /* Send the command reply to the client */
1253 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1258 silc_free(server_name);
1262 /* Server side of command WHOWAS. */
1264 SILC_SERVER_CMD_FUNC(whowas)
1266 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1269 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1271 ret = silc_server_command_whowas_process(cmd);
1272 silc_server_command_free(cmd);
1275 /******************************************************************************
1279 ******************************************************************************/
1282 silc_server_command_identify_send_router(SilcServerCommandContext cmd)
1284 SilcServer server = cmd->server;
1288 old_ident = silc_command_get_ident(cmd->payload);
1289 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1290 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1292 /* Send IDENTIFY command to our router */
1293 silc_server_packet_send(server, (SilcSocketConnection)
1294 server->router->connection,
1295 SILC_PACKET_COMMAND, cmd->packet->flags,
1296 tmpbuf->data, tmpbuf->len, TRUE);
1298 /* Reprocess this packet after received reply from router */
1299 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1300 silc_command_get_ident(cmd->payload),
1301 silc_server_command_identify,
1302 silc_server_command_dup(cmd));
1303 cmd->pending = TRUE;
1304 silc_command_set_ident(cmd->payload, old_ident);
1305 silc_buffer_free(tmpbuf);
1309 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1310 SilcClientEntry **clients,
1311 uint32 *clients_count,
1312 SilcServerEntry **servers,
1313 uint32 *servers_count,
1314 SilcChannelEntry **channels,
1315 uint32 *channels_count,
1318 SilcServer server = cmd->server;
1321 uint32 argc = silc_argument_get_arg_num(cmd->args);
1323 bool check_global = FALSE;
1328 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1329 check_global = TRUE;
1330 else if (server->server_type != SILC_SERVER)
1331 check_global = TRUE;
1333 /* If ID Payload is in the command it must be used instead of names */
1334 tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1336 /* No ID, get the names. */
1338 /* If we are normal server and have not resolved information from
1339 router yet, do so now. */
1340 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1341 server->server_type == SILC_SERVER && !cmd->pending &&
1342 !server->standalone) {
1343 silc_server_command_identify_send_router(cmd);
1347 /* Try to get nickname@server. */
1348 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1351 char *nick_server = NULL;
1353 silc_parse_userfqdn(tmp, &nick, &nick_server);
1355 if (!silc_idlist_get_clients_by_hash(server->local_list,
1356 nick, server->md5hash,
1357 clients, clients_count))
1358 silc_idlist_get_clients_by_nickname(server->local_list,
1360 clients, clients_count);
1362 if (!silc_idlist_get_clients_by_hash(server->global_list,
1363 nick, server->md5hash,
1364 clients, clients_count))
1365 silc_idlist_get_clients_by_nickname(server->global_list,
1367 clients, clients_count);
1371 silc_free(nick_server);
1374 /* the nickname does not exist, send error reply */
1375 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1376 SILC_STATUS_ERR_NO_SUCH_NICK,
1377 3, tmp, strlen(tmp));
1382 /* Try to get server name */
1383 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1385 entry = silc_idlist_find_server_by_name(server->local_list,
1387 if (!entry && check_global)
1388 entry = silc_idlist_find_server_by_name(server->global_list,
1391 *servers = silc_realloc(*servers, sizeof(**servers) *
1392 (*servers_count + 1));
1393 (*servers)[(*servers_count)++] = entry;
1397 /* the server does not exist, send error reply */
1398 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1399 SILC_STATUS_ERR_NO_SUCH_SERVER,
1400 3, tmp, strlen(tmp));
1405 /* Try to get channel name */
1406 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1408 entry = silc_idlist_find_channel_by_name(server->local_list,
1410 if (!entry && check_global)
1411 entry = silc_idlist_find_channel_by_name(server->global_list,
1414 *channels = silc_realloc(*channels, sizeof(**channels) *
1415 (*channels_count + 1));
1416 (*channels)[(*channels_count)++] = entry;
1420 /* The channel does not exist, send error reply */
1421 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1422 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1423 3, tmp, strlen(tmp));
1428 if (!(*clients) && !(*servers) && !(*channels)) {
1429 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1430 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1434 /* Command includes ID, we must use that. Also check whether the command
1435 has more than one ID set - take them all. */
1437 /* Take all ID's from the command packet */
1438 for (i = 0; i < argc; i++) {
1441 tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
1445 idp = silc_id_payload_parse(tmp, len);
1447 silc_free(*clients);
1448 silc_free(*servers);
1449 silc_free(*channels);
1450 silc_server_command_send_status_reply(
1451 cmd, SILC_COMMAND_IDENTIFY,
1452 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1456 id = silc_id_payload_get_id(idp);
1458 switch (silc_id_payload_get_type(idp)) {
1460 case SILC_ID_CLIENT:
1461 entry = (void *)silc_idlist_find_client_by_id(server->local_list,
1463 if (!entry && check_global)
1464 entry = (void *)silc_idlist_find_client_by_id(server->global_list,
1467 *clients = silc_realloc(*clients, sizeof(**clients) *
1468 (*clients_count + 1));
1469 (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
1471 /* If we are normal server and have not resolved information from
1472 router yet, do so now. */
1473 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1474 server->server_type == SILC_SERVER && !cmd->pending &&
1475 !server->standalone) {
1476 silc_server_command_identify_send_router(cmd);
1477 silc_free(*clients);
1478 silc_free(*servers);
1479 silc_free(*channels);
1482 silc_server_command_send_status_data(
1483 cmd, SILC_COMMAND_IDENTIFY,
1484 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1492 case SILC_ID_SERVER:
1493 entry = (void *)silc_idlist_find_server_by_id(server->local_list,
1495 if (!entry && check_global)
1496 entry = (void *)silc_idlist_find_server_by_id(server->global_list,
1499 *servers = silc_realloc(*servers, sizeof(**servers) *
1500 (*servers_count + 1));
1501 (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
1503 /* If we are normal server and have not resolved information from
1504 router yet, do so now. */
1505 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1506 server->server_type == SILC_SERVER && !cmd->pending &&
1507 !server->standalone) {
1508 silc_server_command_identify_send_router(cmd);
1509 silc_free(*clients);
1510 silc_free(*servers);
1511 silc_free(*channels);
1514 silc_server_command_send_status_data(
1515 cmd, SILC_COMMAND_IDENTIFY,
1516 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
1523 case SILC_ID_CHANNEL:
1524 entry = (void *)silc_idlist_find_channel_by_id(server->local_list,
1526 if (!entry && check_global)
1527 entry = (void *)silc_idlist_find_channel_by_id(server->global_list,
1530 *channels = silc_realloc(*channels, sizeof(**channels) *
1531 (*channels_count + 1));
1532 (*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
1534 /* If we are normal server and have not resolved information from
1535 router yet, do so now. */
1536 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1537 server->server_type == SILC_SERVER && !cmd->pending &&
1538 !server->standalone) {
1539 silc_server_command_identify_send_router(cmd);
1540 silc_free(*clients);
1541 silc_free(*servers);
1542 silc_free(*channels);
1545 silc_server_command_send_status_data(
1546 cmd, SILC_COMMAND_IDENTIFY,
1547 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
1560 silc_free(*clients);
1561 silc_free(*servers);
1562 silc_free(*channels);
1566 /* Get the max count of reply messages allowed */
1567 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1576 /* Checks that all mandatory fields in client entry are present. If not
1577 then send WHOIS request to the server who owns the client. We use
1578 WHOIS because we want to get as much information as possible at once. */
1581 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1582 SilcClientEntry *clients,
1583 uint32 clients_count)
1585 SilcServer server = cmd->server;
1586 SilcClientEntry entry;
1587 SilcServerResolveContext resolve = NULL, r = NULL;
1588 uint32 resolve_count = 0;
1592 for (i = 0; i < clients_count; i++) {
1597 if (entry->nickname ||
1598 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1602 /* If we are normal server, and we've not resolved this client from
1603 router and it is global client, we'll check whether it is on some
1604 channel. If not then we cannot be sure about its validity, and
1605 we'll resolve it from router. */
1606 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
1607 entry->connection || silc_hash_table_count(entry->channels))
1611 /* We need to resolve this entry since it is not complete */
1613 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1614 /* The entry is being resolved (and we are not the resolver) so attach
1615 to the command reply and we're done with this one. */
1616 silc_server_command_pending(server, SILC_COMMAND_NONE,
1617 entry->resolve_cmd_ident,
1618 silc_server_command_identify,
1619 silc_server_command_dup(cmd));
1622 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1623 /* We've resolved this and it still is not ready. We'll return
1624 and are that this will be handled again after it is resolved. */
1625 for (i = 0; i < resolve_count; i++) {
1626 for (k = 0; k < r->res_argc; k++)
1627 silc_free(r->res_argv[k]);
1628 silc_free(r->res_argv);
1629 silc_free(r->res_argv_lens);
1630 silc_free(r->res_argv_types);
1635 /* We'll resolve this client */
1639 for (k = 0; k < resolve_count; k++) {
1640 if (resolve[k].router == entry->router) {
1647 resolve = silc_realloc(resolve, sizeof(*resolve) *
1648 (resolve_count + 1));
1649 r = &resolve[resolve_count];
1650 memset(r, 0, sizeof(*r));
1651 r->router = entry->router;
1652 r->ident = ++server->cmd_ident;
1656 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1658 r->res_argv_lens = silc_realloc(r->res_argv_lens,
1659 sizeof(*r->res_argv_lens) *
1661 r->res_argv_types = silc_realloc(r->res_argv_types,
1662 sizeof(*r->res_argv_types) *
1664 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1665 r->res_argv[r->res_argc] = silc_calloc(idp->len,
1666 sizeof(**r->res_argv));
1667 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1668 r->res_argv_lens[r->res_argc] = idp->len;
1669 r->res_argv_types[r->res_argc] = r->res_argc + 3;
1671 silc_buffer_free(idp);
1673 entry->resolve_cmd_ident = r->ident;
1674 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1675 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1680 /* Do the resolving */
1681 for (i = 0; i < resolve_count; i++) {
1686 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1687 now anyway so make it a good one. */
1688 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1689 r->res_argc, r->res_argv,
1693 silc_server_packet_send(server, r->router->connection,
1694 SILC_PACKET_COMMAND, cmd->packet->flags,
1695 res_cmd->data, res_cmd->len, FALSE);
1697 /* Reprocess this packet after received reply */
1698 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1700 silc_server_command_identify,
1701 silc_server_command_dup(cmd));
1702 cmd->pending = TRUE;
1704 silc_buffer_free(res_cmd);
1705 for (k = 0; k < r->res_argc; k++)
1706 silc_free(r->res_argv[k]);
1707 silc_free(r->res_argv);
1708 silc_free(r->res_argv_lens);
1709 silc_free(r->res_argv_types);
1718 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1719 SilcClientEntry *clients,
1720 uint32 clients_count,
1721 SilcServerEntry *servers,
1722 uint32 servers_count,
1723 SilcChannelEntry *channels,
1724 uint32 channels_count,
1727 SilcServer server = cmd->server;
1728 int i, k, len, valid_count;
1729 SilcBuffer packet, idp;
1730 SilcCommandStatus status;
1731 uint16 ident = silc_command_get_ident(cmd->payload);
1732 char nh[256], uh[256];
1733 SilcSocketConnection hsock;
1735 status = SILC_STATUS_OK;
1738 SilcClientEntry entry;
1740 /* Process only valid entries. */
1742 for (i = 0; i < clients_count; i++) {
1743 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1750 /* No valid entries found at all, just send error */
1753 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1755 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1756 SILC_STATUS_ERR_NO_SUCH_NICK,
1757 3, tmp, strlen(tmp));
1759 tmp = silc_argument_get_arg_type(cmd->args, 5, (uint32 *)&len);
1760 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1761 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1767 /* Process all valid client entries and send command replies */
1769 if (valid_count > 1)
1770 status = SILC_STATUS_LIST_START;
1772 for (i = 0, k = 0; i < clients_count; i++) {
1778 status = SILC_STATUS_LIST_ITEM;
1779 if (valid_count > 1 && k == valid_count - 1
1780 && !servers_count && !channels_count)
1781 status = SILC_STATUS_LIST_END;
1782 if (count && k - 1 == count)
1783 status = SILC_STATUS_LIST_END;
1784 if (count && k - 1 > count)
1787 /* Send IDENTIFY reply */
1789 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1790 memset(uh, 0, sizeof(uh));
1791 memset(nh, 0, sizeof(nh));
1792 strncat(nh, entry->nickname, strlen(entry->nickname));
1793 if (!strchr(entry->nickname, '@')) {
1794 strncat(nh, "@", 1);
1795 if (entry->servername) {
1796 strncat(nh, entry->servername, strlen(entry->servername));
1798 len = entry->router ? strlen(entry->router->server_name) :
1799 strlen(server->server_name);
1800 strncat(nh, entry->router ? entry->router->server_name :
1801 server->server_name, len);
1805 if (!entry->username) {
1806 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1808 2, idp->data, idp->len,
1811 strncat(uh, entry->username, strlen(entry->username));
1812 if (!strchr(entry->username, '@')) {
1813 strncat(uh, "@", 1);
1814 hsock = (SilcSocketConnection)entry->connection;
1815 len = strlen(hsock->hostname);
1816 strncat(uh, hsock->hostname, len);
1819 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1821 2, idp->data, idp->len,
1826 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1827 0, packet->data, packet->len, FALSE);
1829 silc_buffer_free(packet);
1830 silc_buffer_free(idp);
1837 SilcServerEntry entry;
1839 if (status == SILC_STATUS_OK && servers_count > 1)
1840 status = SILC_STATUS_LIST_START;
1842 for (i = 0, k = 0; i < servers_count; i++) {
1846 status = SILC_STATUS_LIST_ITEM;
1847 if (servers_count > 1 && k == servers_count - 1 && !channels_count)
1848 status = SILC_STATUS_LIST_END;
1849 if (count && k - 1 == count)
1850 status = SILC_STATUS_LIST_END;
1851 if (count && k - 1 > count)
1854 /* Send IDENTIFY reply */
1855 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1857 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1859 2, idp->data, idp->len,
1860 3, entry->server_name,
1861 entry->server_name ?
1862 strlen(entry->server_name) : 0);
1863 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1864 0, packet->data, packet->len, FALSE);
1866 silc_buffer_free(packet);
1867 silc_buffer_free(idp);
1874 SilcChannelEntry entry;
1876 if (status == SILC_STATUS_OK && channels_count > 1)
1877 status = SILC_STATUS_LIST_START;
1879 for (i = 0, k = 0; i < channels_count; i++) {
1880 entry = channels[i];
1883 status = SILC_STATUS_LIST_ITEM;
1884 if (channels_count > 1 && k == channels_count - 1)
1885 status = SILC_STATUS_LIST_END;
1886 if (count && k - 1 == count)
1887 status = SILC_STATUS_LIST_END;
1888 if (count && k - 1 > count)
1891 /* Send IDENTIFY reply */
1892 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1894 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1896 2, idp->data, idp->len,
1897 3, entry->channel_name,
1898 entry->channel_name ?
1899 strlen(entry->channel_name): 0);
1900 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1901 0, packet->data, packet->len, FALSE);
1903 silc_buffer_free(packet);
1904 silc_buffer_free(idp);
1912 silc_server_command_identify_process(SilcServerCommandContext cmd)
1916 SilcClientEntry *clients = NULL;
1917 SilcServerEntry *servers = NULL;
1918 SilcChannelEntry *channels = NULL;
1919 uint32 clients_count = 0, servers_count = 0, channels_count = 0;
1921 /* Parse the IDENTIFY request */
1922 ret = silc_server_command_identify_parse(cmd,
1923 &clients, &clients_count,
1924 &servers, &servers_count,
1925 &channels, &channels_count,
1931 /* Check that all mandatory fields are present and request those data
1932 from the server who owns the client if necessary. */
1933 if (clients && !silc_server_command_identify_check_client(cmd, clients,
1939 /* Send the command reply to the client */
1940 silc_server_command_identify_send_reply(cmd,
1941 clients, clients_count,
1942 servers, servers_count,
1943 channels, channels_count,
1949 silc_free(channels);
1953 SILC_SERVER_CMD_FUNC(identify)
1955 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1958 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1960 ret = silc_server_command_identify_process(cmd);
1961 silc_server_command_free(cmd);
1964 /* Server side of command NICK. Sets nickname for user. Setting
1965 nickname causes generation of a new client ID for the client. The
1966 new client ID is sent to the client after changing the nickname. */
1968 SILC_SERVER_CMD_FUNC(nick)
1970 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1971 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1972 SilcServer server = cmd->server;
1973 SilcBuffer packet, nidp, oidp = NULL;
1974 SilcClientID *new_id;
1977 uint16 ident = silc_command_get_ident(cmd->payload);
1980 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1983 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
1985 /* Check nickname */
1986 nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
1989 if (silc_server_name_bad_chars(nick, nick_len) == TRUE) {
1990 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1991 SILC_STATUS_ERR_BAD_NICKNAME);
1995 /* Check for same nickname */
1996 if (!strcmp(client->nickname, nick)) {
1997 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2001 /* Create new Client ID */
2002 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
2004 cmd->server->md5hash, nick,
2007 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2010 /* Send notify about nickname change to our router. We send the new
2011 ID and ask to replace it with the old one. If we are router the
2012 packet is broadcasted. Send NICK_CHANGE notify. */
2013 if (!server->standalone)
2014 silc_server_send_notify_nick_change(server, server->router->connection,
2015 server->server_type == SILC_SERVER ?
2016 FALSE : TRUE, client->id,
2019 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2021 /* Remove old cache entry */
2022 silc_idcache_del_by_context(server->local_list->clients, client);
2025 silc_free(client->id);
2027 /* Save the nickname as this client is our local client */
2028 silc_free(client->nickname);
2030 client->nickname = strdup(nick);
2031 client->id = new_id;
2033 /* Update client cache */
2034 silc_idcache_add(server->local_list->clients, client->nickname,
2035 client->id, (void *)client, 0, NULL);
2037 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2039 /* Send NICK_CHANGE notify to the client's channels */
2040 silc_server_send_notify_on_channels(server, NULL, client,
2041 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
2042 oidp->data, oidp->len,
2043 nidp->data, nidp->len);
2046 /* Send the new Client ID as reply command back to client */
2047 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
2048 SILC_STATUS_OK, ident, 1,
2049 2, nidp->data, nidp->len);
2050 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2051 0, packet->data, packet->len, FALSE);
2053 silc_buffer_free(packet);
2054 silc_buffer_free(nidp);
2056 silc_buffer_free(oidp);
2059 silc_server_command_free(cmd);
2062 /* Sends the LIST command reply */
2065 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2066 SilcChannelEntry *lch,
2068 SilcChannelEntry *gch,
2072 SilcBuffer packet, idp;
2073 SilcChannelEntry entry;
2074 SilcCommandStatus status;
2075 uint16 ident = silc_command_get_ident(cmd->payload);
2077 unsigned char usercount[4];
2079 int valid_lcount = 0, valid_rcount = 0;
2081 for (i = 0; i < lch_count; i++) {
2082 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2087 for (i = 0; i < gch_count; i++) {
2088 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2094 status = SILC_STATUS_OK;
2095 if ((lch_count + gch_count) > 1)
2096 status = SILC_STATUS_LIST_START;
2099 for (i = 0, k = 0; i < lch_count; i++) {
2105 status = SILC_STATUS_LIST_ITEM;
2106 if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
2107 status = SILC_STATUS_LIST_END;
2109 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2111 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2112 topic = "*private*";
2113 memset(usercount, 0, sizeof(usercount));
2115 topic = entry->topic;
2116 users = silc_hash_table_count(entry->user_list);
2117 SILC_PUT32_MSB(users, usercount);
2120 /* Send the reply */
2122 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2124 2, idp->data, idp->len,
2125 3, entry->channel_name,
2126 strlen(entry->channel_name),
2127 4, topic, topic ? strlen(topic) : 0,
2129 silc_server_packet_send(cmd->server, cmd->sock,
2130 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2131 packet->len, FALSE);
2132 silc_buffer_free(packet);
2133 silc_buffer_free(idp);
2138 for (i = 0, k = 0; i < gch_count; i++) {
2144 status = SILC_STATUS_LIST_ITEM;
2145 if (valid_rcount > 1 && k == valid_rcount - 1)
2146 status = SILC_STATUS_LIST_END;
2148 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2150 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2151 topic = "*private*";
2152 memset(usercount, 0, sizeof(usercount));
2154 topic = entry->topic;
2155 users = silc_hash_table_count(entry->user_list);
2156 SILC_PUT32_MSB(users, usercount);
2159 /* Send the reply */
2161 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2163 2, idp->data, idp->len,
2164 3, entry->channel_name,
2165 strlen(entry->channel_name),
2166 4, topic, topic ? strlen(topic) : 0,
2168 silc_server_packet_send(cmd->server, cmd->sock,
2169 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2170 packet->len, FALSE);
2171 silc_buffer_free(packet);
2172 silc_buffer_free(idp);
2177 /* Server side of LIST command. This lists the channel of the requested
2178 server. Secret channels are not listed. */
2180 SILC_SERVER_CMD_FUNC(list)
2182 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2183 SilcServer server = cmd->server;
2184 SilcChannelID *channel_id = NULL;
2187 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2188 uint32 lch_count = 0, gch_count = 0;
2190 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2192 /* If we are normal server, send the command to router, since we
2193 want to know all channels in the network. */
2194 if (!cmd->pending && server->server_type == SILC_SERVER &&
2195 !server->standalone) {
2199 old_ident = silc_command_get_ident(cmd->payload);
2200 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2201 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2202 silc_server_packet_send(server, server->router->connection,
2203 SILC_PACKET_COMMAND, cmd->packet->flags,
2204 tmpbuf->data, tmpbuf->len, TRUE);
2206 /* Reprocess this packet after received reply from router */
2207 silc_server_command_pending(server, SILC_COMMAND_LIST,
2208 silc_command_get_ident(cmd->payload),
2209 silc_server_command_list,
2210 silc_server_command_dup(cmd));
2211 cmd->pending = TRUE;
2212 silc_command_set_ident(cmd->payload, old_ident);
2213 silc_buffer_free(tmpbuf);
2217 /* Get Channel ID */
2218 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2220 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2222 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2223 SILC_STATUS_ERR_NO_CHANNEL_ID);
2228 /* Get the channels from local list */
2229 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2232 /* Get the channels from global list */
2233 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2236 /* Send the reply */
2237 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2238 gchannels, gch_count);
2240 silc_free(lchannels);
2241 silc_free(gchannels);
2244 silc_server_command_free(cmd);
2247 /* Server side of TOPIC command. Sets topic for channel and/or returns
2248 current topic to client. */
2250 SILC_SERVER_CMD_FUNC(topic)
2252 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2253 SilcServer server = cmd->server;
2254 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2255 SilcChannelID *channel_id;
2256 SilcChannelEntry channel;
2257 SilcChannelClientEntry chl;
2258 SilcBuffer packet, idp;
2260 uint32 argc, tmp_len;
2261 uint16 ident = silc_command_get_ident(cmd->payload);
2263 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2265 argc = silc_argument_get_arg_num(cmd->args);
2267 /* Get Channel ID */
2268 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2270 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2271 SILC_STATUS_ERR_NO_CHANNEL_ID);
2274 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2276 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2277 SILC_STATUS_ERR_NO_CHANNEL_ID);
2281 /* Check whether the channel exists */
2282 channel = silc_idlist_find_channel_by_id(server->local_list,
2285 channel = silc_idlist_find_channel_by_id(server->global_list,
2288 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2289 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2296 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2298 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2299 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2303 if (strlen(tmp) > 256) {
2304 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2305 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2309 /* See whether the client is on channel and has rights to change topic */
2310 if (!silc_hash_table_find(channel->user_list, client, NULL,
2312 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2313 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2317 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2318 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2319 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2320 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2325 /* Set the topic for channel */
2326 silc_free(channel->topic);
2327 channel->topic = strdup(tmp);
2329 /* Send TOPIC_SET notify type to the network */
2330 if (!server->standalone)
2331 silc_server_send_notify_topic_set(server, server->router->connection,
2332 server->server_type == SILC_ROUTER ?
2333 TRUE : FALSE, channel,
2334 client->id, SILC_ID_CLIENT,
2337 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2339 /* Send notify about topic change to all clients on the channel */
2340 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2341 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2342 idp->data, idp->len,
2343 channel->topic, strlen(channel->topic));
2344 silc_buffer_free(idp);
2347 /* Send the topic to client as reply packet */
2348 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2349 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2350 SILC_STATUS_OK, ident, 2,
2351 2, idp->data, idp->len,
2354 strlen(channel->topic) : 0);
2355 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2356 0, packet->data, packet->len, FALSE);
2358 silc_buffer_free(packet);
2359 silc_buffer_free(idp);
2360 silc_free(channel_id);
2363 silc_server_command_free(cmd);
2366 /* Server side of INVITE command. Invites some client to join some channel.
2367 This command is also used to manage the invite list of the channel. */
2369 SILC_SERVER_CMD_FUNC(invite)
2371 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2372 SilcServer server = cmd->server;
2373 SilcSocketConnection sock = cmd->sock, dest_sock;
2374 SilcChannelClientEntry chl;
2375 SilcClientEntry sender, dest;
2376 SilcClientID *dest_id = NULL;
2377 SilcChannelEntry channel;
2378 SilcChannelID *channel_id = NULL;
2379 SilcIDListData idata;
2380 SilcBuffer idp, idp2, packet;
2381 unsigned char *tmp, *add, *del;
2383 uint16 ident = silc_command_get_ident(cmd->payload);
2385 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2387 /* Get Channel ID */
2388 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2390 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2391 SILC_STATUS_ERR_NO_CHANNEL_ID);
2394 channel_id = silc_id_payload_parse_id(tmp, len);
2396 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2397 SILC_STATUS_ERR_NO_CHANNEL_ID);
2401 /* Get the channel entry */
2402 channel = silc_idlist_find_channel_by_id(server->local_list,
2405 channel = silc_idlist_find_channel_by_id(server->global_list,
2408 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2409 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2414 /* Check whether the sender of this command is on the channel. */
2415 sender = (SilcClientEntry)sock->user_data;
2416 if (!silc_server_client_on_channel(sender, channel)) {
2417 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2418 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2422 /* Check whether the channel is invite-only channel. If yes then the
2423 sender of this command must be at least channel operator. */
2424 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2425 silc_hash_table_find(channel->user_list, sender, NULL, (void *)&chl);
2426 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2427 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2428 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2433 /* Get destination client ID */
2434 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2439 dest_id = silc_id_payload_parse_id(tmp, len);
2441 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2442 SILC_STATUS_ERR_NO_CLIENT_ID);
2446 /* Get the client entry */
2447 dest = silc_server_get_client_resolve(server, dest_id, &resolve);
2449 if (server->server_type != SILC_SERVER || !resolve) {
2450 silc_server_command_send_status_reply(
2451 cmd, SILC_COMMAND_INVITE,
2452 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2456 /* The client info is being resolved. Reprocess this packet after
2457 receiving the reply to the query. */
2458 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2460 silc_server_command_invite,
2461 silc_server_command_dup(cmd));
2462 cmd->pending = TRUE;
2463 silc_free(channel_id);
2468 /* Check whether the requested client is already on the channel. */
2469 if (silc_server_client_on_channel(dest, channel)) {
2470 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2471 SILC_STATUS_ERR_USER_ON_CHANNEL);
2475 /* Get route to the client */
2476 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2478 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2479 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2483 memset(invite, 0, sizeof(invite));
2484 strncat(invite, dest->nickname, strlen(dest->nickname));
2485 strncat(invite, "!", 1);
2486 strncat(invite, dest->username, strlen(dest->username));
2487 if (!strchr(dest->username, '@')) {
2488 strncat(invite, "@", 1);
2489 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2492 len = strlen(invite);
2493 if (!channel->invite_list)
2494 channel->invite_list = silc_calloc(len + 2,
2495 sizeof(*channel->invite_list));
2497 channel->invite_list = silc_realloc(channel->invite_list,
2498 sizeof(*channel->invite_list) *
2500 strlen(channel->invite_list) + 2));
2501 strncat(channel->invite_list, invite, len);
2502 strncat(channel->invite_list, ",", 1);
2504 /* Send notify to the client that is invited to the channel */
2505 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2506 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2507 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2509 SILC_NOTIFY_TYPE_INVITE, 3,
2510 idp->data, idp->len,
2511 channel->channel_name,
2512 strlen(channel->channel_name),
2513 idp2->data, idp2->len);
2514 silc_buffer_free(idp);
2515 silc_buffer_free(idp2);
2518 /* Add the client to the invite list of the channel */
2519 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2521 if (!channel->invite_list)
2522 channel->invite_list = silc_calloc(len + 2,
2523 sizeof(*channel->invite_list));
2525 channel->invite_list = silc_realloc(channel->invite_list,
2526 sizeof(*channel->invite_list) *
2528 strlen(channel->invite_list) + 2));
2529 if (add[len - 1] == ',')
2530 add[len - 1] = '\0';
2532 strncat(channel->invite_list, add, len);
2533 strncat(channel->invite_list, ",", 1);
2536 /* Get the invite to be removed and remove it from the list */
2537 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2538 if (del && channel->invite_list) {
2539 char *start, *end, *n;
2541 if (!strncmp(channel->invite_list, del,
2542 strlen(channel->invite_list) - 1)) {
2543 silc_free(channel->invite_list);
2544 channel->invite_list = NULL;
2546 start = strstr(channel->invite_list, del);
2547 if (start && strlen(start) >= len) {
2549 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2550 strncat(n, channel->invite_list, start - channel->invite_list);
2551 strncat(n, end + 1, ((channel->invite_list +
2552 strlen(channel->invite_list)) - end) - 1);
2553 silc_free(channel->invite_list);
2554 channel->invite_list = n;
2559 /* Send notify to the primary router */
2560 if (!server->standalone)
2561 silc_server_send_notify_invite(server, server->router->connection,
2562 server->server_type == SILC_ROUTER ?
2563 TRUE : FALSE, channel,
2564 sender->id, add, del);
2566 /* Send command reply */
2567 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2571 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2572 SILC_STATUS_OK, ident, 2,
2574 3, channel->invite_list,
2575 channel->invite_list ?
2576 strlen(channel->invite_list) : 0);
2579 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2580 SILC_STATUS_OK, ident, 1,
2582 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2583 packet->data, packet->len, FALSE);
2584 silc_buffer_free(packet);
2588 silc_free(channel_id);
2589 silc_server_command_free(cmd);
2594 SilcSocketConnection sock;
2598 /* Quits connection to client. This gets called if client won't
2599 close the connection even when it has issued QUIT command. */
2601 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2603 QuitInternal q = (QuitInternal)context;
2605 /* Free all client specific data, such as client entry and entires
2606 on channels this client may be on. */
2607 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2609 q->sock->user_data = NULL;
2611 /* Close the connection on our side */
2612 silc_server_close_connection(q->server, q->sock);
2614 silc_free(q->signoff);
2618 /* Quits SILC session. This is the normal way to disconnect client. */
2620 SILC_SERVER_CMD_FUNC(quit)
2622 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2623 SilcServer server = cmd->server;
2624 SilcSocketConnection sock = cmd->sock;
2626 unsigned char *tmp = NULL;
2629 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2631 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2634 /* Get destination ID */
2635 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2639 q = silc_calloc(1, sizeof(*q));
2642 q->signoff = tmp ? strdup(tmp) : NULL;
2644 /* We quit the connection with little timeout */
2645 silc_schedule_task_add(server->schedule, sock->sock,
2646 silc_server_command_quit_cb, (void *)q,
2647 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2650 silc_server_command_free(cmd);
2653 /* Server side of command KILL. This command is used by router operator
2654 to remove an client from the SILC Network temporarily. */
2656 SILC_SERVER_CMD_FUNC(kill)
2658 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2659 SilcServer server = cmd->server;
2660 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2661 SilcClientEntry remote_client;
2662 SilcClientID *client_id;
2663 unsigned char *tmp, *comment;
2664 uint32 tmp_len, tmp_len2;
2667 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2669 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2672 /* KILL command works only on router */
2673 if (server->server_type != SILC_ROUTER) {
2674 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2675 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2679 /* Check whether client has the permissions. */
2680 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2681 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2682 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2686 /* Get the client ID */
2687 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2689 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2690 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2693 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2695 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2696 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2700 /* Get the client entry */
2701 remote_client = silc_idlist_find_client_by_id(server->local_list,
2702 client_id, TRUE, NULL);
2704 if (!remote_client) {
2705 remote_client = silc_idlist_find_client_by_id(server->global_list,
2706 client_id, TRUE, NULL);
2708 if (!remote_client) {
2709 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2710 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2716 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2720 /* Send reply to the sender */
2721 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2724 /* Send the KILL notify packets. First send it to the channel, then
2725 to our primary router and then directly to the client who is being
2726 killed right now. */
2728 /* Send KILLED notify to the channels. It is not sent to the client
2729 as it will be sent differently destined directly to the client and not
2731 silc_server_send_notify_on_channels(server, remote_client,
2732 remote_client, SILC_NOTIFY_TYPE_KILLED,
2735 comment, comment ? tmp_len2 : 0);
2737 /* Send KILLED notify to primary route */
2738 if (!server->standalone)
2739 silc_server_send_notify_killed(server, server->router->connection, TRUE,
2740 remote_client->id, comment);
2742 /* Send KILLED notify to the client directly */
2743 silc_server_send_notify_killed(server, remote_client->connection ?
2744 remote_client->connection :
2745 remote_client->router->connection, FALSE,
2746 remote_client->id, comment);
2748 /* Remove the client from all channels. This generates new keys to the
2749 channels as well. */
2750 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2753 /* Remove the client entry, If it is locally connected then we will also
2754 disconnect the client here */
2755 if (remote_client->connection) {
2756 /* Remove locally conneted client */
2757 SilcSocketConnection sock = remote_client->connection;
2758 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2759 silc_server_close_connection(server, sock);
2761 /* Update statistics */
2762 if (remote_client->connection)
2763 server->stat.my_clients--;
2764 if (server->server_type == SILC_ROUTER)
2765 server->stat.cell_clients--;
2766 SILC_OPER_STATS_UPDATE(remote_client, server, SILC_UMODE_SERVER_OPERATOR);
2767 SILC_OPER_STATS_UPDATE(remote_client, router, SILC_UMODE_ROUTER_OPERATOR);
2769 /* Remove remote client */
2770 silc_idlist_del_client(local ? server->local_list :
2771 server->global_list, remote_client);
2775 silc_server_command_free(cmd);
2778 /* Server side of command INFO. This sends information about us to
2779 the client. If client requested specific server we will send the
2780 command to that server. */
2782 SILC_SERVER_CMD_FUNC(info)
2784 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2785 SilcServer server = cmd->server;
2786 SilcBuffer packet, idp;
2789 char *dest_server, *server_info = NULL, *server_name;
2790 uint16 ident = silc_command_get_ident(cmd->payload);
2791 SilcServerEntry entry = NULL;
2792 SilcServerID *server_id = NULL;
2794 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2796 /* Get server name */
2797 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2800 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2802 server_id = silc_id_payload_parse_id(tmp, tmp_len);
2804 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2805 SILC_STATUS_ERR_NO_SERVER_ID);
2811 /* Check whether we have this server cached */
2812 entry = silc_idlist_find_server_by_id(server->local_list,
2813 server_id, TRUE, NULL);
2815 entry = silc_idlist_find_server_by_id(server->global_list,
2816 server_id, TRUE, NULL);
2817 if (!entry && server->server_type != SILC_SERVER) {
2818 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2819 SILC_STATUS_ERR_NO_SUCH_SERVER);
2825 /* Some buggy servers has sent request to router about themselves. */
2826 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2829 if ((!dest_server && !server_id && !entry) || (entry &&
2830 entry == server->id_entry) ||
2831 (dest_server && !cmd->pending &&
2832 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2833 /* Send our reply */
2834 char info_string[256];
2836 memset(info_string, 0, sizeof(info_string));
2837 snprintf(info_string, sizeof(info_string),
2838 "location: %s server: %s admin: %s <%s>",
2839 server->config->admin_info->location,
2840 server->config->admin_info->server_type,
2841 server->config->admin_info->admin_name,
2842 server->config->admin_info->admin_email);
2844 server_info = info_string;
2845 entry = server->id_entry;
2847 /* Check whether we have this server cached */
2848 if (!entry && dest_server) {
2849 entry = silc_idlist_find_server_by_name(server->global_list,
2850 dest_server, TRUE, NULL);
2852 entry = silc_idlist_find_server_by_name(server->local_list,
2853 dest_server, TRUE, NULL);
2857 if (!cmd->pending &&
2858 server->server_type != SILC_SERVER && entry && !entry->server_info) {
2859 /* Send to the server */
2863 old_ident = silc_command_get_ident(cmd->payload);
2864 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2865 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2867 silc_server_packet_send(server, entry->connection,
2868 SILC_PACKET_COMMAND, cmd->packet->flags,
2869 tmpbuf->data, tmpbuf->len, TRUE);
2871 /* Reprocess this packet after received reply from router */
2872 silc_server_command_pending(server, SILC_COMMAND_INFO,
2873 silc_command_get_ident(cmd->payload),
2874 silc_server_command_info,
2875 silc_server_command_dup(cmd));
2876 cmd->pending = TRUE;
2877 silc_command_set_ident(cmd->payload, old_ident);
2878 silc_buffer_free(tmpbuf);
2882 if (!entry && !cmd->pending && !server->standalone) {
2883 /* Send to the primary router */
2887 old_ident = silc_command_get_ident(cmd->payload);
2888 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2889 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2891 silc_server_packet_send(server, server->router->connection,
2892 SILC_PACKET_COMMAND, cmd->packet->flags,
2893 tmpbuf->data, tmpbuf->len, TRUE);
2895 /* Reprocess this packet after received reply from router */
2896 silc_server_command_pending(server, SILC_COMMAND_INFO,
2897 silc_command_get_ident(cmd->payload),
2898 silc_server_command_info,
2899 silc_server_command_dup(cmd));
2900 cmd->pending = TRUE;
2901 silc_command_set_ident(cmd->payload, old_ident);
2902 silc_buffer_free(tmpbuf);
2907 silc_free(server_id);
2910 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2911 SILC_STATUS_ERR_NO_SUCH_SERVER);
2915 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2917 server_info = entry->server_info;
2918 server_name = entry->server_name;
2920 /* Send the reply */
2921 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2922 SILC_STATUS_OK, ident, 3,
2923 2, idp->data, idp->len,
2925 strlen(server_name),
2928 strlen(server_info) : 0);
2929 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2930 packet->data, packet->len, FALSE);
2932 silc_buffer_free(packet);
2933 silc_buffer_free(idp);
2936 silc_server_command_free(cmd);
2939 /* Server side of command PING. This just replies to the ping. */
2941 SILC_SERVER_CMD_FUNC(ping)
2943 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2944 SilcServer server = cmd->server;
2949 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
2952 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2954 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2955 SILC_STATUS_ERR_NO_SERVER_ID);
2958 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2962 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2963 /* Send our reply */
2964 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2967 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2968 SILC_STATUS_ERR_NO_SUCH_SERVER);
2975 silc_server_command_free(cmd);
2978 /* Internal routine to join channel. The channel sent to this function
2979 has been either created or resolved from ID lists. This joins the sent
2980 client to the channel. */
2982 static void silc_server_command_join_channel(SilcServer server,
2983 SilcServerCommandContext cmd,
2984 SilcChannelEntry channel,
2985 SilcClientID *client_id,
2989 const unsigned char *auth,
2992 SilcSocketConnection sock = cmd->sock;
2994 uint32 tmp_len, user_count;
2995 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
2996 SilcClientEntry client;
2997 SilcChannelClientEntry chl;
2998 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
2999 uint16 ident = silc_command_get_ident(cmd->payload);
3000 char check[512], check2[512];
3001 bool founder = FALSE;
3004 SILC_LOG_DEBUG(("Start"));
3009 /* Get the client entry */
3010 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3011 client = (SilcClientEntry)sock->user_data;
3013 client = silc_server_get_client_resolve(server, client_id, &resolve);
3019 silc_server_command_send_status_reply(
3020 cmd, SILC_COMMAND_JOIN,
3021 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3025 /* The client info is being resolved. Reprocess this packet after
3026 receiving the reply to the query. */
3027 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
3029 silc_server_command_join,
3030 silc_server_command_dup(cmd));
3031 cmd->pending = TRUE;
3035 cmd->pending = FALSE;
3039 * Check founder auth payload if provided. If client can gain founder
3040 * privileges it can override various conditions on joining the channel,
3041 * and can have directly the founder mode set on the channel.
3043 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3044 SilcIDListData idata = (SilcIDListData)client;
3046 if (channel->founder_key && idata->public_key &&
3047 silc_pkcs_public_key_compare(channel->founder_key,
3048 idata->public_key)) {
3049 void *auth_data = (channel->founder_method == SILC_AUTH_PASSWORD ?
3050 (void *)channel->founder_passwd :
3051 (void *)channel->founder_key);
3052 uint32 auth_data_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
3053 channel->founder_passwd_len : 0);
3055 /* Check whether the client is to become founder */
3056 if (silc_auth_verify_data(auth, auth_len, channel->founder_method,
3057 auth_data, auth_data_len,
3058 idata->hash, client->id, SILC_ID_CLIENT)) {
3059 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3066 * Check channel modes
3070 memset(check, 0, sizeof(check));
3071 memset(check2, 0, sizeof(check2));
3072 strncat(check, client->nickname, strlen(client->nickname));
3073 strncat(check, "!", 1);
3074 strncat(check, client->username, strlen(client->username));
3075 if (!strchr(client->username, '@')) {
3076 strncat(check, "@", 1);
3077 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3080 strncat(check2, client->nickname, strlen(client->nickname));
3081 if (!strchr(client->nickname, '@')) {
3082 strncat(check2, "@", 1);
3083 strncat(check2, server->server_name, strlen(server->server_name));
3085 strncat(check2, "!", 1);
3086 strncat(check2, client->username, strlen(client->username));
3087 if (!strchr(client->username, '@')) {
3088 strncat(check2, "@", 1);
3089 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3092 /* Check invite list if channel is invite-only channel */
3093 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3094 if (!channel->invite_list ||
3095 (!silc_string_match(channel->invite_list, check) &&
3096 !silc_string_match(channel->invite_list, check2))) {
3097 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3098 SILC_STATUS_ERR_NOT_INVITED);
3103 /* Check ban list if it exists. If the client's nickname, server,
3104 username and/or hostname is in the ban list the access to the
3105 channel is denied. */
3106 if (channel->ban_list) {
3107 if (silc_string_match(channel->ban_list, check) ||
3108 silc_string_match(channel->ban_list, check2)) {
3109 silc_server_command_send_status_reply(
3110 cmd, SILC_COMMAND_JOIN,
3111 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
3116 /* Check user count limit if set. */
3117 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3118 if (silc_hash_table_count(channel->user_list) + 1 >
3119 channel->user_limit) {
3120 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3121 SILC_STATUS_ERR_CHANNEL_IS_FULL);
3127 /* Check the channel passphrase if set. */
3128 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3129 /* Get passphrase */
3130 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3132 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
3133 memcpy(passphrase, tmp, tmp_len);
3136 if (!passphrase || !channel->passphrase ||
3137 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3138 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3139 SILC_STATUS_ERR_BAD_PASSWORD);
3145 * Client is allowed to join to the channel. Make it happen.
3148 /* Check whether the client already is on the channel */
3149 if (silc_server_client_on_channel(client, channel)) {
3150 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3151 SILC_STATUS_ERR_USER_ON_CHANNEL);
3155 /* Generate new channel key as protocol dictates */
3157 if (!silc_server_create_channel_key(server, channel, 0))
3160 /* Send the channel key. This is broadcasted to the channel but is not
3161 sent to the client who is joining to the channel. */
3162 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3163 silc_server_send_channel_key(server, NULL, channel,
3164 server->server_type == SILC_ROUTER ?
3165 FALSE : !server->standalone);
3168 /* Join the client to the channel by adding it to channel's user list.
3169 Add also the channel to client entry's channels list for fast cross-
3171 chl = silc_calloc(1, sizeof(*chl));
3173 chl->client = client;
3174 chl->channel = channel;
3175 silc_hash_table_add(channel->user_list, client, chl);
3176 silc_hash_table_add(client->channels, channel, chl);
3178 /* Get users on the channel */
3179 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3182 /* Encode Client ID Payload of the original client who wants to join */
3183 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3185 /* Encode command reply packet */
3186 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3187 SILC_PUT32_MSB(channel->mode, mode);
3188 SILC_PUT32_MSB(created, tmp2);
3189 SILC_PUT32_MSB(user_count, tmp3);
3191 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3192 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3193 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
3194 strlen(channel->channel_key->
3196 channel->channel_key->cipher->name,
3197 channel->key_len / 8, channel->key);
3202 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3203 SILC_STATUS_OK, ident, 13,
3204 2, channel->channel_name,
3205 strlen(channel->channel_name),
3206 3, chidp->data, chidp->len,
3207 4, clidp->data, clidp->len,
3210 7, keyp ? keyp->data : NULL,
3211 keyp ? keyp->len : 0,
3212 8, channel->ban_list,
3214 strlen(channel->ban_list) : 0,
3215 9, channel->invite_list,
3216 channel->invite_list ?
3217 strlen(channel->invite_list) : 0,
3220 strlen(channel->topic) : 0,
3221 11, silc_hmac_get_name(channel->hmac),
3222 strlen(silc_hmac_get_name(channel->
3225 13, user_list->data, user_list->len,
3226 14, mode_list->data,
3229 /* Send command reply */
3230 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3231 reply->data, reply->len, FALSE);
3233 /* Send JOIN notify to locally connected clients on the channel. If
3234 we are normal server then router will send or have sent JOIN notify
3235 already. However since we've added the client already to our channel
3236 we'll ignore it (in packet_receive.c) so we must send it here. If
3237 we are router then this will send it to local clients and local
3239 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3240 SILC_NOTIFY_TYPE_JOIN, 2,
3241 clidp->data, clidp->len,
3242 chidp->data, chidp->len);
3244 if (!cmd->pending) {
3245 /* Send JOIN notify packet to our primary router */
3246 if (!server->standalone)
3247 silc_server_send_notify_join(server, server->router->connection,
3248 server->server_type == SILC_ROUTER ?
3249 TRUE : FALSE, channel, client->id);
3252 /* Distribute the channel key to all backup routers. */
3253 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3254 keyp->data, keyp->len, FALSE, TRUE);
3257 /* If client became founder by providing correct founder auth data
3258 notify the mode change to the channel. */
3260 SILC_PUT32_MSB(chl->mode, mode);
3261 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3262 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3263 clidp->data, clidp->len,
3264 mode, 4, clidp->data, clidp->len);
3266 /* Set CUMODE notify type to network */
3267 if (!server->standalone)
3268 silc_server_send_notify_cumode(server, server->router->connection,
3269 server->server_type == SILC_ROUTER ?
3270 TRUE : FALSE, channel,
3271 chl->mode, client->id, SILC_ID_CLIENT,
3275 silc_buffer_free(reply);
3276 silc_buffer_free(clidp);
3277 silc_buffer_free(chidp);
3278 silc_buffer_free(keyp);
3279 silc_buffer_free(user_list);
3280 silc_buffer_free(mode_list);
3283 silc_free(passphrase);
3286 /* Server side of command JOIN. Joins client into requested channel. If
3287 the channel does not exist it will be created. */
3289 SILC_SERVER_CMD_FUNC(join)
3291 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3292 SilcServer server = cmd->server;
3293 unsigned char *auth;
3294 uint32 tmp_len, auth_len;
3295 char *tmp, *channel_name = NULL, *cipher, *hmac;
3296 SilcChannelEntry channel;
3298 bool created = FALSE, create_key = TRUE;
3299 SilcClientID *client_id;
3301 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3303 /* Get channel name */
3304 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3306 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3307 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3313 channel_name[255] = '\0';
3315 if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
3316 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3317 SILC_STATUS_ERR_BAD_CHANNEL);
3321 /* Get Client ID of the client who is joining to the channel */
3322 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3324 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3325 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3328 client_id = silc_id_payload_parse_id(tmp, tmp_len);
3330 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3331 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3335 /* Get cipher, hmac name and auth payload */
3336 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3337 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3338 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3340 /* See if the channel exists */
3341 channel = silc_idlist_find_channel_by_name(server->local_list,
3342 channel_name, NULL);
3344 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3345 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3346 client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
3348 if (!channel || channel->disabled) {
3349 /* Channel not found */
3351 /* If we are standalone server we don't have a router, we just create
3352 the channel by ourselves. */
3353 if (server->standalone) {
3354 channel = silc_server_create_new_channel(server, server->id, cipher,
3355 hmac, channel_name, TRUE);
3357 silc_server_command_send_status_reply(
3358 cmd, SILC_COMMAND_JOIN,
3359 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3363 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3369 /* The channel does not exist on our server. If we are normal server
3370 we will send JOIN command to our router which will handle the
3371 joining procedure (either creates the channel if it doesn't exist
3372 or joins the client to it). */
3373 if (server->server_type != SILC_ROUTER) {
3377 /* If this is pending command callback then we've resolved
3378 it and it didn't work, return since we've notified the
3379 client already in the command reply callback. */
3383 old_ident = silc_command_get_ident(cmd->payload);
3384 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3385 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3387 /* Send JOIN command to our router */
3388 silc_server_packet_send(server, (SilcSocketConnection)
3389 server->router->connection,
3390 SILC_PACKET_COMMAND, cmd->packet->flags,
3391 tmpbuf->data, tmpbuf->len, TRUE);
3393 /* Reprocess this packet after received reply from router */
3394 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3395 silc_command_get_ident(cmd->payload),
3396 silc_server_command_join,
3397 silc_server_command_dup(cmd));
3398 cmd->pending = TRUE;
3399 silc_command_set_ident(cmd->payload, old_ident);
3403 /* We are router and the channel does not seem exist so we will check
3404 our global list as well for the channel. */
3405 channel = silc_idlist_find_channel_by_name(server->global_list,
3406 channel_name, NULL);
3408 /* Channel really does not exist, create it */
3409 channel = silc_server_create_new_channel(server, server->id, cipher,
3410 hmac, channel_name, TRUE);
3412 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3413 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3417 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3425 /* Channel not found */
3427 /* If the command came from router and we are normal server then
3428 something went wrong with the joining as the channel was not found.
3429 We can't do anything else but ignore this. */
3430 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3431 server->server_type != SILC_ROUTER)
3434 /* We are router and the channel does not seem exist so we will check
3435 our global list as well for the channel. */
3436 channel = silc_idlist_find_channel_by_name(server->global_list,
3437 channel_name, NULL);
3439 /* Channel really does not exist, create it */
3440 channel = silc_server_create_new_channel(server, server->id, cipher,
3441 hmac, channel_name, TRUE);
3443 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3444 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3448 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3455 /* Check whether the channel was created by our router */
3456 if (cmd->pending && context2) {
3457 SilcServerCommandReplyContext reply =
3458 (SilcServerCommandReplyContext)context2;
3460 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3461 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3462 SILC_GET32_MSB(created, tmp);
3463 if (silc_argument_get_arg_type(reply->args, 7, NULL))
3464 create_key = FALSE; /* Router returned the key already */
3467 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
3468 !silc_hash_table_count(channel->user_list))
3472 /* If the channel does not have global users and is also empty the client
3473 will be the channel founder and operator. */
3474 if (!channel->global_users && !silc_hash_table_count(channel->user_list))
3475 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3477 /* Join to the channel */
3478 silc_server_command_join_channel(server, cmd, channel, client_id,
3479 created, create_key, umode,
3482 silc_free(client_id);
3485 silc_server_command_free(cmd);
3488 /* Server side of command MOTD. Sends server's current "message of the
3489 day" to the client. */
3491 SILC_SERVER_CMD_FUNC(motd)
3493 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3494 SilcServer server = cmd->server;
3495 SilcBuffer packet, idp;
3496 char *motd, *dest_server;
3498 uint16 ident = silc_command_get_ident(cmd->payload);
3500 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3502 /* Get server name */
3503 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3505 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3506 SILC_STATUS_ERR_NO_SUCH_SERVER);
3510 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3513 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3515 if (server->config && server->config->motd &&
3516 server->config->motd->motd_file) {
3518 motd = silc_file_readfile(server->config->motd->motd_file, &motd_len);
3523 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3524 SILC_STATUS_OK, ident, 2,
3529 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3530 SILC_STATUS_OK, ident, 1,
3534 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3535 packet->data, packet->len, FALSE);
3536 silc_buffer_free(packet);
3537 silc_buffer_free(idp);
3539 SilcServerEntry entry;
3541 /* Check whether we have this server cached */
3542 entry = silc_idlist_find_server_by_name(server->global_list,
3543 dest_server, TRUE, NULL);
3545 entry = silc_idlist_find_server_by_name(server->local_list,
3546 dest_server, TRUE, NULL);
3549 if (server->server_type != SILC_SERVER && !cmd->pending &&
3550 entry && !entry->motd) {
3551 /* Send to the server */
3555 old_ident = silc_command_get_ident(cmd->payload);
3556 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3557 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3559 silc_server_packet_send(server, entry->connection,
3560 SILC_PACKET_COMMAND, cmd->packet->flags,
3561 tmpbuf->data, tmpbuf->len, TRUE);
3563 /* Reprocess this packet after received reply from router */
3564 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3565 silc_command_get_ident(cmd->payload),
3566 silc_server_command_motd,
3567 silc_server_command_dup(cmd));
3568 cmd->pending = TRUE;
3569 silc_command_set_ident(cmd->payload, old_ident);
3570 silc_buffer_free(tmpbuf);
3574 if (!entry && !cmd->pending && !server->standalone) {
3575 /* Send to the primary router */
3579 old_ident = silc_command_get_ident(cmd->payload);
3580 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3581 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3583 silc_server_packet_send(server, server->router->connection,
3584 SILC_PACKET_COMMAND, cmd->packet->flags,
3585 tmpbuf->data, tmpbuf->len, TRUE);
3587 /* Reprocess this packet after received reply from router */
3588 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3589 silc_command_get_ident(cmd->payload),
3590 silc_server_command_motd,
3591 silc_server_command_dup(cmd));
3592 cmd->pending = TRUE;
3593 silc_command_set_ident(cmd->payload, old_ident);
3594 silc_buffer_free(tmpbuf);
3599 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3600 SILC_STATUS_ERR_NO_SUCH_SERVER);
3604 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3605 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3606 SILC_STATUS_OK, ident, 2,
3610 strlen(entry->motd) : 0);
3611 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3612 packet->data, packet->len, FALSE);
3613 silc_buffer_free(packet);
3614 silc_buffer_free(idp);
3618 silc_server_command_free(cmd);
3621 /* Server side of command UMODE. Client can use this command to set/unset
3622 user mode. Client actually cannot set itself to be as server/router
3623 operator so this can be used only to unset the modes. */
3625 SILC_SERVER_CMD_FUNC(umode)
3627 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3628 SilcServer server = cmd->server;
3629 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3631 unsigned char *tmp_mask;
3633 uint16 ident = silc_command_get_ident(cmd->payload);
3635 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3638 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 2, 2);
3640 /* Get the client's mode mask */
3641 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3643 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3644 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3647 SILC_GET32_MSB(mask, tmp_mask);
3653 if (mask & SILC_UMODE_SERVER_OPERATOR) {
3654 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR)) {
3655 /* Cannot operator mode */
3656 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3657 SILC_STATUS_ERR_PERM_DENIED);
3661 /* Remove the server operator rights */
3662 if (client->mode & SILC_UMODE_SERVER_OPERATOR) {
3663 client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3664 if (client->connection)
3665 server->stat.my_server_ops--;
3666 if (server->server_type == SILC_ROUTER)
3667 server->stat.server_ops--;
3671 if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3672 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
3673 /* Cannot operator mode */
3674 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3675 SILC_STATUS_ERR_PERM_DENIED);
3679 /* Remove the router operator rights */
3680 if (client->mode & SILC_UMODE_ROUTER_OPERATOR) {
3681 client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3682 if (client->connection)
3683 server->stat.my_router_ops--;
3684 if (server->server_type == SILC_ROUTER)
3685 server->stat.router_ops--;
3689 if (mask & SILC_UMODE_GONE) {
3690 client->mode |= SILC_UMODE_GONE;
3692 if (client->mode & SILC_UMODE_GONE)
3693 /* Remove the gone status */
3694 client->mode &= ~SILC_UMODE_GONE;
3697 /* Send UMODE change to primary router */
3698 if (!server->standalone)
3699 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3700 client->id, client->mode);
3702 /* Send command reply to sender */
3703 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3704 SILC_STATUS_OK, ident, 1,
3706 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3707 packet->data, packet->len, FALSE);
3708 silc_buffer_free(packet);
3711 silc_server_command_free(cmd);
3714 /* Checks that client has rights to add or remove channel modes. If any
3715 of the checks fails FALSE is returned. */
3717 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3718 SilcChannelClientEntry client,
3721 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3722 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3724 /* Check whether has rights to change anything */
3725 if (!is_op && !is_fo)
3728 /* Check whether has rights to change everything */
3732 /* We know that client is channel operator, check that they are not
3733 changing anything that requires channel founder rights. Rest of the
3734 modes are available automatically for channel operator. */
3736 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3737 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3738 if (is_op && !is_fo)
3741 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3742 if (is_op && !is_fo)
3747 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3748 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE))
3749 if (is_op && !is_fo)
3752 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3753 if (is_op && !is_fo)
3758 if (mode & SILC_CHANNEL_MODE_CIPHER) {
3759 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER))
3760 if (is_op && !is_fo)
3763 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3764 if (is_op && !is_fo)
3769 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3770 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH))
3771 if (is_op && !is_fo)
3774 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3775 if (is_op && !is_fo)
3783 /* Server side command of CMODE. Changes channel mode */
3785 SILC_SERVER_CMD_FUNC(cmode)
3787 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3788 SilcServer server = cmd->server;
3789 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3790 SilcIDListData idata = (SilcIDListData)client;
3791 SilcChannelID *channel_id;
3792 SilcChannelEntry channel;
3793 SilcChannelClientEntry chl;
3794 SilcBuffer packet, cidp;
3795 unsigned char *tmp, *tmp_id, *tmp_mask;
3796 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3797 uint32 mode_mask, tmp_len, tmp_len2;
3798 uint16 ident = silc_command_get_ident(cmd->payload);
3800 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 2, 7);
3802 /* Get Channel ID */
3803 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3805 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3806 SILC_STATUS_ERR_NO_CHANNEL_ID);
3809 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3811 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3812 SILC_STATUS_ERR_NO_CHANNEL_ID);
3816 /* Get the channel mode mask */
3817 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3819 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3820 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3823 SILC_GET32_MSB(mode_mask, tmp_mask);
3825 /* Get channel entry */
3826 channel = silc_idlist_find_channel_by_id(server->local_list,
3829 channel = silc_idlist_find_channel_by_id(server->global_list,
3832 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3833 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3838 /* Check whether this client is on the channel */
3839 if (!silc_server_client_on_channel(client, channel)) {
3840 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3841 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3845 /* Get entry to the channel user list */
3846 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
3848 /* Check that client has rights to change any requested channel modes */
3849 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3850 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3851 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3856 * Check the modes. Modes that requires nothing special operation are
3860 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3861 /* Channel uses private keys to protect traffic. Client(s) has set the
3862 key locally they want to use, server does not know that key. */
3863 /* Nothing interesting to do here */
3865 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3866 /* The mode is removed and we need to generate and distribute
3867 new channel key. Clients are not using private channel keys
3868 anymore after this. */
3870 /* Re-generate channel key */
3871 if (!silc_server_create_channel_key(server, channel, 0))
3874 /* Send the channel key. This sends it to our local clients and if
3875 we are normal server to our router as well. */
3876 silc_server_send_channel_key(server, NULL, channel,
3877 server->server_type == SILC_ROUTER ?
3878 FALSE : !server->standalone);
3880 cipher = channel->channel_key->cipher->name;
3881 hmac = (char *)silc_hmac_get_name(channel->hmac);
3885 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3886 /* User limit is set on channel */
3889 /* Get user limit */
3890 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3892 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3893 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3894 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3898 SILC_GET32_MSB(user_limit, tmp);
3899 channel->user_limit = user_limit;
3902 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3903 /* User limit mode is unset. Remove user limit */
3904 channel->user_limit = 0;
3907 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3908 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3909 /* Passphrase has been set to channel */
3911 /* Get the passphrase */
3912 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3914 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3915 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3919 /* Save the passphrase */
3920 passphrase = channel->passphrase = strdup(tmp);
3923 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3924 /* Passphrase mode is unset. remove the passphrase */
3925 if (channel->passphrase) {
3926 silc_free(channel->passphrase);
3927 channel->passphrase = NULL;
3932 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3933 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3934 /* Cipher to use protect the traffic */
3935 SilcCipher newkey, oldkey;
3938 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3940 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3941 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3945 /* Delete old cipher and allocate the new one */
3946 if (!silc_cipher_alloc(cipher, &newkey)) {
3947 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3948 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3952 oldkey = channel->channel_key;
3953 channel->channel_key = newkey;
3955 /* Re-generate channel key */
3956 if (!silc_server_create_channel_key(server, channel, 0)) {
3957 /* We don't have new key, revert to old one */
3958 channel->channel_key = oldkey;
3962 /* Remove old channel key for good */
3963 silc_cipher_free(oldkey);
3965 /* Send the channel key. This sends it to our local clients and if
3966 we are normal server to our router as well. */
3967 silc_server_send_channel_key(server, NULL, channel,
3968 server->server_type == SILC_ROUTER ?
3969 FALSE : !server->standalone);
3972 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3973 /* Cipher mode is unset. Remove the cipher and revert back to
3975 SilcCipher newkey, oldkey;
3976 cipher = channel->cipher;
3978 /* Delete old cipher and allocate default one */
3979 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_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);
4006 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
4007 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
4008 /* HMAC to use protect the traffic */
4009 unsigned char hash[32];
4013 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4015 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4016 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4020 /* Delete old hmac and allocate the new one */
4021 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4022 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4023 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4027 silc_hmac_free(channel->hmac);
4028 channel->hmac = newhmac;
4030 /* Set the HMAC key out of current channel key. The client must do
4032 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4033 channel->key_len / 8, hash);
4034 silc_hmac_set_key(channel->hmac, hash,
4035 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4036 memset(hash, 0, sizeof(hash));
4039 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4040 /* Hmac mode is unset. Remove the hmac and revert back to
4043 unsigned char hash[32];
4044 hmac = channel->hmac_name;
4046 /* Delete old hmac and allocate default one */
4047 silc_hmac_free(channel->hmac);
4048 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4049 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4050 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4054 silc_hmac_free(channel->hmac);
4055 channel->hmac = newhmac;
4057 /* Set the HMAC key out of current channel key. The client must do
4059 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4060 channel->key_len / 8,
4062 silc_hmac_set_key(channel->hmac, hash,
4063 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4064 memset(hash, 0, sizeof(hash));
4068 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4069 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4070 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4071 /* Set the founder authentication */
4072 SilcAuthPayload auth;
4074 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4076 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4077 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4081 auth = silc_auth_payload_parse(tmp, tmp_len);
4083 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4084 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4088 /* Save the public key */
4089 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
4090 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
4093 channel->founder_method = silc_auth_get_method(auth);
4095 if (channel->founder_method == SILC_AUTH_PASSWORD) {
4096 tmp = silc_auth_get_data(auth, &tmp_len);
4097 channel->founder_passwd =
4098 silc_calloc(tmp_len + 1, sizeof(*channel->founder_passwd));
4099 memcpy(channel->founder_passwd, tmp, tmp_len);
4100 channel->founder_passwd_len = tmp_len;
4102 /* Verify the payload before setting the mode */
4103 if (!silc_auth_verify(auth, channel->founder_method,
4104 channel->founder_key, 0, idata->hash,
4105 client->id, SILC_ID_CLIENT)) {
4106 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4107 SILC_STATUS_ERR_AUTH_FAILED);
4112 silc_auth_payload_free(auth);
4116 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4117 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4118 if (channel->founder_key)
4119 silc_pkcs_public_key_free(channel->founder_key);
4120 if (channel->founder_passwd) {
4121 silc_free(channel->founder_passwd);
4122 channel->founder_passwd = NULL;
4128 /* Finally, set the mode */
4129 channel->mode = mode_mask;
4131 /* Send CMODE_CHANGE notify. */
4132 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4133 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4134 SILC_NOTIFY_TYPE_CMODE_CHANGE, 5,
4135 cidp->data, cidp->len,
4137 cipher, cipher ? strlen(cipher) : 0,
4138 hmac, hmac ? strlen(hmac) : 0,
4139 passphrase, passphrase ?
4140 strlen(passphrase) : 0);
4142 /* Set CMODE notify type to network */
4143 if (!server->standalone)
4144 silc_server_send_notify_cmode(server, server->router->connection,
4145 server->server_type == SILC_ROUTER ?
4146 TRUE : FALSE, channel,
4147 mode_mask, client->id, SILC_ID_CLIENT,
4148 cipher, hmac, passphrase);
4150 /* Send command reply to sender */
4151 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4152 SILC_STATUS_OK, ident, 2,
4153 2, tmp_id, tmp_len2,
4155 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4156 packet->data, packet->len, FALSE);
4158 silc_buffer_free(packet);
4159 silc_free(channel_id);
4160 silc_buffer_free(cidp);
4163 silc_server_command_free(cmd);
4166 /* Server side of CUMODE command. Changes client's mode on a channel. */
4168 SILC_SERVER_CMD_FUNC(cumode)
4170 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4171 SilcServer server = cmd->server;
4172 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4173 SilcIDListData idata = (SilcIDListData)client;
4174 SilcChannelID *channel_id;
4175 SilcClientID *client_id;
4176 SilcChannelEntry channel;
4177 SilcClientEntry target_client;
4178 SilcChannelClientEntry chl;
4179 SilcBuffer packet, idp;
4180 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4181 uint32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4183 uint16 ident = silc_command_get_ident(cmd->payload);
4185 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4187 /* Get Channel ID */
4188 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4190 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4191 SILC_STATUS_ERR_NO_CHANNEL_ID);
4194 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
4196 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4197 SILC_STATUS_ERR_NO_CHANNEL_ID);
4201 /* Get channel entry */
4202 channel = silc_idlist_find_channel_by_id(server->local_list,
4205 channel = silc_idlist_find_channel_by_id(server->global_list,
4208 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4209 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4214 /* Check whether sender is on the channel */
4215 if (!silc_server_client_on_channel(client, channel)) {
4216 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4217 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4221 /* Check that client has rights to change other's rights */
4222 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4223 sender_mask = chl->mode;
4225 /* Get the target client's channel mode mask */
4226 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4228 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4229 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4232 SILC_GET32_MSB(target_mask, tmp_mask);
4234 /* Get target Client ID */
4235 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4237 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4238 SILC_STATUS_ERR_NO_CLIENT_ID);
4241 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
4243 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4244 SILC_STATUS_ERR_NO_CLIENT_ID);
4248 /* Get target client's entry */
4249 target_client = silc_idlist_find_client_by_id(server->local_list,
4250 client_id, TRUE, NULL);
4251 if (!target_client) {
4252 target_client = silc_idlist_find_client_by_id(server->global_list,
4253 client_id, TRUE, NULL);
4256 if (target_client != client &&
4257 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4258 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4259 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4260 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4264 /* Check whether target client is on the channel */
4265 if (target_client != client) {
4266 if (!silc_server_client_on_channel(target_client, channel)) {
4267 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4268 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4272 /* Get entry to the channel user list */
4273 silc_hash_table_find(channel->user_list, target_client, NULL,
4281 /* If the target client is founder, no one else can change their mode
4283 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4284 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4285 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4289 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4290 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4291 /* The client tries to claim the founder rights. */
4292 unsigned char *tmp_auth;
4293 uint32 tmp_auth_len, auth_len;
4296 if (target_client != client) {
4297 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4298 SILC_STATUS_ERR_NOT_YOU);
4302 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4303 !channel->founder_key || !idata->public_key ||
4304 !silc_pkcs_public_key_compare(channel->founder_key,
4305 idata->public_key)) {
4306 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4307 SILC_STATUS_ERR_NOT_YOU);
4311 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4313 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4314 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4318 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4319 (void *)channel->founder_passwd : (void *)channel->founder_key);
4320 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4321 channel->founder_passwd_len : 0);
4323 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4324 channel->founder_method, auth, auth_len,
4325 idata->hash, client->id, SILC_ID_CLIENT)) {
4326 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4327 SILC_STATUS_ERR_AUTH_FAILED);
4331 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4335 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4336 if (target_client == client) {
4337 /* Remove channel founder rights from itself */
4338 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4341 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4342 SILC_STATUS_ERR_NOT_YOU);
4348 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4349 /* Promote to operator */
4350 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4351 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4352 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4353 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4354 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4358 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4362 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4363 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4364 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4365 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4366 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4370 /* Demote to normal user */
4371 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4376 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4377 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4379 /* Send notify to channel, notify only if mode was actually changed. */
4381 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4382 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4383 idp->data, idp->len,
4387 /* Set CUMODE notify type to network */
4388 if (!server->standalone)
4389 silc_server_send_notify_cumode(server, server->router->connection,
4390 server->server_type == SILC_ROUTER ?
4391 TRUE : FALSE, channel,
4392 target_mask, client->id,
4397 /* Send command reply to sender */
4398 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4399 SILC_STATUS_OK, ident, 3,
4401 3, tmp_ch_id, tmp_ch_len,
4402 4, tmp_id, tmp_len);
4403 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4404 packet->data, packet->len, FALSE);
4406 silc_buffer_free(packet);
4407 silc_free(channel_id);
4408 silc_free(client_id);
4409 silc_buffer_free(idp);
4412 silc_server_command_free(cmd);
4415 /* Server side of KICK command. Kicks client out of channel. */
4417 SILC_SERVER_CMD_FUNC(kick)
4419 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4420 SilcServer server = cmd->server;
4421 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4422 SilcClientEntry target_client;
4423 SilcChannelID *channel_id;
4424 SilcClientID *client_id;
4425 SilcChannelEntry channel;
4426 SilcChannelClientEntry chl;
4428 uint32 tmp_len, target_idp_len;
4429 unsigned char *tmp, *comment, *target_idp;
4431 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4433 /* Get Channel ID */
4434 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4436 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4437 SILC_STATUS_ERR_NO_CHANNEL_ID);
4440 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
4442 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4443 SILC_STATUS_ERR_NO_CHANNEL_ID);
4447 /* Get channel entry */
4448 channel = silc_idlist_find_channel_by_id(server->local_list,
4451 channel = silc_idlist_find_channel_by_id(server->local_list,
4454 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4455 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4460 /* Check whether sender is on the channel */
4461 if (!silc_server_client_on_channel(client, channel)) {
4462 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4463 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4467 /* Check that the kicker is channel operator or channel founder */
4468 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4469 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4470 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4471 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4475 /* Get target Client ID */
4476 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4478 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4479 SILC_STATUS_ERR_NO_CLIENT_ID);
4482 client_id = silc_id_payload_parse_id(target_idp, target_idp_len);
4484 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4485 SILC_STATUS_ERR_NO_CLIENT_ID);
4489 /* Get target client's entry */
4490 target_client = silc_idlist_find_client_by_id(server->local_list,
4491 client_id, TRUE, NULL);
4492 if (!target_client) {
4493 target_client = silc_idlist_find_client_by_id(server->global_list,
4494 client_id, TRUE, NULL);
4497 /* Check that the target client is not channel founder. Channel founder
4498 cannot be kicked from the channel. */
4499 silc_hash_table_find(channel->user_list, target_client, NULL, (void *)&chl);
4500 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4501 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4502 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4506 /* Check whether target client is on the channel */
4507 if (!silc_server_client_on_channel(target_client, channel)) {
4508 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4509 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4515 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4519 /* Send command reply to sender */
4520 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4523 /* Send KICKED notify to local clients on the channel */
4524 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4525 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4526 SILC_NOTIFY_TYPE_KICKED, 3,
4527 target_idp, target_idp_len,
4528 comment, comment ? strlen(comment) : 0,
4529 idp->data, idp->len);
4530 silc_buffer_free(idp);
4532 /* Remove the client from the channel. If the channel does not exist
4533 after removing the client then the client kicked itself off the channel
4534 and we don't have to send anything after that. */
4535 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4536 target_client, FALSE))
4539 /* Send KICKED notify to primary route */
4540 if (!server->standalone)
4541 silc_server_send_notify_kicked(server, server->router->connection,
4542 server->server_type == SILC_ROUTER ?
4543 TRUE : FALSE, channel,
4544 target_client->id, client->id, comment);
4546 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4547 /* Re-generate channel key */
4548 if (!silc_server_create_channel_key(server, channel, 0))
4551 /* Send the channel key to the channel. The key of course is not sent
4552 to the client who was kicked off the channel. */
4553 silc_server_send_channel_key(server, target_client->connection, channel,
4554 server->server_type == SILC_ROUTER ?
4555 FALSE : !server->standalone);
4559 silc_server_command_free(cmd);
4562 /* Server side of OPER command. Client uses this comand to obtain server
4563 operator privileges to this server/router. */
4565 SILC_SERVER_CMD_FUNC(oper)
4567 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4568 SilcServer server = cmd->server;
4569 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4570 unsigned char *username, *auth;
4572 SilcServerConfigSectionAdminConnection *admin;
4573 SilcIDListData idata = (SilcIDListData)client;
4575 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4577 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4580 /* Get the username */
4581 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4583 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4584 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4588 /* Get the admin configuration */
4589 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4590 username, client->nickname);
4592 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4593 username, client->nickname);
4595 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4596 SILC_STATUS_ERR_AUTH_FAILED);
4601 /* Get the authentication payload */
4602 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4604 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4605 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4609 /* Verify the authentication data */
4610 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4611 admin->auth_data, admin->auth_data_len,
4612 idata->hash, client->id, SILC_ID_CLIENT)) {
4613 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4614 SILC_STATUS_ERR_AUTH_FAILED);
4618 /* Client is now server operator */
4619 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4621 /* Update statistics */
4622 if (client->connection)
4623 server->stat.my_server_ops++;
4624 if (server->server_type == SILC_ROUTER)
4625 server->stat.server_ops++;
4627 /* Send UMODE change to primary router */
4628 if (!server->standalone)
4629 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4630 client->id, client->mode);
4632 /* Send reply to the sender */
4633 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4637 silc_server_command_free(cmd);
4640 /* Server side of SILCOPER command. Client uses this comand to obtain router
4641 operator privileges to this router. */
4643 SILC_SERVER_CMD_FUNC(silcoper)
4645 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4646 SilcServer server = cmd->server;
4647 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4648 unsigned char *username, *auth;
4650 SilcServerConfigSectionAdminConnection *admin;
4651 SilcIDListData idata = (SilcIDListData)client;
4653 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4655 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4658 if (server->server_type != SILC_ROUTER) {
4659 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4660 SILC_STATUS_ERR_AUTH_FAILED);
4664 /* Get the username */
4665 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4667 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4668 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4672 /* Get the admin configuration */
4673 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4674 username, client->nickname);
4676 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4677 username, client->nickname);
4679 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4680 SILC_STATUS_ERR_AUTH_FAILED);
4685 /* Get the authentication payload */
4686 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4688 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4689 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4693 /* Verify the authentication data */
4694 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4695 admin->auth_data, admin->auth_data_len,
4696 idata->hash, client->id, SILC_ID_CLIENT)) {
4697 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4698 SILC_STATUS_ERR_AUTH_FAILED);
4702 /* Client is now router operator */
4703 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4705 /* Update statistics */
4706 if (client->connection)
4707 server->stat.my_router_ops++;
4708 if (server->server_type == SILC_ROUTER)
4709 server->stat.router_ops++;
4711 /* Send UMODE change to primary router */
4712 if (!server->standalone)
4713 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4714 client->id, client->mode);
4716 /* Send reply to the sender */
4717 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4721 silc_server_command_free(cmd);
4724 /* Server side command of CONNECT. Connects us to the specified remote
4725 server or router. */
4727 SILC_SERVER_CMD_FUNC(connect)
4729 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4730 SilcServer server = cmd->server;
4731 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4732 unsigned char *tmp, *host;
4734 uint32 port = SILC_PORT;
4736 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CONNECT, cmd, 1, 2);
4738 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4741 /* Check whether client has the permissions. */
4742 if (client->mode == SILC_UMODE_NONE) {
4743 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4744 SILC_STATUS_ERR_NO_SERVER_PRIV);
4748 if (server->server_type == SILC_ROUTER &&
4749 client->mode & SILC_UMODE_SERVER_OPERATOR) {
4750 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4751 SILC_STATUS_ERR_NO_ROUTER_PRIV);
4755 /* Get the remote server */
4756 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4758 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4759 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4764 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4766 SILC_GET32_MSB(port, tmp);
4768 /* Create the connection. It is done with timeout and is async. */
4769 silc_server_create_connection(server, host, port);
4771 /* Send reply to the sender */
4772 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4776 silc_server_command_free(cmd);
4779 /* Server side of command BAN. This is used to manage the ban list of the
4780 channel. To add clients and remove clients from the ban list. */
4782 SILC_SERVER_CMD_FUNC(ban)
4784 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4785 SilcServer server = cmd->server;
4786 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4788 SilcChannelEntry channel;
4789 SilcChannelClientEntry chl;
4790 SilcChannelID *channel_id = NULL;
4791 unsigned char *id, *add, *del;
4792 uint32 id_len, tmp_len;
4793 uint16 ident = silc_command_get_ident(cmd->payload);
4795 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4798 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4800 /* Get Channel ID */
4801 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4803 channel_id = silc_id_payload_parse_id(id, id_len);
4805 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4806 SILC_STATUS_ERR_NO_CHANNEL_ID);
4811 /* Get channel entry. The server must know about the channel since the
4812 client is expected to be on the channel. */
4813 channel = silc_idlist_find_channel_by_id(server->local_list,
4816 channel = silc_idlist_find_channel_by_id(server->global_list,
4819 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4820 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4825 /* Check whether this client is on the channel */
4826 if (!silc_server_client_on_channel(client, channel)) {
4827 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4828 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4832 /* Get entry to the channel user list */
4833 if (!silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl)) {
4834 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4835 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4839 /* The client must be at least channel operator. */
4840 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4841 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4842 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4846 /* Get the new ban and add it to the ban list */
4847 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4849 if (!channel->ban_list)
4850 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4852 channel->ban_list = silc_realloc(channel->ban_list,
4853 sizeof(*channel->ban_list) *
4855 strlen(channel->ban_list) + 2));
4856 if (add[tmp_len - 1] == ',')
4857 add[tmp_len - 1] = '\0';
4859 strncat(channel->ban_list, add, tmp_len);
4860 strncat(channel->ban_list, ",", 1);
4863 /* Get the ban to be removed and remove it from the list */
4864 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4865 if (del && channel->ban_list) {
4866 char *start, *end, *n;
4868 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4869 silc_free(channel->ban_list);
4870 channel->ban_list = NULL;
4872 start = strstr(channel->ban_list, del);
4873 if (start && strlen(start) >= tmp_len) {
4874 end = start + tmp_len;
4875 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4876 strncat(n, channel->ban_list, start - channel->ban_list);
4877 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4879 silc_free(channel->ban_list);
4880 channel->ban_list = n;
4885 /* Send the BAN notify type to our primary router. */
4886 if (!server->standalone && (add || del))
4887 silc_server_send_notify_ban(server, server->router->connection,
4888 server->server_type == SILC_ROUTER ?
4889 TRUE : FALSE, channel, add, del);
4891 /* Send the reply back to the client */
4893 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4894 SILC_STATUS_OK, ident, 2,
4896 3, channel->ban_list,
4898 strlen(channel->ban_list) : 0);
4899 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4900 packet->data, packet->len, FALSE);
4902 silc_buffer_free(packet);
4905 silc_free(channel_id);
4906 silc_server_command_free(cmd);
4909 /* Server side command of CLOSE. Closes connection to a specified server. */
4911 SILC_SERVER_CMD_FUNC(close)
4913 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4914 SilcServer server = cmd->server;
4915 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4916 SilcServerEntry server_entry;
4917 SilcSocketConnection sock;
4920 unsigned char *name;
4921 uint32 port = SILC_PORT;
4923 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CLOSE, cmd, 1, 2);
4925 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4928 /* Check whether client has the permissions. */
4929 if (client->mode == SILC_UMODE_NONE) {
4930 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4931 SILC_STATUS_ERR_NO_SERVER_PRIV);
4935 /* Get the remote server */
4936 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4938 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4939 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4944 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4946 SILC_GET32_MSB(port, tmp);
4948 server_entry = silc_idlist_find_server_by_conn(server->local_list,
4949 name, port, FALSE, NULL);
4951 server_entry = silc_idlist_find_server_by_conn(server->global_list,
4952 name, port, FALSE, NULL);
4953 if (!server_entry) {
4954 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4955 SILC_STATUS_ERR_NO_SERVER_ID);
4959 /* Send reply to the sender */
4960 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4963 /* Close the connection to the server */
4964 sock = (SilcSocketConnection)server_entry->connection;
4966 /* If we shutdown primary router connection manually then don't trigger
4967 any reconnect or backup router connections, by setting the router
4969 if (server->router == server_entry) {
4970 server->id_entry->router = NULL;
4971 server->router = NULL;
4972 server->standalone = TRUE;
4974 silc_server_free_sock_user_data(server, sock, NULL);
4975 silc_server_close_connection(server, sock);
4978 silc_server_command_free(cmd);
4981 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4982 active connections. */
4984 SILC_SERVER_CMD_FUNC(shutdown)
4986 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4987 SilcServer server = cmd->server;
4988 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4990 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4992 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4995 /* Check whether client has the permission. */
4996 if (client->mode == SILC_UMODE_NONE) {
4997 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4998 SILC_STATUS_ERR_NO_SERVER_PRIV);
5002 /* Send reply to the sender */
5003 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
5006 /* Then, gracefully, or not, bring the server down. */
5007 silc_server_stop(server);
5011 silc_server_command_free(cmd);
5014 /* Server side command of LEAVE. Removes client from a channel. */
5016 SILC_SERVER_CMD_FUNC(leave)
5018 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5019 SilcServer server = cmd->server;
5020 SilcSocketConnection sock = cmd->sock;
5021 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
5022 SilcChannelID *id = NULL;
5023 SilcChannelEntry channel;
5027 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
5029 /* Get Channel ID */
5030 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
5032 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5033 SILC_STATUS_ERR_NO_CHANNEL_ID);
5036 id = silc_id_payload_parse_id(tmp, len);
5038 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5039 SILC_STATUS_ERR_NO_CHANNEL_ID);
5043 /* Get channel entry */
5044 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5046 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5048 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5049 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5054 /* Check whether this client is on the channel */
5055 if (!silc_server_client_on_channel(id_entry, channel)) {
5056 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5057 SILC_STATUS_ERR_NOT_ON_CHANNEL);
5061 /* Notify routers that they should remove this client from their list
5062 of clients on the channel. Send LEAVE notify type. */
5063 if (!server->standalone)
5064 silc_server_send_notify_leave(server, server->router->connection,
5065 server->server_type == SILC_ROUTER ?
5066 TRUE : FALSE, channel, id_entry->id);
5068 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5071 /* Remove client from channel */
5072 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5074 /* If the channel does not exist anymore we won't send anything */
5077 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5078 /* Re-generate channel key */
5079 if (!silc_server_create_channel_key(server, channel, 0))
5082 /* Send the channel key */
5083 silc_server_send_channel_key(server, NULL, channel,
5084 server->server_type == SILC_ROUTER ?
5085 FALSE : !server->standalone);
5090 silc_server_command_free(cmd);
5093 /* Server side of command USERS. Resolves clients and their USERS currently
5094 joined on the requested channel. The list of Client ID's and their modes
5095 on the channel is sent back. */
5097 SILC_SERVER_CMD_FUNC(users)
5099 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5100 SilcServer server = cmd->server;
5101 SilcChannelEntry channel;
5102 SilcChannelID *id = NULL;
5103 SilcBuffer packet, idp;
5104 unsigned char *channel_id;
5105 uint32 channel_id_len;
5106 SilcBuffer client_id_list;
5107 SilcBuffer client_mode_list;
5108 unsigned char lc[4];
5109 uint32 list_count = 0;
5110 uint16 ident = silc_command_get_ident(cmd->payload);
5113 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5115 /* Get Channel ID */
5116 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5118 /* Get channel name */
5119 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5121 if (!channel_id && !channel_name) {
5122 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5123 SILC_STATUS_ERR_NO_CHANNEL_ID);
5128 id = silc_id_payload_parse_id(channel_id, channel_id_len);
5130 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5131 SILC_STATUS_ERR_NO_CHANNEL_ID);
5136 /* If we are server and we don't know about this channel we will send
5137 the command to our router. If we know about the channel then we also
5138 have the list of users already. */
5140 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5142 channel = silc_idlist_find_channel_by_name(server->local_list,
5143 channel_name, NULL);
5145 if (!channel || channel->disabled) {
5146 if (server->server_type != SILC_ROUTER && !server->standalone &&
5150 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5151 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5153 /* Send USERS command */
5154 silc_server_packet_send(server, server->router->connection,
5155 SILC_PACKET_COMMAND, cmd->packet->flags,
5156 tmpbuf->data, tmpbuf->len, TRUE);
5158 /* Reprocess this packet after received reply */
5159 silc_server_command_pending(server, SILC_COMMAND_USERS,
5160 silc_command_get_ident(cmd->payload),
5161 silc_server_command_users,
5162 silc_server_command_dup(cmd));
5163 cmd->pending = TRUE;
5164 silc_command_set_ident(cmd->payload, ident);
5165 silc_buffer_free(tmpbuf);
5170 /* Check the global list as well. */
5172 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5174 channel = silc_idlist_find_channel_by_name(server->global_list,
5175 channel_name, NULL);
5177 /* Channel really does not exist */
5178 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5179 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5184 /* If the channel is private or secret do not send anything, unless the
5185 user requesting this command is on the channel. */
5186 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5187 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5188 && !silc_server_client_on_channel(cmd->sock->user_data, channel)) {
5189 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5190 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5195 (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
5196 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5197 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5202 /* Get the users list */
5203 silc_server_get_users_on_channel(server, channel, &client_id_list,
5204 &client_mode_list, &list_count);
5207 SILC_PUT32_MSB(list_count, lc);
5210 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5211 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5212 SILC_STATUS_OK, ident, 4,
5213 2, idp->data, idp->len,
5215 4, client_id_list->data,
5216 client_id_list->len,
5217 5, client_mode_list->data,
5218 client_mode_list->len);
5219 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5220 packet->data, packet->len, FALSE);
5222 silc_buffer_free(idp);
5223 silc_buffer_free(packet);
5224 silc_buffer_free(client_id_list);
5225 silc_buffer_free(client_mode_list);
5229 silc_server_command_free(cmd);
5232 /* Server side of command GETKEY. This fetches the client's public key
5233 from the server where to the client is connected. */
5235 SILC_SERVER_CMD_FUNC(getkey)
5237 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5238 SilcServer server = cmd->server;
5240 SilcClientEntry client;
5241 SilcServerEntry server_entry;
5242 SilcClientID *client_id = NULL;
5243 SilcServerID *server_id = NULL;
5244 SilcIDPayload idp = NULL;
5245 uint16 ident = silc_command_get_ident(cmd->payload);
5246 unsigned char *tmp, *pkdata;
5247 uint32 tmp_len, pklen;
5248 SilcBuffer pk = NULL;
5250 SilcPublicKey public_key;
5252 SILC_LOG_DEBUG(("Start"));
5254 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5256 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5257 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5260 idp = silc_id_payload_parse(tmp, tmp_len);
5262 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5263 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5267 id_type = silc_id_payload_get_type(idp);
5268 if (id_type == SILC_ID_CLIENT) {
5269 client_id = silc_id_payload_get_id(idp);
5271 /* If the client is not found from local list there is no chance it
5272 would be locally connected client so send the command further. */
5273 client = silc_idlist_find_client_by_id(server->local_list,
5274 client_id, TRUE, NULL);
5276 client = silc_idlist_find_client_by_id(server->global_list,
5277 client_id, TRUE, NULL);
5279 if ((!client && !cmd->pending && !server->standalone) ||
5280 (client && !client->connection && !cmd->pending) ||
5281 (client && !client->data.public_key && !cmd->pending)) {
5284 SilcSocketConnection dest_sock;
5286 dest_sock = silc_server_get_client_route(server, NULL, 0,
5291 old_ident = silc_command_get_ident(cmd->payload);
5292 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5293 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5295 silc_server_packet_send(server, dest_sock,
5296 SILC_PACKET_COMMAND, cmd->packet->flags,
5297 tmpbuf->data, tmpbuf->len, TRUE);
5299 /* Reprocess this packet after received reply from router */
5300 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5301 silc_command_get_ident(cmd->payload),
5302 silc_server_command_getkey,
5303 silc_server_command_dup(cmd));
5304 cmd->pending = TRUE;
5305 silc_command_set_ident(cmd->payload, old_ident);
5306 silc_buffer_free(tmpbuf);
5311 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5312 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5316 /* The client is locally connected, just get the public key and
5317 send it back. If they key does not exist then do not send it,
5318 send just OK reply */
5319 public_key = client->data.public_key;
5324 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5325 pk = silc_buffer_alloc(4 + tmp_len);
5326 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5327 silc_buffer_format(pk,
5328 SILC_STR_UI_SHORT(tmp_len),
5329 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5330 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5336 } else if (id_type == SILC_ID_SERVER) {
5337 server_id = silc_id_payload_get_id(idp);
5339 /* If the server is not found from local list there is no chance it
5340 would be locally connected server so send the command further. */
5341 server_entry = silc_idlist_find_server_by_id(server->local_list,
5342 server_id, TRUE, NULL);
5344 server_entry = silc_idlist_find_server_by_id(server->global_list,
5345 server_id, TRUE, NULL);
5347 if (server_entry != server->id_entry &&
5348 ((!server_entry && !cmd->pending && !server->standalone) ||
5349 (server_entry && !server_entry->connection && !cmd->pending &&
5350 !server->standalone) ||
5351 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5352 !server->standalone))) {
5356 old_ident = silc_command_get_ident(cmd->payload);
5357 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5358 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5360 silc_server_packet_send(server, server->router->connection,
5361 SILC_PACKET_COMMAND, cmd->packet->flags,
5362 tmpbuf->data, tmpbuf->len, TRUE);
5364 /* Reprocess this packet after received reply from router */
5365 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5366 silc_command_get_ident(cmd->payload),
5367 silc_server_command_getkey,
5368 silc_server_command_dup(cmd));
5369 cmd->pending = TRUE;
5370 silc_command_set_ident(cmd->payload, old_ident);
5371 silc_buffer_free(tmpbuf);
5375 if (!server_entry) {
5376 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5377 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5381 /* If they key does not exist then do not send it, send just OK reply */
5382 public_key = (!server_entry->data.public_key ?
5383 (server_entry == server->id_entry ? server->public_key :
5384 NULL) : server_entry->data.public_key);
5389 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5390 pk = silc_buffer_alloc(4 + tmp_len);
5391 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5392 silc_buffer_format(pk,
5393 SILC_STR_UI_SHORT(tmp_len),
5394 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5395 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5405 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5406 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5407 SILC_STATUS_OK, ident,
5411 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5412 packet->data, packet->len, FALSE);
5413 silc_buffer_free(packet);
5416 silc_buffer_free(pk);
5420 silc_id_payload_free(idp);
5421 silc_free(client_id);
5422 silc_free(server_id);
5423 silc_server_command_free(cmd);