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, k, count = 0, len;
1087 SilcBuffer packet, idp;
1088 SilcClientEntry entry = NULL;
1089 SilcCommandStatus status;
1090 uint16 ident = silc_command_get_ident(cmd->payload);
1091 char nh[256], uh[256];
1094 status = SILC_STATUS_OK;
1096 /* Process only entries that are not registered anymore. */
1098 for (i = 0; i < clients_count; i++) {
1099 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1106 /* No valid entries found at all, just send error */
1109 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1111 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1112 SILC_STATUS_ERR_NO_SUCH_NICK,
1113 3, tmp, strlen(tmp));
1117 if (valid_count > 1)
1118 status = SILC_STATUS_LIST_START;
1120 for (i = 0, k = 0; i < clients_count; i++) {
1126 status = SILC_STATUS_LIST_ITEM;
1127 if (valid_count > 1 && k == valid_count - 1)
1128 status = SILC_STATUS_LIST_END;
1129 if (count && k - 1 == count)
1130 status = SILC_STATUS_LIST_END;
1131 if (count && k - 1 > count)
1134 /* Send WHOWAS reply */
1135 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1136 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1137 memset(uh, 0, sizeof(uh));
1138 memset(nh, 0, sizeof(nh));
1140 strncat(nh, entry->nickname, strlen(entry->nickname));
1141 if (!strchr(entry->nickname, '@')) {
1142 strncat(nh, "@", 1);
1143 if (entry->servername) {
1144 strncat(nh, entry->servername, strlen(entry->servername));
1146 len = entry->router ? strlen(entry->router->server_name) :
1147 strlen(server->server_name);
1148 strncat(nh, entry->router ? entry->router->server_name :
1149 server->server_name, len);
1153 strncat(uh, entry->username, strlen(entry->username));
1154 if (!strchr(entry->username, '@')) {
1155 strncat(uh, "@", 1);
1156 strcat(uh, "*private*");
1160 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1162 2, idp->data, idp->len,
1167 strlen(entry->userinfo) : 0);
1168 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1169 0, packet->data, packet->len, FALSE);
1171 silc_buffer_free(packet);
1172 silc_buffer_free(idp);
1179 silc_server_command_whowas_process(SilcServerCommandContext cmd)
1181 SilcServer server = cmd->server;
1182 char *nick = NULL, *server_name = NULL;
1184 SilcClientEntry *clients = NULL;
1185 uint32 clients_count = 0;
1187 bool check_global = FALSE;
1189 /* Protocol dictates that we must always send the received WHOWAS request
1190 to our router if we are normal server, so let's do it now unless we
1191 are standalone. We will not send any replies to the client until we
1192 have received reply from the router. */
1193 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1194 server->server_type == SILC_SERVER && !cmd->pending &&
1195 !server->standalone) {
1199 old_ident = silc_command_get_ident(cmd->payload);
1200 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1201 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1203 /* Send WHOWAS command to our router */
1204 silc_server_packet_send(server, (SilcSocketConnection)
1205 server->router->connection,
1206 SILC_PACKET_COMMAND, cmd->packet->flags,
1207 tmpbuf->data, tmpbuf->len, TRUE);
1209 /* Reprocess this packet after received reply from router */
1210 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1211 silc_command_get_ident(cmd->payload),
1212 silc_server_command_whowas,
1213 silc_server_command_dup(cmd));
1214 cmd->pending = TRUE;
1215 silc_command_set_ident(cmd->payload, old_ident);
1217 silc_buffer_free(tmpbuf);
1222 /* We are ready to process the command request. Let's search for the
1223 requested client and send reply to the requesting client. */
1225 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1226 check_global = TRUE;
1227 else if (server->server_type != SILC_SERVER)
1228 check_global = TRUE;
1230 /* Parse the whowas request */
1231 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1234 /* Get all clients matching that nickname from local list */
1235 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1237 &clients, &clients_count))
1238 silc_idlist_get_clients_by_hash(server->local_list,
1239 nick, server->md5hash,
1240 &clients, &clients_count);
1242 /* Check global list as well */
1244 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1246 &clients, &clients_count))
1247 silc_idlist_get_clients_by_hash(server->global_list,
1248 nick, server->md5hash,
1249 &clients, &clients_count);
1253 /* Such a client really does not exist in the SILC network. */
1254 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1255 SILC_STATUS_ERR_NO_SUCH_NICK,
1256 3, nick, strlen(nick));
1260 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1265 /* Send the command reply to the client */
1266 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1271 silc_free(server_name);
1275 /* Server side of command WHOWAS. */
1277 SILC_SERVER_CMD_FUNC(whowas)
1279 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1282 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1284 ret = silc_server_command_whowas_process(cmd);
1285 silc_server_command_free(cmd);
1288 /******************************************************************************
1292 ******************************************************************************/
1295 silc_server_command_identify_send_router(SilcServerCommandContext cmd)
1297 SilcServer server = cmd->server;
1301 old_ident = silc_command_get_ident(cmd->payload);
1302 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1303 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1305 /* Send IDENTIFY command to our router */
1306 silc_server_packet_send(server, (SilcSocketConnection)
1307 server->router->connection,
1308 SILC_PACKET_COMMAND, cmd->packet->flags,
1309 tmpbuf->data, tmpbuf->len, TRUE);
1311 /* Reprocess this packet after received reply from router */
1312 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1313 silc_command_get_ident(cmd->payload),
1314 silc_server_command_identify,
1315 silc_server_command_dup(cmd));
1316 cmd->pending = TRUE;
1317 silc_command_set_ident(cmd->payload, old_ident);
1318 silc_buffer_free(tmpbuf);
1322 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1323 SilcClientEntry **clients,
1324 uint32 *clients_count,
1325 SilcServerEntry **servers,
1326 uint32 *servers_count,
1327 SilcChannelEntry **channels,
1328 uint32 *channels_count,
1331 SilcServer server = cmd->server;
1334 uint32 argc = silc_argument_get_arg_num(cmd->args);
1336 bool check_global = FALSE;
1341 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1342 check_global = TRUE;
1343 else if (server->server_type != SILC_SERVER)
1344 check_global = TRUE;
1346 /* If ID Payload is in the command it must be used instead of names */
1347 tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1349 /* No ID, get the names. */
1351 /* If we are normal server and have not resolved information from
1352 router yet, do so now. */
1353 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1354 server->server_type == SILC_SERVER && !cmd->pending &&
1355 !server->standalone) {
1356 silc_server_command_identify_send_router(cmd);
1360 /* Try to get nickname@server. */
1361 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1364 char *nick_server = NULL;
1366 silc_parse_userfqdn(tmp, &nick, &nick_server);
1368 if (!silc_idlist_get_clients_by_hash(server->local_list,
1369 nick, server->md5hash,
1370 clients, clients_count))
1371 silc_idlist_get_clients_by_nickname(server->local_list,
1373 clients, clients_count);
1375 if (!silc_idlist_get_clients_by_hash(server->global_list,
1376 nick, server->md5hash,
1377 clients, clients_count))
1378 silc_idlist_get_clients_by_nickname(server->global_list,
1380 clients, clients_count);
1384 silc_free(nick_server);
1387 /* the nickname does not exist, send error reply */
1388 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1389 SILC_STATUS_ERR_NO_SUCH_NICK,
1390 3, tmp, strlen(tmp));
1395 /* Try to get server name */
1396 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1398 entry = silc_idlist_find_server_by_name(server->local_list,
1400 if (!entry && check_global)
1401 entry = silc_idlist_find_server_by_name(server->global_list,
1404 *servers = silc_realloc(*servers, sizeof(**servers) *
1405 (*servers_count + 1));
1406 (*servers)[(*servers_count)++] = entry;
1410 /* the server does not exist, send error reply */
1411 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1412 SILC_STATUS_ERR_NO_SUCH_SERVER,
1413 3, tmp, strlen(tmp));
1418 /* Try to get channel name */
1419 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1421 entry = silc_idlist_find_channel_by_name(server->local_list,
1423 if (!entry && check_global)
1424 entry = silc_idlist_find_channel_by_name(server->global_list,
1427 *channels = silc_realloc(*channels, sizeof(**channels) *
1428 (*channels_count + 1));
1429 (*channels)[(*channels_count)++] = entry;
1433 /* The channel does not exist, send error reply */
1434 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1435 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1436 3, tmp, strlen(tmp));
1441 if (!(*clients) && !(*servers) && !(*channels)) {
1442 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1443 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1447 /* Command includes ID, we must use that. Also check whether the command
1448 has more than one ID set - take them all. */
1450 /* Take all ID's from the command packet */
1451 for (i = 0; i < argc; i++) {
1454 tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
1458 idp = silc_id_payload_parse(tmp, len);
1460 silc_free(*clients);
1461 silc_free(*servers);
1462 silc_free(*channels);
1463 silc_server_command_send_status_reply(
1464 cmd, SILC_COMMAND_IDENTIFY,
1465 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1469 id = silc_id_payload_get_id(idp);
1471 switch (silc_id_payload_get_type(idp)) {
1473 case SILC_ID_CLIENT:
1474 entry = (void *)silc_idlist_find_client_by_id(server->local_list,
1476 if (!entry && check_global)
1477 entry = (void *)silc_idlist_find_client_by_id(server->global_list,
1480 *clients = silc_realloc(*clients, sizeof(**clients) *
1481 (*clients_count + 1));
1482 (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
1484 /* If we are normal server and have not resolved information from
1485 router yet, do so now. */
1486 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1487 server->server_type == SILC_SERVER && !cmd->pending &&
1488 !server->standalone) {
1489 silc_server_command_identify_send_router(cmd);
1490 silc_free(*clients);
1491 silc_free(*servers);
1492 silc_free(*channels);
1495 silc_server_command_send_status_data(
1496 cmd, SILC_COMMAND_IDENTIFY,
1497 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1505 case SILC_ID_SERVER:
1506 entry = (void *)silc_idlist_find_server_by_id(server->local_list,
1508 if (!entry && check_global)
1509 entry = (void *)silc_idlist_find_server_by_id(server->global_list,
1512 *servers = silc_realloc(*servers, sizeof(**servers) *
1513 (*servers_count + 1));
1514 (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
1516 /* If we are normal server and have not resolved information from
1517 router yet, do so now. */
1518 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1519 server->server_type == SILC_SERVER && !cmd->pending &&
1520 !server->standalone) {
1521 silc_server_command_identify_send_router(cmd);
1522 silc_free(*clients);
1523 silc_free(*servers);
1524 silc_free(*channels);
1527 silc_server_command_send_status_data(
1528 cmd, SILC_COMMAND_IDENTIFY,
1529 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
1536 case SILC_ID_CHANNEL:
1537 entry = (void *)silc_idlist_find_channel_by_id(server->local_list,
1539 if (!entry && check_global)
1540 entry = (void *)silc_idlist_find_channel_by_id(server->global_list,
1543 *channels = silc_realloc(*channels, sizeof(**channels) *
1544 (*channels_count + 1));
1545 (*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
1547 /* If we are normal server and have not resolved information from
1548 router yet, do so now. */
1549 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1550 server->server_type == SILC_SERVER && !cmd->pending &&
1551 !server->standalone) {
1552 silc_server_command_identify_send_router(cmd);
1553 silc_free(*clients);
1554 silc_free(*servers);
1555 silc_free(*channels);
1558 silc_server_command_send_status_data(
1559 cmd, SILC_COMMAND_IDENTIFY,
1560 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
1573 silc_free(*clients);
1574 silc_free(*servers);
1575 silc_free(*channels);
1579 /* Get the max count of reply messages allowed */
1580 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1589 /* Checks that all mandatory fields in client entry are present. If not
1590 then send WHOIS request to the server who owns the client. We use
1591 WHOIS because we want to get as much information as possible at once. */
1594 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1595 SilcClientEntry *clients,
1596 uint32 clients_count)
1598 SilcServer server = cmd->server;
1599 SilcClientEntry entry;
1600 SilcServerResolveContext resolve = NULL, r = NULL;
1601 uint32 resolve_count = 0;
1605 for (i = 0; i < clients_count; i++) {
1610 if (entry->nickname ||
1611 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1615 /* If we are normal server, and we've not resolved this client from
1616 router and it is global client, we'll check whether it is on some
1617 channel. If not then we cannot be sure about its validity, and
1618 we'll resolve it from router. */
1619 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
1620 entry->connection || silc_hash_table_count(entry->channels))
1624 /* We need to resolve this entry since it is not complete */
1626 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1627 /* The entry is being resolved (and we are not the resolver) so attach
1628 to the command reply and we're done with this one. */
1629 silc_server_command_pending(server, SILC_COMMAND_NONE,
1630 entry->resolve_cmd_ident,
1631 silc_server_command_identify,
1632 silc_server_command_dup(cmd));
1635 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1636 /* We've resolved this and it still is not ready. We'll return
1637 and are that this will be handled again after it is resolved. */
1638 for (i = 0; i < resolve_count; i++) {
1639 for (k = 0; k < r->res_argc; k++)
1640 silc_free(r->res_argv[k]);
1641 silc_free(r->res_argv);
1642 silc_free(r->res_argv_lens);
1643 silc_free(r->res_argv_types);
1648 /* We'll resolve this client */
1652 for (k = 0; k < resolve_count; k++) {
1653 if (resolve[k].router == entry->router) {
1660 resolve = silc_realloc(resolve, sizeof(*resolve) *
1661 (resolve_count + 1));
1662 r = &resolve[resolve_count];
1663 memset(r, 0, sizeof(*r));
1664 r->router = entry->router;
1665 r->ident = ++server->cmd_ident;
1669 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1671 r->res_argv_lens = silc_realloc(r->res_argv_lens,
1672 sizeof(*r->res_argv_lens) *
1674 r->res_argv_types = silc_realloc(r->res_argv_types,
1675 sizeof(*r->res_argv_types) *
1677 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1678 r->res_argv[r->res_argc] = silc_calloc(idp->len,
1679 sizeof(**r->res_argv));
1680 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1681 r->res_argv_lens[r->res_argc] = idp->len;
1682 r->res_argv_types[r->res_argc] = r->res_argc + 3;
1684 silc_buffer_free(idp);
1686 entry->resolve_cmd_ident = r->ident;
1687 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1688 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1693 /* Do the resolving */
1694 for (i = 0; i < resolve_count; i++) {
1699 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1700 now anyway so make it a good one. */
1701 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1702 r->res_argc, r->res_argv,
1706 silc_server_packet_send(server, r->router->connection,
1707 SILC_PACKET_COMMAND, cmd->packet->flags,
1708 res_cmd->data, res_cmd->len, FALSE);
1710 /* Reprocess this packet after received reply */
1711 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1713 silc_server_command_identify,
1714 silc_server_command_dup(cmd));
1715 cmd->pending = TRUE;
1717 silc_buffer_free(res_cmd);
1718 for (k = 0; k < r->res_argc; k++)
1719 silc_free(r->res_argv[k]);
1720 silc_free(r->res_argv);
1721 silc_free(r->res_argv_lens);
1722 silc_free(r->res_argv_types);
1731 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1732 SilcClientEntry *clients,
1733 uint32 clients_count,
1734 SilcServerEntry *servers,
1735 uint32 servers_count,
1736 SilcChannelEntry *channels,
1737 uint32 channels_count,
1740 SilcServer server = cmd->server;
1741 int i, k, len, valid_count;
1742 SilcBuffer packet, idp;
1743 SilcCommandStatus status;
1744 uint16 ident = silc_command_get_ident(cmd->payload);
1745 char nh[256], uh[256];
1746 SilcSocketConnection hsock;
1748 status = SILC_STATUS_OK;
1751 SilcClientEntry entry;
1753 /* Process only valid entries. */
1755 for (i = 0; i < clients_count; i++) {
1756 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1763 /* No valid entries found at all, just send error */
1766 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1768 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1769 SILC_STATUS_ERR_NO_SUCH_NICK,
1770 3, tmp, strlen(tmp));
1772 tmp = silc_argument_get_arg_type(cmd->args, 5, (uint32 *)&len);
1773 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1774 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1780 /* Process all valid client entries and send command replies */
1782 if (valid_count > 1)
1783 status = SILC_STATUS_LIST_START;
1785 for (i = 0, k = 0; i < clients_count; i++) {
1791 status = SILC_STATUS_LIST_ITEM;
1792 if (valid_count > 1 && k == valid_count - 1
1793 && !servers_count && !channels_count)
1794 status = SILC_STATUS_LIST_END;
1795 if (count && k - 1 == count)
1796 status = SILC_STATUS_LIST_END;
1797 if (count && k - 1 > count)
1800 /* Send IDENTIFY reply */
1802 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1803 memset(uh, 0, sizeof(uh));
1804 memset(nh, 0, sizeof(nh));
1805 strncat(nh, entry->nickname, strlen(entry->nickname));
1806 if (!strchr(entry->nickname, '@')) {
1807 strncat(nh, "@", 1);
1808 if (entry->servername) {
1809 strncat(nh, entry->servername, strlen(entry->servername));
1811 len = entry->router ? strlen(entry->router->server_name) :
1812 strlen(server->server_name);
1813 strncat(nh, entry->router ? entry->router->server_name :
1814 server->server_name, len);
1818 if (!entry->username) {
1819 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1821 2, idp->data, idp->len,
1824 strncat(uh, entry->username, strlen(entry->username));
1825 if (!strchr(entry->username, '@')) {
1826 strncat(uh, "@", 1);
1827 hsock = (SilcSocketConnection)entry->connection;
1828 len = strlen(hsock->hostname);
1829 strncat(uh, hsock->hostname, len);
1832 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1834 2, idp->data, idp->len,
1839 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1840 0, packet->data, packet->len, FALSE);
1842 silc_buffer_free(packet);
1843 silc_buffer_free(idp);
1850 SilcServerEntry entry;
1852 if (status == SILC_STATUS_OK && servers_count > 1)
1853 status = SILC_STATUS_LIST_START;
1855 for (i = 0, k = 0; i < servers_count; i++) {
1859 status = SILC_STATUS_LIST_ITEM;
1860 if (servers_count > 1 && k == servers_count - 1 && !channels_count)
1861 status = SILC_STATUS_LIST_END;
1862 if (count && k - 1 == count)
1863 status = SILC_STATUS_LIST_END;
1864 if (count && k - 1 > count)
1867 /* Send IDENTIFY reply */
1868 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1870 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1872 2, idp->data, idp->len,
1873 3, entry->server_name,
1874 entry->server_name ?
1875 strlen(entry->server_name) : 0);
1876 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1877 0, packet->data, packet->len, FALSE);
1879 silc_buffer_free(packet);
1880 silc_buffer_free(idp);
1887 SilcChannelEntry entry;
1889 if (status == SILC_STATUS_OK && channels_count > 1)
1890 status = SILC_STATUS_LIST_START;
1892 for (i = 0, k = 0; i < channels_count; i++) {
1893 entry = channels[i];
1896 status = SILC_STATUS_LIST_ITEM;
1897 if (channels_count > 1 && k == channels_count - 1)
1898 status = SILC_STATUS_LIST_END;
1899 if (count && k - 1 == count)
1900 status = SILC_STATUS_LIST_END;
1901 if (count && k - 1 > count)
1904 /* Send IDENTIFY reply */
1905 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1907 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1909 2, idp->data, idp->len,
1910 3, entry->channel_name,
1911 entry->channel_name ?
1912 strlen(entry->channel_name): 0);
1913 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1914 0, packet->data, packet->len, FALSE);
1916 silc_buffer_free(packet);
1917 silc_buffer_free(idp);
1925 silc_server_command_identify_process(SilcServerCommandContext cmd)
1929 SilcClientEntry *clients = NULL;
1930 SilcServerEntry *servers = NULL;
1931 SilcChannelEntry *channels = NULL;
1932 uint32 clients_count = 0, servers_count = 0, channels_count = 0;
1934 /* Parse the IDENTIFY request */
1935 ret = silc_server_command_identify_parse(cmd,
1936 &clients, &clients_count,
1937 &servers, &servers_count,
1938 &channels, &channels_count,
1944 /* Check that all mandatory fields are present and request those data
1945 from the server who owns the client if necessary. */
1946 if (clients && !silc_server_command_identify_check_client(cmd, clients,
1952 /* Send the command reply to the client */
1953 silc_server_command_identify_send_reply(cmd,
1954 clients, clients_count,
1955 servers, servers_count,
1956 channels, channels_count,
1962 silc_free(channels);
1966 SILC_SERVER_CMD_FUNC(identify)
1968 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1971 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1973 ret = silc_server_command_identify_process(cmd);
1974 silc_server_command_free(cmd);
1977 /* Server side of command NICK. Sets nickname for user. Setting
1978 nickname causes generation of a new client ID for the client. The
1979 new client ID is sent to the client after changing the nickname. */
1981 SILC_SERVER_CMD_FUNC(nick)
1983 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1984 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1985 SilcServer server = cmd->server;
1986 SilcBuffer packet, nidp, oidp = NULL;
1987 SilcClientID *new_id;
1990 uint16 ident = silc_command_get_ident(cmd->payload);
1993 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1996 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
1998 /* Check nickname */
1999 nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
2002 if (silc_server_name_bad_chars(nick, nick_len) == TRUE) {
2003 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2004 SILC_STATUS_ERR_BAD_NICKNAME);
2008 /* Check for same nickname */
2009 if (!strcmp(client->nickname, nick)) {
2010 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2014 /* Create new Client ID */
2015 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
2017 cmd->server->md5hash, nick,
2020 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2023 /* Send notify about nickname change to our router. We send the new
2024 ID and ask to replace it with the old one. If we are router the
2025 packet is broadcasted. Send NICK_CHANGE notify. */
2026 if (!server->standalone)
2027 silc_server_send_notify_nick_change(server, server->router->connection,
2028 server->server_type == SILC_SERVER ?
2029 FALSE : TRUE, client->id,
2032 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2034 /* Remove old cache entry */
2035 silc_idcache_del_by_context(server->local_list->clients, client);
2038 silc_free(client->id);
2040 /* Save the nickname as this client is our local client */
2041 silc_free(client->nickname);
2043 client->nickname = strdup(nick);
2044 client->id = new_id;
2046 /* Update client cache */
2047 silc_idcache_add(server->local_list->clients, client->nickname,
2048 client->id, (void *)client, 0, NULL);
2050 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2052 /* Send NICK_CHANGE notify to the client's channels */
2053 silc_server_send_notify_on_channels(server, NULL, client,
2054 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
2055 oidp->data, oidp->len,
2056 nidp->data, nidp->len);
2059 /* Send the new Client ID as reply command back to client */
2060 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
2061 SILC_STATUS_OK, ident, 1,
2062 2, nidp->data, nidp->len);
2063 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2064 0, packet->data, packet->len, FALSE);
2066 silc_buffer_free(packet);
2067 silc_buffer_free(nidp);
2069 silc_buffer_free(oidp);
2072 silc_server_command_free(cmd);
2075 /* Sends the LIST command reply */
2078 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2079 SilcChannelEntry *lch,
2081 SilcChannelEntry *gch,
2085 SilcBuffer packet, idp;
2086 SilcChannelEntry entry;
2087 SilcCommandStatus status;
2088 uint16 ident = silc_command_get_ident(cmd->payload);
2090 unsigned char usercount[4];
2092 int valid_lcount = 0, valid_rcount = 0;
2094 for (i = 0; i < lch_count; i++) {
2095 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2100 for (i = 0; i < gch_count; i++) {
2101 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2107 status = SILC_STATUS_OK;
2108 if ((lch_count + gch_count) > 1)
2109 status = SILC_STATUS_LIST_START;
2112 for (i = 0, k = 0; i < lch_count; i++) {
2118 status = SILC_STATUS_LIST_ITEM;
2119 if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
2120 status = SILC_STATUS_LIST_END;
2122 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2124 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2125 topic = "*private*";
2126 memset(usercount, 0, sizeof(usercount));
2128 topic = entry->topic;
2129 users = silc_hash_table_count(entry->user_list);
2130 SILC_PUT32_MSB(users, usercount);
2133 /* Send the reply */
2135 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2137 2, idp->data, idp->len,
2138 3, entry->channel_name,
2139 strlen(entry->channel_name),
2140 4, topic, topic ? strlen(topic) : 0,
2142 silc_server_packet_send(cmd->server, cmd->sock,
2143 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2144 packet->len, FALSE);
2145 silc_buffer_free(packet);
2146 silc_buffer_free(idp);
2151 for (i = 0, k = 0; i < gch_count; i++) {
2157 status = SILC_STATUS_LIST_ITEM;
2158 if (valid_rcount > 1 && k == valid_rcount - 1)
2159 status = SILC_STATUS_LIST_END;
2161 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2163 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2164 topic = "*private*";
2165 memset(usercount, 0, sizeof(usercount));
2167 topic = entry->topic;
2168 users = silc_hash_table_count(entry->user_list);
2169 SILC_PUT32_MSB(users, usercount);
2172 /* Send the reply */
2174 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2176 2, idp->data, idp->len,
2177 3, entry->channel_name,
2178 strlen(entry->channel_name),
2179 4, topic, topic ? strlen(topic) : 0,
2181 silc_server_packet_send(cmd->server, cmd->sock,
2182 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2183 packet->len, FALSE);
2184 silc_buffer_free(packet);
2185 silc_buffer_free(idp);
2190 /* Server side of LIST command. This lists the channel of the requested
2191 server. Secret channels are not listed. */
2193 SILC_SERVER_CMD_FUNC(list)
2195 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2196 SilcServer server = cmd->server;
2197 SilcChannelID *channel_id = NULL;
2200 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2201 uint32 lch_count = 0, gch_count = 0;
2203 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2205 /* If we are normal server, send the command to router, since we
2206 want to know all channels in the network. */
2207 if (!cmd->pending && server->server_type == SILC_SERVER &&
2208 !server->standalone) {
2212 old_ident = silc_command_get_ident(cmd->payload);
2213 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2214 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2215 silc_server_packet_send(server, server->router->connection,
2216 SILC_PACKET_COMMAND, cmd->packet->flags,
2217 tmpbuf->data, tmpbuf->len, TRUE);
2219 /* Reprocess this packet after received reply from router */
2220 silc_server_command_pending(server, SILC_COMMAND_LIST,
2221 silc_command_get_ident(cmd->payload),
2222 silc_server_command_list,
2223 silc_server_command_dup(cmd));
2224 cmd->pending = TRUE;
2225 silc_command_set_ident(cmd->payload, old_ident);
2226 silc_buffer_free(tmpbuf);
2230 /* Get Channel ID */
2231 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2233 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2235 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2236 SILC_STATUS_ERR_NO_CHANNEL_ID);
2241 /* Get the channels from local list */
2242 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2245 /* Get the channels from global list */
2246 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2249 /* Send the reply */
2250 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2251 gchannels, gch_count);
2253 silc_free(lchannels);
2254 silc_free(gchannels);
2257 silc_server_command_free(cmd);
2260 /* Server side of TOPIC command. Sets topic for channel and/or returns
2261 current topic to client. */
2263 SILC_SERVER_CMD_FUNC(topic)
2265 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2266 SilcServer server = cmd->server;
2267 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2268 SilcChannelID *channel_id;
2269 SilcChannelEntry channel;
2270 SilcChannelClientEntry chl;
2271 SilcBuffer packet, idp;
2273 uint32 argc, tmp_len;
2274 uint16 ident = silc_command_get_ident(cmd->payload);
2276 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2278 argc = silc_argument_get_arg_num(cmd->args);
2280 /* Get Channel ID */
2281 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2283 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2284 SILC_STATUS_ERR_NO_CHANNEL_ID);
2287 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2289 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2290 SILC_STATUS_ERR_NO_CHANNEL_ID);
2294 /* Check whether the channel exists */
2295 channel = silc_idlist_find_channel_by_id(server->local_list,
2298 channel = silc_idlist_find_channel_by_id(server->global_list,
2301 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2302 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2309 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2311 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2312 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2316 if (strlen(tmp) > 256) {
2317 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2318 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2322 /* See whether the client is on channel and has rights to change topic */
2323 if (!silc_hash_table_find(channel->user_list, client, NULL,
2325 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2326 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2330 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2331 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2332 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2333 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2338 /* Set the topic for channel */
2339 silc_free(channel->topic);
2340 channel->topic = strdup(tmp);
2342 /* Send TOPIC_SET notify type to the network */
2343 if (!server->standalone)
2344 silc_server_send_notify_topic_set(server, server->router->connection,
2345 server->server_type == SILC_ROUTER ?
2346 TRUE : FALSE, channel,
2347 client->id, SILC_ID_CLIENT,
2350 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2352 /* Send notify about topic change to all clients on the channel */
2353 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2354 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2355 idp->data, idp->len,
2356 channel->topic, strlen(channel->topic));
2357 silc_buffer_free(idp);
2360 /* Send the topic to client as reply packet */
2361 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2362 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2363 SILC_STATUS_OK, ident, 2,
2364 2, idp->data, idp->len,
2367 strlen(channel->topic) : 0);
2368 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2369 0, packet->data, packet->len, FALSE);
2371 silc_buffer_free(packet);
2372 silc_buffer_free(idp);
2373 silc_free(channel_id);
2376 silc_server_command_free(cmd);
2379 /* Server side of INVITE command. Invites some client to join some channel.
2380 This command is also used to manage the invite list of the channel. */
2382 SILC_SERVER_CMD_FUNC(invite)
2384 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2385 SilcServer server = cmd->server;
2386 SilcSocketConnection sock = cmd->sock, dest_sock;
2387 SilcChannelClientEntry chl;
2388 SilcClientEntry sender, dest;
2389 SilcClientID *dest_id = NULL;
2390 SilcChannelEntry channel;
2391 SilcChannelID *channel_id = NULL;
2392 SilcIDListData idata;
2393 SilcBuffer idp, idp2, packet;
2394 unsigned char *tmp, *add, *del;
2396 uint16 ident = silc_command_get_ident(cmd->payload);
2398 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2400 /* Get Channel ID */
2401 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2403 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2404 SILC_STATUS_ERR_NO_CHANNEL_ID);
2407 channel_id = silc_id_payload_parse_id(tmp, len);
2409 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2410 SILC_STATUS_ERR_NO_CHANNEL_ID);
2414 /* Get the channel entry */
2415 channel = silc_idlist_find_channel_by_id(server->local_list,
2418 channel = silc_idlist_find_channel_by_id(server->global_list,
2421 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2422 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2427 /* Check whether the sender of this command is on the channel. */
2428 sender = (SilcClientEntry)sock->user_data;
2429 if (!silc_server_client_on_channel(sender, channel)) {
2430 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2431 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2435 /* Check whether the channel is invite-only channel. If yes then the
2436 sender of this command must be at least channel operator. */
2437 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2438 silc_hash_table_find(channel->user_list, sender, NULL, (void *)&chl);
2439 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2440 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2441 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2446 /* Get destination client ID */
2447 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2452 dest_id = silc_id_payload_parse_id(tmp, len);
2454 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2455 SILC_STATUS_ERR_NO_CLIENT_ID);
2459 /* Get the client entry */
2460 dest = silc_server_get_client_resolve(server, dest_id, &resolve);
2462 if (server->server_type != SILC_SERVER || !resolve) {
2463 silc_server_command_send_status_reply(
2464 cmd, SILC_COMMAND_INVITE,
2465 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2469 /* The client info is being resolved. Reprocess this packet after
2470 receiving the reply to the query. */
2471 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2473 silc_server_command_invite,
2474 silc_server_command_dup(cmd));
2475 cmd->pending = TRUE;
2476 silc_free(channel_id);
2481 /* Check whether the requested client is already on the channel. */
2482 if (silc_server_client_on_channel(dest, channel)) {
2483 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2484 SILC_STATUS_ERR_USER_ON_CHANNEL);
2488 /* Get route to the client */
2489 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2491 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2492 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2496 memset(invite, 0, sizeof(invite));
2497 strncat(invite, dest->nickname, strlen(dest->nickname));
2498 strncat(invite, "!", 1);
2499 strncat(invite, dest->username, strlen(dest->username));
2500 if (!strchr(dest->username, '@')) {
2501 strncat(invite, "@", 1);
2502 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2505 len = strlen(invite);
2506 if (!channel->invite_list)
2507 channel->invite_list = silc_calloc(len + 2,
2508 sizeof(*channel->invite_list));
2510 channel->invite_list = silc_realloc(channel->invite_list,
2511 sizeof(*channel->invite_list) *
2513 strlen(channel->invite_list) + 2));
2514 strncat(channel->invite_list, invite, len);
2515 strncat(channel->invite_list, ",", 1);
2517 /* Send notify to the client that is invited to the channel */
2518 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2519 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2520 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2522 SILC_NOTIFY_TYPE_INVITE, 3,
2523 idp->data, idp->len,
2524 channel->channel_name,
2525 strlen(channel->channel_name),
2526 idp2->data, idp2->len);
2527 silc_buffer_free(idp);
2528 silc_buffer_free(idp2);
2531 /* Add the client to the invite list of the channel */
2532 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2534 if (!channel->invite_list)
2535 channel->invite_list = silc_calloc(len + 2,
2536 sizeof(*channel->invite_list));
2538 channel->invite_list = silc_realloc(channel->invite_list,
2539 sizeof(*channel->invite_list) *
2541 strlen(channel->invite_list) + 2));
2542 if (add[len - 1] == ',')
2543 add[len - 1] = '\0';
2545 strncat(channel->invite_list, add, len);
2546 strncat(channel->invite_list, ",", 1);
2549 /* Get the invite to be removed and remove it from the list */
2550 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2551 if (del && channel->invite_list) {
2552 char *start, *end, *n;
2554 if (!strncmp(channel->invite_list, del,
2555 strlen(channel->invite_list) - 1)) {
2556 silc_free(channel->invite_list);
2557 channel->invite_list = NULL;
2559 start = strstr(channel->invite_list, del);
2560 if (start && strlen(start) >= len) {
2562 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2563 strncat(n, channel->invite_list, start - channel->invite_list);
2564 strncat(n, end + 1, ((channel->invite_list +
2565 strlen(channel->invite_list)) - end) - 1);
2566 silc_free(channel->invite_list);
2567 channel->invite_list = n;
2572 /* Send notify to the primary router */
2573 if (!server->standalone)
2574 silc_server_send_notify_invite(server, server->router->connection,
2575 server->server_type == SILC_ROUTER ?
2576 TRUE : FALSE, channel,
2577 sender->id, add, del);
2579 /* Send command reply */
2580 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2584 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2585 SILC_STATUS_OK, ident, 2,
2587 3, channel->invite_list,
2588 channel->invite_list ?
2589 strlen(channel->invite_list) : 0);
2592 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2593 SILC_STATUS_OK, ident, 1,
2595 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2596 packet->data, packet->len, FALSE);
2597 silc_buffer_free(packet);
2601 silc_free(channel_id);
2602 silc_server_command_free(cmd);
2607 SilcSocketConnection sock;
2611 /* Quits connection to client. This gets called if client won't
2612 close the connection even when it has issued QUIT command. */
2614 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2616 QuitInternal q = (QuitInternal)context;
2618 /* Free all client specific data, such as client entry and entires
2619 on channels this client may be on. */
2620 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2622 q->sock->user_data = NULL;
2624 /* Close the connection on our side */
2625 silc_server_close_connection(q->server, q->sock);
2627 silc_free(q->signoff);
2631 /* Quits SILC session. This is the normal way to disconnect client. */
2633 SILC_SERVER_CMD_FUNC(quit)
2635 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2636 SilcServer server = cmd->server;
2637 SilcSocketConnection sock = cmd->sock;
2639 unsigned char *tmp = NULL;
2642 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2644 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2647 /* Get destination ID */
2648 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2652 q = silc_calloc(1, sizeof(*q));
2655 q->signoff = tmp ? strdup(tmp) : NULL;
2657 /* We quit the connection with little timeout */
2658 silc_schedule_task_add(server->schedule, sock->sock,
2659 silc_server_command_quit_cb, (void *)q,
2660 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2663 silc_server_command_free(cmd);
2666 /* Server side of command KILL. This command is used by router operator
2667 to remove an client from the SILC Network temporarily. */
2669 SILC_SERVER_CMD_FUNC(kill)
2671 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2672 SilcServer server = cmd->server;
2673 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2674 SilcClientEntry remote_client;
2675 SilcClientID *client_id;
2676 unsigned char *tmp, *comment;
2677 uint32 tmp_len, tmp_len2;
2680 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2682 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2685 /* KILL command works only on router */
2686 if (server->server_type != SILC_ROUTER) {
2687 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2688 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2692 /* Check whether client has the permissions. */
2693 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2694 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2695 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2699 /* Get the client ID */
2700 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2702 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2703 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2706 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2708 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2709 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2713 /* Get the client entry */
2714 remote_client = silc_idlist_find_client_by_id(server->local_list,
2715 client_id, TRUE, NULL);
2717 if (!remote_client) {
2718 remote_client = silc_idlist_find_client_by_id(server->global_list,
2719 client_id, TRUE, NULL);
2721 if (!remote_client) {
2722 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2723 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2729 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2733 /* Send reply to the sender */
2734 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2737 /* Send the KILL notify packets. First send it to the channel, then
2738 to our primary router and then directly to the client who is being
2739 killed right now. */
2741 /* Send KILLED notify to the channels. It is not sent to the client
2742 as it will be sent differently destined directly to the client and not
2744 silc_server_send_notify_on_channels(server, remote_client,
2745 remote_client, SILC_NOTIFY_TYPE_KILLED,
2748 comment, comment ? tmp_len2 : 0);
2750 /* Send KILLED notify to primary route */
2751 if (!server->standalone)
2752 silc_server_send_notify_killed(server, server->router->connection, TRUE,
2753 remote_client->id, comment);
2755 /* Send KILLED notify to the client directly */
2756 silc_server_send_notify_killed(server, remote_client->connection ?
2757 remote_client->connection :
2758 remote_client->router->connection, FALSE,
2759 remote_client->id, comment);
2761 /* Remove the client from all channels. This generates new keys to the
2762 channels as well. */
2763 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2766 /* Remove the client entry, If it is locally connected then we will also
2767 disconnect the client here */
2768 if (remote_client->connection) {
2769 /* Remove locally conneted client */
2770 SilcSocketConnection sock = remote_client->connection;
2771 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2772 silc_server_close_connection(server, sock);
2774 /* Update statistics */
2775 if (remote_client->connection)
2776 server->stat.my_clients--;
2777 if (server->server_type == SILC_ROUTER)
2778 server->stat.cell_clients--;
2779 SILC_OPER_STATS_UPDATE(remote_client, server, SILC_UMODE_SERVER_OPERATOR);
2780 SILC_OPER_STATS_UPDATE(remote_client, router, SILC_UMODE_ROUTER_OPERATOR);
2782 /* Remove remote client */
2783 silc_idlist_del_client(local ? server->local_list :
2784 server->global_list, remote_client);
2788 silc_server_command_free(cmd);
2791 /* Server side of command INFO. This sends information about us to
2792 the client. If client requested specific server we will send the
2793 command to that server. */
2795 SILC_SERVER_CMD_FUNC(info)
2797 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2798 SilcServer server = cmd->server;
2799 SilcBuffer packet, idp;
2802 char *dest_server, *server_info = NULL, *server_name;
2803 uint16 ident = silc_command_get_ident(cmd->payload);
2804 SilcServerEntry entry = NULL;
2805 SilcServerID *server_id = NULL;
2807 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2809 /* Get server name */
2810 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2813 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2815 server_id = silc_id_payload_parse_id(tmp, tmp_len);
2817 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2818 SILC_STATUS_ERR_NO_SERVER_ID);
2824 /* Check whether we have this server cached */
2825 entry = silc_idlist_find_server_by_id(server->local_list,
2826 server_id, TRUE, NULL);
2828 entry = silc_idlist_find_server_by_id(server->global_list,
2829 server_id, TRUE, NULL);
2830 if (!entry && server->server_type != SILC_SERVER) {
2831 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2832 SILC_STATUS_ERR_NO_SUCH_SERVER);
2838 /* Some buggy servers has sent request to router about themselves. */
2839 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2842 if ((!dest_server && !server_id && !entry) || (entry &&
2843 entry == server->id_entry) ||
2844 (dest_server && !cmd->pending &&
2845 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2846 /* Send our reply */
2847 char info_string[256];
2849 memset(info_string, 0, sizeof(info_string));
2850 snprintf(info_string, sizeof(info_string),
2851 "location: %s server: %s admin: %s <%s>",
2852 server->config->server_info->location,
2853 server->config->server_info->server_type,
2854 server->config->server_info->admin,
2855 server->config->server_info->email);
2857 server_info = info_string;
2858 entry = server->id_entry;
2860 /* Check whether we have this server cached */
2861 if (!entry && dest_server) {
2862 entry = silc_idlist_find_server_by_name(server->global_list,
2863 dest_server, TRUE, NULL);
2865 entry = silc_idlist_find_server_by_name(server->local_list,
2866 dest_server, TRUE, NULL);
2870 if (!cmd->pending &&
2871 server->server_type != SILC_SERVER && entry && !entry->server_info) {
2872 /* Send to the server */
2876 old_ident = silc_command_get_ident(cmd->payload);
2877 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2878 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2880 silc_server_packet_send(server, entry->connection,
2881 SILC_PACKET_COMMAND, cmd->packet->flags,
2882 tmpbuf->data, tmpbuf->len, TRUE);
2884 /* Reprocess this packet after received reply from router */
2885 silc_server_command_pending(server, SILC_COMMAND_INFO,
2886 silc_command_get_ident(cmd->payload),
2887 silc_server_command_info,
2888 silc_server_command_dup(cmd));
2889 cmd->pending = TRUE;
2890 silc_command_set_ident(cmd->payload, old_ident);
2891 silc_buffer_free(tmpbuf);
2895 if (!entry && !cmd->pending && !server->standalone) {
2896 /* Send to the primary router */
2900 old_ident = silc_command_get_ident(cmd->payload);
2901 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2902 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2904 silc_server_packet_send(server, server->router->connection,
2905 SILC_PACKET_COMMAND, cmd->packet->flags,
2906 tmpbuf->data, tmpbuf->len, TRUE);
2908 /* Reprocess this packet after received reply from router */
2909 silc_server_command_pending(server, SILC_COMMAND_INFO,
2910 silc_command_get_ident(cmd->payload),
2911 silc_server_command_info,
2912 silc_server_command_dup(cmd));
2913 cmd->pending = TRUE;
2914 silc_command_set_ident(cmd->payload, old_ident);
2915 silc_buffer_free(tmpbuf);
2920 silc_free(server_id);
2923 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2924 SILC_STATUS_ERR_NO_SUCH_SERVER);
2928 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2930 server_info = entry->server_info;
2931 server_name = entry->server_name;
2933 /* Send the reply */
2934 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2935 SILC_STATUS_OK, ident, 3,
2936 2, idp->data, idp->len,
2938 strlen(server_name),
2941 strlen(server_info) : 0);
2942 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2943 packet->data, packet->len, FALSE);
2945 silc_buffer_free(packet);
2946 silc_buffer_free(idp);
2949 silc_server_command_free(cmd);
2952 /* Server side of command PING. This just replies to the ping. */
2954 SILC_SERVER_CMD_FUNC(ping)
2956 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2957 SilcServer server = cmd->server;
2962 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
2965 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2967 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2968 SILC_STATUS_ERR_NO_SERVER_ID);
2971 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2975 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2976 /* Send our reply */
2977 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2980 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2981 SILC_STATUS_ERR_NO_SUCH_SERVER);
2988 silc_server_command_free(cmd);
2991 /* Internal routine to join channel. The channel sent to this function
2992 has been either created or resolved from ID lists. This joins the sent
2993 client to the channel. */
2995 static void silc_server_command_join_channel(SilcServer server,
2996 SilcServerCommandContext cmd,
2997 SilcChannelEntry channel,
2998 SilcClientID *client_id,
3002 const unsigned char *auth,
3005 SilcSocketConnection sock = cmd->sock;
3007 uint32 tmp_len, user_count;
3008 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
3009 SilcClientEntry client;
3010 SilcChannelClientEntry chl;
3011 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
3012 uint16 ident = silc_command_get_ident(cmd->payload);
3013 char check[512], check2[512];
3014 bool founder = FALSE;
3017 SILC_LOG_DEBUG(("Start"));
3022 /* Get the client entry */
3023 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3024 client = (SilcClientEntry)sock->user_data;
3026 client = silc_server_get_client_resolve(server, client_id, &resolve);
3032 silc_server_command_send_status_reply(
3033 cmd, SILC_COMMAND_JOIN,
3034 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3038 /* The client info is being resolved. Reprocess this packet after
3039 receiving the reply to the query. */
3040 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
3042 silc_server_command_join,
3043 silc_server_command_dup(cmd));
3044 cmd->pending = TRUE;
3048 cmd->pending = FALSE;
3052 * Check founder auth payload if provided. If client can gain founder
3053 * privileges it can override various conditions on joining the channel,
3054 * and can have directly the founder mode set on the channel.
3056 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3057 SilcIDListData idata = (SilcIDListData)client;
3059 if (channel->founder_key && idata->public_key &&
3060 silc_pkcs_public_key_compare(channel->founder_key,
3061 idata->public_key)) {
3062 void *auth_data = (channel->founder_method == SILC_AUTH_PASSWORD ?
3063 (void *)channel->founder_passwd :
3064 (void *)channel->founder_key);
3065 uint32 auth_data_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
3066 channel->founder_passwd_len : 0);
3068 /* Check whether the client is to become founder */
3069 if (silc_auth_verify_data(auth, auth_len, channel->founder_method,
3070 auth_data, auth_data_len,
3071 idata->hash, client->id, SILC_ID_CLIENT)) {
3072 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3079 * Check channel modes
3083 memset(check, 0, sizeof(check));
3084 memset(check2, 0, sizeof(check2));
3085 strncat(check, client->nickname, strlen(client->nickname));
3086 strncat(check, "!", 1);
3087 strncat(check, client->username, strlen(client->username));
3088 if (!strchr(client->username, '@')) {
3089 strncat(check, "@", 1);
3090 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3093 strncat(check2, client->nickname, strlen(client->nickname));
3094 if (!strchr(client->nickname, '@')) {
3095 strncat(check2, "@", 1);
3096 strncat(check2, server->server_name, strlen(server->server_name));
3098 strncat(check2, "!", 1);
3099 strncat(check2, client->username, strlen(client->username));
3100 if (!strchr(client->username, '@')) {
3101 strncat(check2, "@", 1);
3102 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3105 /* Check invite list if channel is invite-only channel */
3106 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3107 if (!channel->invite_list ||
3108 (!silc_string_match(channel->invite_list, check) &&
3109 !silc_string_match(channel->invite_list, check2))) {
3110 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3111 SILC_STATUS_ERR_NOT_INVITED);
3116 /* Check ban list if it exists. If the client's nickname, server,
3117 username and/or hostname is in the ban list the access to the
3118 channel is denied. */
3119 if (channel->ban_list) {
3120 if (silc_string_match(channel->ban_list, check) ||
3121 silc_string_match(channel->ban_list, check2)) {
3122 silc_server_command_send_status_reply(
3123 cmd, SILC_COMMAND_JOIN,
3124 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
3129 /* Check user count limit if set. */
3130 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3131 if (silc_hash_table_count(channel->user_list) + 1 >
3132 channel->user_limit) {
3133 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3134 SILC_STATUS_ERR_CHANNEL_IS_FULL);
3140 /* Check the channel passphrase if set. */
3141 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3142 /* Get passphrase */
3143 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3145 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
3146 memcpy(passphrase, tmp, tmp_len);
3149 if (!passphrase || !channel->passphrase ||
3150 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3151 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3152 SILC_STATUS_ERR_BAD_PASSWORD);
3158 * Client is allowed to join to the channel. Make it happen.
3161 /* Check whether the client already is on the channel */
3162 if (silc_server_client_on_channel(client, channel)) {
3163 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3164 SILC_STATUS_ERR_USER_ON_CHANNEL);
3168 /* Generate new channel key as protocol dictates */
3170 if (!silc_server_create_channel_key(server, channel, 0))
3173 /* Send the channel key. This is broadcasted to the channel but is not
3174 sent to the client who is joining to the channel. */
3175 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3176 silc_server_send_channel_key(server, NULL, channel,
3177 server->server_type == SILC_ROUTER ?
3178 FALSE : !server->standalone);
3181 /* Join the client to the channel by adding it to channel's user list.
3182 Add also the channel to client entry's channels list for fast cross-
3184 chl = silc_calloc(1, sizeof(*chl));
3186 chl->client = client;
3187 chl->channel = channel;
3188 silc_hash_table_add(channel->user_list, client, chl);
3189 silc_hash_table_add(client->channels, channel, chl);
3191 /* Get users on the channel */
3192 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3195 /* Encode Client ID Payload of the original client who wants to join */
3196 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3198 /* Encode command reply packet */
3199 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3200 SILC_PUT32_MSB(channel->mode, mode);
3201 SILC_PUT32_MSB(created, tmp2);
3202 SILC_PUT32_MSB(user_count, tmp3);
3204 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3205 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3206 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
3207 strlen(channel->channel_key->
3209 channel->channel_key->cipher->name,
3210 channel->key_len / 8, channel->key);
3215 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3216 SILC_STATUS_OK, ident, 13,
3217 2, channel->channel_name,
3218 strlen(channel->channel_name),
3219 3, chidp->data, chidp->len,
3220 4, clidp->data, clidp->len,
3223 7, keyp ? keyp->data : NULL,
3224 keyp ? keyp->len : 0,
3225 8, channel->ban_list,
3227 strlen(channel->ban_list) : 0,
3228 9, channel->invite_list,
3229 channel->invite_list ?
3230 strlen(channel->invite_list) : 0,
3233 strlen(channel->topic) : 0,
3234 11, silc_hmac_get_name(channel->hmac),
3235 strlen(silc_hmac_get_name(channel->
3238 13, user_list->data, user_list->len,
3239 14, mode_list->data,
3242 /* Send command reply */
3243 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3244 reply->data, reply->len, FALSE);
3246 /* Send JOIN notify to locally connected clients on the channel. If
3247 we are normal server then router will send or have sent JOIN notify
3248 already. However since we've added the client already to our channel
3249 we'll ignore it (in packet_receive.c) so we must send it here. If
3250 we are router then this will send it to local clients and local
3252 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3253 SILC_NOTIFY_TYPE_JOIN, 2,
3254 clidp->data, clidp->len,
3255 chidp->data, chidp->len);
3257 if (!cmd->pending) {
3258 /* Send JOIN notify packet to our primary router */
3259 if (!server->standalone)
3260 silc_server_send_notify_join(server, server->router->connection,
3261 server->server_type == SILC_ROUTER ?
3262 TRUE : FALSE, channel, client->id);
3265 /* Distribute the channel key to all backup routers. */
3266 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3267 keyp->data, keyp->len, FALSE, TRUE);
3270 /* If client became founder by providing correct founder auth data
3271 notify the mode change to the channel. */
3273 SILC_PUT32_MSB(chl->mode, mode);
3274 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3275 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3276 clidp->data, clidp->len,
3277 mode, 4, clidp->data, clidp->len);
3279 /* Set CUMODE notify type to network */
3280 if (!server->standalone)
3281 silc_server_send_notify_cumode(server, server->router->connection,
3282 server->server_type == SILC_ROUTER ?
3283 TRUE : FALSE, channel,
3284 chl->mode, client->id, SILC_ID_CLIENT,
3288 silc_buffer_free(reply);
3289 silc_buffer_free(clidp);
3290 silc_buffer_free(chidp);
3291 silc_buffer_free(keyp);
3292 silc_buffer_free(user_list);
3293 silc_buffer_free(mode_list);
3296 silc_free(passphrase);
3299 /* Server side of command JOIN. Joins client into requested channel. If
3300 the channel does not exist it will be created. */
3302 SILC_SERVER_CMD_FUNC(join)
3304 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3305 SilcServer server = cmd->server;
3306 unsigned char *auth;
3307 uint32 tmp_len, auth_len;
3308 char *tmp, *channel_name = NULL, *cipher, *hmac;
3309 SilcChannelEntry channel;
3311 bool created = FALSE, create_key = TRUE;
3312 SilcClientID *client_id;
3314 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3316 /* Get channel name */
3317 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3319 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3320 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3326 channel_name[255] = '\0';
3328 if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
3329 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3330 SILC_STATUS_ERR_BAD_CHANNEL);
3334 /* Get Client ID of the client who is joining to the channel */
3335 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3337 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3338 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3341 client_id = silc_id_payload_parse_id(tmp, tmp_len);
3343 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3344 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3348 /* Get cipher, hmac name and auth payload */
3349 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3350 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3351 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3353 /* See if the channel exists */
3354 channel = silc_idlist_find_channel_by_name(server->local_list,
3355 channel_name, NULL);
3357 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3358 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3359 client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
3361 if (!channel || channel->disabled) {
3362 /* Channel not found */
3364 /* If we are standalone server we don't have a router, we just create
3365 the channel by ourselves. */
3366 if (server->standalone) {
3367 channel = silc_server_create_new_channel(server, server->id, cipher,
3368 hmac, channel_name, TRUE);
3370 silc_server_command_send_status_reply(
3371 cmd, SILC_COMMAND_JOIN,
3372 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3376 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3382 /* The channel does not exist on our server. If we are normal server
3383 we will send JOIN command to our router which will handle the
3384 joining procedure (either creates the channel if it doesn't exist
3385 or joins the client to it). */
3386 if (server->server_type != SILC_ROUTER) {
3390 /* If this is pending command callback then we've resolved
3391 it and it didn't work, return since we've notified the
3392 client already in the command reply callback. */
3396 old_ident = silc_command_get_ident(cmd->payload);
3397 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3398 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3400 /* Send JOIN command to our router */
3401 silc_server_packet_send(server, (SilcSocketConnection)
3402 server->router->connection,
3403 SILC_PACKET_COMMAND, cmd->packet->flags,
3404 tmpbuf->data, tmpbuf->len, TRUE);
3406 /* Reprocess this packet after received reply from router */
3407 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3408 silc_command_get_ident(cmd->payload),
3409 silc_server_command_join,
3410 silc_server_command_dup(cmd));
3411 cmd->pending = TRUE;
3412 silc_command_set_ident(cmd->payload, old_ident);
3413 silc_buffer_free(tmpbuf);
3417 /* We are router and the channel does not seem exist so we will check
3418 our global list as well for the channel. */
3419 channel = silc_idlist_find_channel_by_name(server->global_list,
3420 channel_name, NULL);
3422 /* Channel really does not exist, create it */
3423 channel = silc_server_create_new_channel(server, server->id, cipher,
3424 hmac, channel_name, TRUE);
3426 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3427 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3431 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3439 /* Channel not found */
3441 /* If the command came from router and we are normal server then
3442 something went wrong with the joining as the channel was not found.
3443 We can't do anything else but ignore this. */
3444 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3445 server->server_type != SILC_ROUTER)
3448 /* We are router and the channel does not seem exist so we will check
3449 our global list as well for the channel. */
3450 channel = silc_idlist_find_channel_by_name(server->global_list,
3451 channel_name, NULL);
3453 /* Channel really does not exist, create it */
3454 channel = silc_server_create_new_channel(server, server->id, cipher,
3455 hmac, channel_name, TRUE);
3457 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3458 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3462 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3469 /* Check whether the channel was created by our router */
3470 if (cmd->pending && context2) {
3471 SilcServerCommandReplyContext reply =
3472 (SilcServerCommandReplyContext)context2;
3474 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3475 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3476 SILC_GET32_MSB(created, tmp);
3477 if (silc_argument_get_arg_type(reply->args, 7, NULL))
3478 create_key = FALSE; /* Router returned the key already */
3481 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
3482 !silc_hash_table_count(channel->user_list))
3486 /* If the channel does not have global users and is also empty the client
3487 will be the channel founder and operator. */
3488 if (!channel->global_users && !silc_hash_table_count(channel->user_list))
3489 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3491 /* Join to the channel */
3492 silc_server_command_join_channel(server, cmd, channel, client_id,
3493 created, create_key, umode,
3496 silc_free(client_id);
3499 silc_server_command_free(cmd);
3502 /* Server side of command MOTD. Sends server's current "message of the
3503 day" to the client. */
3505 SILC_SERVER_CMD_FUNC(motd)
3507 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3508 SilcServer server = cmd->server;
3509 SilcBuffer packet, idp;
3510 char *motd, *dest_server;
3512 uint16 ident = silc_command_get_ident(cmd->payload);
3514 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3516 /* Get server name */
3517 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3519 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3520 SILC_STATUS_ERR_NO_SUCH_SERVER);
3524 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3527 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3529 if (server->config && server->config->server_info &&
3530 server->config->server_info->motd_file) {
3532 motd = silc_file_readfile(server->config->server_info->motd_file, &motd_len);
3537 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3538 SILC_STATUS_OK, ident, 2,
3543 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3544 SILC_STATUS_OK, ident, 1,
3548 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3549 packet->data, packet->len, FALSE);
3550 silc_buffer_free(packet);
3551 silc_buffer_free(idp);
3553 SilcServerEntry entry;
3555 /* Check whether we have this server cached */
3556 entry = silc_idlist_find_server_by_name(server->global_list,
3557 dest_server, TRUE, NULL);
3559 entry = silc_idlist_find_server_by_name(server->local_list,
3560 dest_server, TRUE, NULL);
3563 if (server->server_type != SILC_SERVER && !cmd->pending &&
3564 entry && !entry->motd) {
3565 /* Send to the server */
3569 old_ident = silc_command_get_ident(cmd->payload);
3570 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3571 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3573 silc_server_packet_send(server, entry->connection,
3574 SILC_PACKET_COMMAND, cmd->packet->flags,
3575 tmpbuf->data, tmpbuf->len, TRUE);
3577 /* Reprocess this packet after received reply from router */
3578 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3579 silc_command_get_ident(cmd->payload),
3580 silc_server_command_motd,
3581 silc_server_command_dup(cmd));
3582 cmd->pending = TRUE;
3583 silc_command_set_ident(cmd->payload, old_ident);
3584 silc_buffer_free(tmpbuf);
3588 if (!entry && !cmd->pending && !server->standalone) {
3589 /* Send to the primary router */
3593 old_ident = silc_command_get_ident(cmd->payload);
3594 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3595 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3597 silc_server_packet_send(server, server->router->connection,
3598 SILC_PACKET_COMMAND, cmd->packet->flags,
3599 tmpbuf->data, tmpbuf->len, TRUE);
3601 /* Reprocess this packet after received reply from router */
3602 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3603 silc_command_get_ident(cmd->payload),
3604 silc_server_command_motd,
3605 silc_server_command_dup(cmd));
3606 cmd->pending = TRUE;
3607 silc_command_set_ident(cmd->payload, old_ident);
3608 silc_buffer_free(tmpbuf);
3613 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3614 SILC_STATUS_ERR_NO_SUCH_SERVER);
3618 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3619 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3620 SILC_STATUS_OK, ident, 2,
3624 strlen(entry->motd) : 0);
3625 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3626 packet->data, packet->len, FALSE);
3627 silc_buffer_free(packet);
3628 silc_buffer_free(idp);
3632 silc_server_command_free(cmd);
3635 /* Server side of command UMODE. Client can use this command to set/unset
3636 user mode. Client actually cannot set itself to be as server/router
3637 operator so this can be used only to unset the modes. */
3639 SILC_SERVER_CMD_FUNC(umode)
3641 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3642 SilcServer server = cmd->server;
3643 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3645 unsigned char *tmp_mask;
3647 uint16 ident = silc_command_get_ident(cmd->payload);
3649 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3652 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 2, 2);
3654 /* Get the client's mode mask */
3655 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3657 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3658 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3661 SILC_GET32_MSB(mask, tmp_mask);
3667 if (mask & SILC_UMODE_SERVER_OPERATOR) {
3668 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR)) {
3669 /* Cannot operator mode */
3670 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3671 SILC_STATUS_ERR_PERM_DENIED);
3675 /* Remove the server operator rights */
3676 if (client->mode & SILC_UMODE_SERVER_OPERATOR) {
3677 client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3678 if (client->connection)
3679 server->stat.my_server_ops--;
3680 if (server->server_type == SILC_ROUTER)
3681 server->stat.server_ops--;
3685 if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3686 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
3687 /* Cannot operator mode */
3688 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3689 SILC_STATUS_ERR_PERM_DENIED);
3693 /* Remove the router operator rights */
3694 if (client->mode & SILC_UMODE_ROUTER_OPERATOR) {
3695 client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3696 if (client->connection)
3697 server->stat.my_router_ops--;
3698 if (server->server_type == SILC_ROUTER)
3699 server->stat.router_ops--;
3703 if (mask & SILC_UMODE_GONE) {
3704 client->mode |= SILC_UMODE_GONE;
3706 if (client->mode & SILC_UMODE_GONE)
3707 /* Remove the gone status */
3708 client->mode &= ~SILC_UMODE_GONE;
3711 /* Send UMODE change to primary router */
3712 if (!server->standalone)
3713 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3714 client->id, client->mode);
3716 /* Send command reply to sender */
3717 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3718 SILC_STATUS_OK, ident, 1,
3720 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3721 packet->data, packet->len, FALSE);
3722 silc_buffer_free(packet);
3725 silc_server_command_free(cmd);
3728 /* Checks that client has rights to add or remove channel modes. If any
3729 of the checks fails FALSE is returned. */
3731 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3732 SilcChannelClientEntry client,
3735 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3736 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3738 /* Check whether has rights to change anything */
3739 if (!is_op && !is_fo)
3742 /* Check whether has rights to change everything */
3746 /* We know that client is channel operator, check that they are not
3747 changing anything that requires channel founder rights. Rest of the
3748 modes are available automatically for channel operator. */
3750 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3751 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3752 if (is_op && !is_fo)
3755 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3756 if (is_op && !is_fo)
3761 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3762 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE))
3763 if (is_op && !is_fo)
3766 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3767 if (is_op && !is_fo)
3772 if (mode & SILC_CHANNEL_MODE_CIPHER) {
3773 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER))
3774 if (is_op && !is_fo)
3777 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3778 if (is_op && !is_fo)
3783 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3784 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH))
3785 if (is_op && !is_fo)
3788 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3789 if (is_op && !is_fo)
3797 /* Server side command of CMODE. Changes channel mode */
3799 SILC_SERVER_CMD_FUNC(cmode)
3801 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3802 SilcServer server = cmd->server;
3803 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3804 SilcIDListData idata = (SilcIDListData)client;
3805 SilcChannelID *channel_id;
3806 SilcChannelEntry channel;
3807 SilcChannelClientEntry chl;
3808 SilcBuffer packet, cidp;
3809 unsigned char *tmp, *tmp_id, *tmp_mask;
3810 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3811 uint32 mode_mask, tmp_len, tmp_len2;
3812 uint16 ident = silc_command_get_ident(cmd->payload);
3814 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 2, 7);
3816 /* Get Channel ID */
3817 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3819 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3820 SILC_STATUS_ERR_NO_CHANNEL_ID);
3823 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3825 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3826 SILC_STATUS_ERR_NO_CHANNEL_ID);
3830 /* Get the channel mode mask */
3831 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3833 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3834 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3837 SILC_GET32_MSB(mode_mask, tmp_mask);
3839 /* Get channel entry */
3840 channel = silc_idlist_find_channel_by_id(server->local_list,
3843 channel = silc_idlist_find_channel_by_id(server->global_list,
3846 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3847 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3852 /* Check whether this client is on the channel */
3853 if (!silc_server_client_on_channel(client, channel)) {
3854 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3855 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3859 /* Get entry to the channel user list */
3860 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
3862 /* Check that client has rights to change any requested channel modes */
3863 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3864 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3865 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3870 * Check the modes. Modes that requires nothing special operation are
3874 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3875 /* Channel uses private keys to protect traffic. Client(s) has set the
3876 key locally they want to use, server does not know that key. */
3877 /* Nothing interesting to do here */
3879 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3880 /* The mode is removed and we need to generate and distribute
3881 new channel key. Clients are not using private channel keys
3882 anymore after this. */
3884 /* Re-generate channel key */
3885 if (!silc_server_create_channel_key(server, channel, 0))
3888 /* Send the channel key. This sends it to our local clients and if
3889 we are normal server to our router as well. */
3890 silc_server_send_channel_key(server, NULL, channel,
3891 server->server_type == SILC_ROUTER ?
3892 FALSE : !server->standalone);
3894 cipher = channel->channel_key->cipher->name;
3895 hmac = (char *)silc_hmac_get_name(channel->hmac);
3899 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3900 /* User limit is set on channel */
3903 /* Get user limit */
3904 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3906 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3907 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3908 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3912 SILC_GET32_MSB(user_limit, tmp);
3913 channel->user_limit = user_limit;
3916 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3917 /* User limit mode is unset. Remove user limit */
3918 channel->user_limit = 0;
3921 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3922 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3923 /* Passphrase has been set to channel */
3925 /* Get the passphrase */
3926 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3928 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3929 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3933 /* Save the passphrase */
3934 passphrase = channel->passphrase = strdup(tmp);
3937 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3938 /* Passphrase mode is unset. remove the passphrase */
3939 if (channel->passphrase) {
3940 silc_free(channel->passphrase);
3941 channel->passphrase = NULL;
3946 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3947 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3948 /* Cipher to use protect the traffic */
3949 SilcCipher newkey, oldkey;
3952 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3954 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3955 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3959 /* Delete old cipher and allocate the new one */
3960 if (!silc_cipher_alloc(cipher, &newkey)) {
3961 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3962 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3966 oldkey = channel->channel_key;
3967 channel->channel_key = newkey;
3969 /* Re-generate channel key */
3970 if (!silc_server_create_channel_key(server, channel, 0)) {
3971 /* We don't have new key, revert to old one */
3972 channel->channel_key = oldkey;
3976 /* Remove old channel key for good */
3977 silc_cipher_free(oldkey);
3979 /* Send the channel key. This sends it to our local clients and if
3980 we are normal server to our router as well. */
3981 silc_server_send_channel_key(server, NULL, channel,
3982 server->server_type == SILC_ROUTER ?
3983 FALSE : !server->standalone);
3986 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3987 /* Cipher mode is unset. Remove the cipher and revert back to
3989 SilcCipher newkey, oldkey;
3990 cipher = channel->cipher;
3992 /* Delete old cipher and allocate default one */
3993 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
3994 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3995 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3999 oldkey = channel->channel_key;
4000 channel->channel_key = newkey;
4002 /* Re-generate channel key */
4003 if (!silc_server_create_channel_key(server, channel, 0)) {
4004 /* We don't have new key, revert to old one */
4005 channel->channel_key = oldkey;
4009 /* Remove old channel key for good */
4010 silc_cipher_free(oldkey);
4012 /* Send the channel key. This sends it to our local clients and if
4013 we are normal server to our router as well. */
4014 silc_server_send_channel_key(server, NULL, channel,
4015 server->server_type == SILC_ROUTER ?
4016 FALSE : !server->standalone);
4020 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
4021 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
4022 /* HMAC to use protect the traffic */
4023 unsigned char hash[32];
4027 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4029 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4030 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4034 /* Delete old hmac and allocate the new one */
4035 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4036 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4037 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4041 silc_hmac_free(channel->hmac);
4042 channel->hmac = newhmac;
4044 /* Set the HMAC key out of current channel key. The client must do
4046 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4047 channel->key_len / 8, hash);
4048 silc_hmac_set_key(channel->hmac, hash,
4049 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4050 memset(hash, 0, sizeof(hash));
4053 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4054 /* Hmac mode is unset. Remove the hmac and revert back to
4057 unsigned char hash[32];
4058 hmac = channel->hmac_name;
4060 /* Delete old hmac and allocate default one */
4061 silc_hmac_free(channel->hmac);
4062 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4063 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4064 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4068 silc_hmac_free(channel->hmac);
4069 channel->hmac = newhmac;
4071 /* Set the HMAC key out of current channel key. The client must do
4073 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4074 channel->key_len / 8,
4076 silc_hmac_set_key(channel->hmac, hash,
4077 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4078 memset(hash, 0, sizeof(hash));
4082 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4083 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4084 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4085 /* Set the founder authentication */
4086 SilcAuthPayload auth;
4088 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4090 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4091 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4095 auth = silc_auth_payload_parse(tmp, tmp_len);
4097 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4098 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4102 /* Save the public key */
4103 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
4104 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
4107 channel->founder_method = silc_auth_get_method(auth);
4109 if (channel->founder_method == SILC_AUTH_PASSWORD) {
4110 tmp = silc_auth_get_data(auth, &tmp_len);
4111 channel->founder_passwd =
4112 silc_calloc(tmp_len + 1, sizeof(*channel->founder_passwd));
4113 memcpy(channel->founder_passwd, tmp, tmp_len);
4114 channel->founder_passwd_len = tmp_len;
4116 /* Verify the payload before setting the mode */
4117 if (!silc_auth_verify(auth, channel->founder_method,
4118 channel->founder_key, 0, idata->hash,
4119 client->id, SILC_ID_CLIENT)) {
4120 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4121 SILC_STATUS_ERR_AUTH_FAILED);
4126 silc_auth_payload_free(auth);
4130 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4131 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4132 if (channel->founder_key)
4133 silc_pkcs_public_key_free(channel->founder_key);
4134 if (channel->founder_passwd) {
4135 silc_free(channel->founder_passwd);
4136 channel->founder_passwd = NULL;
4142 /* Finally, set the mode */
4143 channel->mode = mode_mask;
4145 /* Send CMODE_CHANGE notify. */
4146 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4147 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4148 SILC_NOTIFY_TYPE_CMODE_CHANGE, 5,
4149 cidp->data, cidp->len,
4151 cipher, cipher ? strlen(cipher) : 0,
4152 hmac, hmac ? strlen(hmac) : 0,
4153 passphrase, passphrase ?
4154 strlen(passphrase) : 0);
4156 /* Set CMODE notify type to network */
4157 if (!server->standalone)
4158 silc_server_send_notify_cmode(server, server->router->connection,
4159 server->server_type == SILC_ROUTER ?
4160 TRUE : FALSE, channel,
4161 mode_mask, client->id, SILC_ID_CLIENT,
4162 cipher, hmac, passphrase);
4164 /* Send command reply to sender */
4165 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4166 SILC_STATUS_OK, ident, 2,
4167 2, tmp_id, tmp_len2,
4169 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4170 packet->data, packet->len, FALSE);
4172 silc_buffer_free(packet);
4173 silc_free(channel_id);
4174 silc_buffer_free(cidp);
4177 silc_server_command_free(cmd);
4180 /* Server side of CUMODE command. Changes client's mode on a channel. */
4182 SILC_SERVER_CMD_FUNC(cumode)
4184 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4185 SilcServer server = cmd->server;
4186 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4187 SilcIDListData idata = (SilcIDListData)client;
4188 SilcChannelID *channel_id;
4189 SilcClientID *client_id;
4190 SilcChannelEntry channel;
4191 SilcClientEntry target_client;
4192 SilcChannelClientEntry chl;
4193 SilcBuffer packet, idp;
4194 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4195 uint32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4197 uint16 ident = silc_command_get_ident(cmd->payload);
4199 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4201 /* Get Channel ID */
4202 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4204 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4205 SILC_STATUS_ERR_NO_CHANNEL_ID);
4208 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
4210 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4211 SILC_STATUS_ERR_NO_CHANNEL_ID);
4215 /* Get channel entry */
4216 channel = silc_idlist_find_channel_by_id(server->local_list,
4219 channel = silc_idlist_find_channel_by_id(server->global_list,
4222 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4223 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4228 /* Check whether sender is on the channel */
4229 if (!silc_server_client_on_channel(client, channel)) {
4230 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4231 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4235 /* Check that client has rights to change other's rights */
4236 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4237 sender_mask = chl->mode;
4239 /* Get the target client's channel mode mask */
4240 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4242 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4243 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4246 SILC_GET32_MSB(target_mask, tmp_mask);
4248 /* Get target Client ID */
4249 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4251 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4252 SILC_STATUS_ERR_NO_CLIENT_ID);
4255 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
4257 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4258 SILC_STATUS_ERR_NO_CLIENT_ID);
4262 /* Get target client's entry */
4263 target_client = silc_idlist_find_client_by_id(server->local_list,
4264 client_id, TRUE, NULL);
4265 if (!target_client) {
4266 target_client = silc_idlist_find_client_by_id(server->global_list,
4267 client_id, TRUE, NULL);
4270 if (target_client != client &&
4271 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4272 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4273 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4274 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4278 /* Check whether target client is on the channel */
4279 if (target_client != client) {
4280 if (!silc_server_client_on_channel(target_client, channel)) {
4281 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4282 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4286 /* Get entry to the channel user list */
4287 silc_hash_table_find(channel->user_list, target_client, NULL,
4295 /* If the target client is founder, no one else can change their mode
4297 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4298 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4299 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4303 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4304 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4305 /* The client tries to claim the founder rights. */
4306 unsigned char *tmp_auth;
4307 uint32 tmp_auth_len, auth_len;
4310 if (target_client != client) {
4311 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4312 SILC_STATUS_ERR_NOT_YOU);
4316 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4317 !channel->founder_key || !idata->public_key ||
4318 !silc_pkcs_public_key_compare(channel->founder_key,
4319 idata->public_key)) {
4320 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4321 SILC_STATUS_ERR_NOT_YOU);
4325 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4327 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4328 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4332 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4333 (void *)channel->founder_passwd : (void *)channel->founder_key);
4334 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4335 channel->founder_passwd_len : 0);
4337 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4338 channel->founder_method, auth, auth_len,
4339 idata->hash, client->id, SILC_ID_CLIENT)) {
4340 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4341 SILC_STATUS_ERR_AUTH_FAILED);
4345 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4349 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4350 if (target_client == client) {
4351 /* Remove channel founder rights from itself */
4352 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4355 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4356 SILC_STATUS_ERR_NOT_YOU);
4362 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4363 /* Promote to operator */
4364 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4365 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4366 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4367 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4368 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4372 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4376 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4377 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4378 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4379 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4380 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4384 /* Demote to normal user */
4385 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4390 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4391 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4393 /* Send notify to channel, notify only if mode was actually changed. */
4395 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4396 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4397 idp->data, idp->len,
4401 /* Set CUMODE notify type to network */
4402 if (!server->standalone)
4403 silc_server_send_notify_cumode(server, server->router->connection,
4404 server->server_type == SILC_ROUTER ?
4405 TRUE : FALSE, channel,
4406 target_mask, client->id,
4411 /* Send command reply to sender */
4412 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4413 SILC_STATUS_OK, ident, 3,
4415 3, tmp_ch_id, tmp_ch_len,
4416 4, tmp_id, tmp_len);
4417 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4418 packet->data, packet->len, FALSE);
4420 silc_buffer_free(packet);
4421 silc_free(channel_id);
4422 silc_free(client_id);
4423 silc_buffer_free(idp);
4426 silc_server_command_free(cmd);
4429 /* Server side of KICK command. Kicks client out of channel. */
4431 SILC_SERVER_CMD_FUNC(kick)
4433 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4434 SilcServer server = cmd->server;
4435 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4436 SilcClientEntry target_client;
4437 SilcChannelID *channel_id;
4438 SilcClientID *client_id;
4439 SilcChannelEntry channel;
4440 SilcChannelClientEntry chl;
4442 uint32 tmp_len, target_idp_len;
4443 unsigned char *tmp, *comment, *target_idp;
4445 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4447 /* Get Channel ID */
4448 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4450 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4451 SILC_STATUS_ERR_NO_CHANNEL_ID);
4454 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
4456 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4457 SILC_STATUS_ERR_NO_CHANNEL_ID);
4461 /* Get channel entry */
4462 channel = silc_idlist_find_channel_by_id(server->local_list,
4465 channel = silc_idlist_find_channel_by_id(server->local_list,
4468 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4469 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4474 /* Check whether sender is on the channel */
4475 if (!silc_server_client_on_channel(client, channel)) {
4476 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4477 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4481 /* Check that the kicker is channel operator or channel founder */
4482 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4483 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4484 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4485 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4489 /* Get target Client ID */
4490 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4492 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4493 SILC_STATUS_ERR_NO_CLIENT_ID);
4496 client_id = silc_id_payload_parse_id(target_idp, target_idp_len);
4498 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4499 SILC_STATUS_ERR_NO_CLIENT_ID);
4503 /* Get target client's entry */
4504 target_client = silc_idlist_find_client_by_id(server->local_list,
4505 client_id, TRUE, NULL);
4506 if (!target_client) {
4507 target_client = silc_idlist_find_client_by_id(server->global_list,
4508 client_id, TRUE, NULL);
4511 /* Check that the target client is not channel founder. Channel founder
4512 cannot be kicked from the channel. */
4513 silc_hash_table_find(channel->user_list, target_client, NULL, (void *)&chl);
4514 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4515 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4516 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4520 /* Check whether target client is on the channel */
4521 if (!silc_server_client_on_channel(target_client, channel)) {
4522 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4523 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4529 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4533 /* Send command reply to sender */
4534 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4537 /* Send KICKED notify to local clients on the channel */
4538 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4539 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4540 SILC_NOTIFY_TYPE_KICKED, 3,
4541 target_idp, target_idp_len,
4542 comment, comment ? strlen(comment) : 0,
4543 idp->data, idp->len);
4544 silc_buffer_free(idp);
4546 /* Remove the client from the channel. If the channel does not exist
4547 after removing the client then the client kicked itself off the channel
4548 and we don't have to send anything after that. */
4549 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4550 target_client, FALSE))
4553 /* Send KICKED notify to primary route */
4554 if (!server->standalone)
4555 silc_server_send_notify_kicked(server, server->router->connection,
4556 server->server_type == SILC_ROUTER ?
4557 TRUE : FALSE, channel,
4558 target_client->id, client->id, comment);
4560 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4561 /* Re-generate channel key */
4562 if (!silc_server_create_channel_key(server, channel, 0))
4565 /* Send the channel key to the channel. The key of course is not sent
4566 to the client who was kicked off the channel. */
4567 silc_server_send_channel_key(server, target_client->connection, channel,
4568 server->server_type == SILC_ROUTER ?
4569 FALSE : !server->standalone);
4573 silc_server_command_free(cmd);
4576 /* Server side of OPER command. Client uses this comand to obtain server
4577 operator privileges to this server/router. */
4579 SILC_SERVER_CMD_FUNC(oper)
4581 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4582 SilcServer server = cmd->server;
4583 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4584 unsigned char *username, *auth;
4586 SilcServerConfigSectionAdmin *admin;
4587 SilcIDListData idata = (SilcIDListData)client;
4589 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4591 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4594 /* Get the username */
4595 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4597 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4598 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4602 /* Get the admin configuration */
4603 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4604 username, client->nickname);
4606 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4607 username, client->nickname);
4609 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4610 SILC_STATUS_ERR_AUTH_FAILED);
4615 /* Get the authentication payload */
4616 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4618 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4619 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4623 /* Verify the authentication data */
4624 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4625 admin->auth_data, admin->auth_data_len,
4626 idata->hash, client->id, SILC_ID_CLIENT)) {
4627 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4628 SILC_STATUS_ERR_AUTH_FAILED);
4632 /* Client is now server operator */
4633 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4635 /* Update statistics */
4636 if (client->connection)
4637 server->stat.my_server_ops++;
4638 if (server->server_type == SILC_ROUTER)
4639 server->stat.server_ops++;
4641 /* Send UMODE change to primary router */
4642 if (!server->standalone)
4643 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4644 client->id, client->mode);
4646 /* Send reply to the sender */
4647 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4651 silc_server_command_free(cmd);
4654 /* Server side of SILCOPER command. Client uses this comand to obtain router
4655 operator privileges to this router. */
4657 SILC_SERVER_CMD_FUNC(silcoper)
4659 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4660 SilcServer server = cmd->server;
4661 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4662 unsigned char *username, *auth;
4664 SilcServerConfigSectionAdmin *admin;
4665 SilcIDListData idata = (SilcIDListData)client;
4667 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4669 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4672 if (server->server_type != SILC_ROUTER) {
4673 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4674 SILC_STATUS_ERR_AUTH_FAILED);
4678 /* Get the username */
4679 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4681 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4682 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4686 /* Get the admin configuration */
4687 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4688 username, client->nickname);
4690 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4691 username, client->nickname);
4693 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4694 SILC_STATUS_ERR_AUTH_FAILED);
4699 /* Get the authentication payload */
4700 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4702 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4703 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4707 /* Verify the authentication data */
4708 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4709 admin->auth_data, admin->auth_data_len,
4710 idata->hash, client->id, SILC_ID_CLIENT)) {
4711 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4712 SILC_STATUS_ERR_AUTH_FAILED);
4716 /* Client is now router operator */
4717 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4719 /* Update statistics */
4720 if (client->connection)
4721 server->stat.my_router_ops++;
4722 if (server->server_type == SILC_ROUTER)
4723 server->stat.router_ops++;
4725 /* Send UMODE change to primary router */
4726 if (!server->standalone)
4727 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4728 client->id, client->mode);
4730 /* Send reply to the sender */
4731 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4735 silc_server_command_free(cmd);
4738 /* Server side command of CONNECT. Connects us to the specified remote
4739 server or router. */
4741 SILC_SERVER_CMD_FUNC(connect)
4743 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4744 SilcServer server = cmd->server;
4745 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4746 unsigned char *tmp, *host;
4748 uint32 port = SILC_PORT;
4750 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CONNECT, cmd, 1, 2);
4752 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4755 /* Check whether client has the permissions. */
4756 if (client->mode == SILC_UMODE_NONE) {
4757 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4758 SILC_STATUS_ERR_NO_SERVER_PRIV);
4762 if (server->server_type == SILC_ROUTER &&
4763 client->mode & SILC_UMODE_SERVER_OPERATOR) {
4764 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4765 SILC_STATUS_ERR_NO_ROUTER_PRIV);
4769 /* Get the remote server */
4770 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4772 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4773 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4778 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4780 SILC_GET32_MSB(port, tmp);
4782 /* Create the connection. It is done with timeout and is async. */
4783 silc_server_create_connection(server, host, port);
4785 /* Send reply to the sender */
4786 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4790 silc_server_command_free(cmd);
4793 /* Server side of command BAN. This is used to manage the ban list of the
4794 channel. To add clients and remove clients from the ban list. */
4796 SILC_SERVER_CMD_FUNC(ban)
4798 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4799 SilcServer server = cmd->server;
4800 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4802 SilcChannelEntry channel;
4803 SilcChannelClientEntry chl;
4804 SilcChannelID *channel_id = NULL;
4805 unsigned char *id, *add, *del;
4806 uint32 id_len, tmp_len;
4807 uint16 ident = silc_command_get_ident(cmd->payload);
4809 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4812 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4814 /* Get Channel ID */
4815 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4817 channel_id = silc_id_payload_parse_id(id, id_len);
4819 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4820 SILC_STATUS_ERR_NO_CHANNEL_ID);
4825 /* Get channel entry. The server must know about the channel since the
4826 client is expected to be on the channel. */
4827 channel = silc_idlist_find_channel_by_id(server->local_list,
4830 channel = silc_idlist_find_channel_by_id(server->global_list,
4833 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4834 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4839 /* Check whether this client is on the channel */
4840 if (!silc_server_client_on_channel(client, channel)) {
4841 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4842 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4846 /* Get entry to the channel user list */
4847 if (!silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl)) {
4848 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4849 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4853 /* The client must be at least channel operator. */
4854 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4855 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4856 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4860 /* Get the new ban and add it to the ban list */
4861 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4863 if (!channel->ban_list)
4864 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4866 channel->ban_list = silc_realloc(channel->ban_list,
4867 sizeof(*channel->ban_list) *
4869 strlen(channel->ban_list) + 2));
4870 if (add[tmp_len - 1] == ',')
4871 add[tmp_len - 1] = '\0';
4873 strncat(channel->ban_list, add, tmp_len);
4874 strncat(channel->ban_list, ",", 1);
4877 /* Get the ban to be removed and remove it from the list */
4878 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4879 if (del && channel->ban_list) {
4880 char *start, *end, *n;
4882 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4883 silc_free(channel->ban_list);
4884 channel->ban_list = NULL;
4886 start = strstr(channel->ban_list, del);
4887 if (start && strlen(start) >= tmp_len) {
4888 end = start + tmp_len;
4889 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4890 strncat(n, channel->ban_list, start - channel->ban_list);
4891 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4893 silc_free(channel->ban_list);
4894 channel->ban_list = n;
4899 /* Send the BAN notify type to our primary router. */
4900 if (!server->standalone && (add || del))
4901 silc_server_send_notify_ban(server, server->router->connection,
4902 server->server_type == SILC_ROUTER ?
4903 TRUE : FALSE, channel, add, del);
4905 /* Send the reply back to the client */
4907 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4908 SILC_STATUS_OK, ident, 2,
4910 3, channel->ban_list,
4912 strlen(channel->ban_list) -1 : 0);
4913 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4914 packet->data, packet->len, FALSE);
4916 silc_buffer_free(packet);
4919 silc_free(channel_id);
4920 silc_server_command_free(cmd);
4923 /* Server side command of CLOSE. Closes connection to a specified server. */
4925 SILC_SERVER_CMD_FUNC(close)
4927 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4928 SilcServer server = cmd->server;
4929 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4930 SilcServerEntry server_entry;
4931 SilcSocketConnection sock;
4934 unsigned char *name;
4935 uint32 port = SILC_PORT;
4937 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CLOSE, cmd, 1, 2);
4939 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4942 /* Check whether client has the permissions. */
4943 if (client->mode == SILC_UMODE_NONE) {
4944 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4945 SILC_STATUS_ERR_NO_SERVER_PRIV);
4949 /* Get the remote server */
4950 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4952 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4953 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4958 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4960 SILC_GET32_MSB(port, tmp);
4962 server_entry = silc_idlist_find_server_by_conn(server->local_list,
4963 name, port, FALSE, NULL);
4965 server_entry = silc_idlist_find_server_by_conn(server->global_list,
4966 name, port, FALSE, NULL);
4967 if (!server_entry) {
4968 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4969 SILC_STATUS_ERR_NO_SERVER_ID);
4973 /* Send reply to the sender */
4974 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4977 /* Close the connection to the server */
4978 sock = (SilcSocketConnection)server_entry->connection;
4980 /* If we shutdown primary router connection manually then don't trigger
4981 any reconnect or backup router connections, by setting the router
4983 if (server->router == server_entry) {
4984 server->id_entry->router = NULL;
4985 server->router = NULL;
4986 server->standalone = TRUE;
4988 silc_server_free_sock_user_data(server, sock, NULL);
4989 silc_server_close_connection(server, sock);
4992 silc_server_command_free(cmd);
4995 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4996 active connections. */
4998 SILC_SERVER_CMD_FUNC(shutdown)
5000 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5001 SilcServer server = cmd->server;
5002 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5004 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
5006 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5009 /* Check whether client has the permission. */
5010 if (client->mode == SILC_UMODE_NONE) {
5011 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
5012 SILC_STATUS_ERR_NO_SERVER_PRIV);
5016 /* Send reply to the sender */
5017 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
5020 /* Then, gracefully, or not, bring the server down. */
5021 silc_server_stop(server);
5025 silc_server_command_free(cmd);
5028 /* Server side command of LEAVE. Removes client from a channel. */
5030 SILC_SERVER_CMD_FUNC(leave)
5032 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5033 SilcServer server = cmd->server;
5034 SilcSocketConnection sock = cmd->sock;
5035 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
5036 SilcChannelID *id = NULL;
5037 SilcChannelEntry channel;
5041 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
5043 /* Get Channel ID */
5044 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
5046 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5047 SILC_STATUS_ERR_NO_CHANNEL_ID);
5050 id = silc_id_payload_parse_id(tmp, len);
5052 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5053 SILC_STATUS_ERR_NO_CHANNEL_ID);
5057 /* Get channel entry */
5058 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5060 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5062 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5063 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5068 /* Check whether this client is on the channel */
5069 if (!silc_server_client_on_channel(id_entry, channel)) {
5070 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5071 SILC_STATUS_ERR_NOT_ON_CHANNEL);
5075 /* Notify routers that they should remove this client from their list
5076 of clients on the channel. Send LEAVE notify type. */
5077 if (!server->standalone)
5078 silc_server_send_notify_leave(server, server->router->connection,
5079 server->server_type == SILC_ROUTER ?
5080 TRUE : FALSE, channel, id_entry->id);
5082 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5085 /* Remove client from channel */
5086 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5088 /* If the channel does not exist anymore we won't send anything */
5091 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5092 /* Re-generate channel key */
5093 if (!silc_server_create_channel_key(server, channel, 0))
5096 /* Send the channel key */
5097 silc_server_send_channel_key(server, NULL, channel,
5098 server->server_type == SILC_ROUTER ?
5099 FALSE : !server->standalone);
5104 silc_server_command_free(cmd);
5107 /* Server side of command USERS. Resolves clients and their USERS currently
5108 joined on the requested channel. The list of Client ID's and their modes
5109 on the channel is sent back. */
5111 SILC_SERVER_CMD_FUNC(users)
5113 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5114 SilcServer server = cmd->server;
5115 SilcChannelEntry channel;
5116 SilcChannelID *id = NULL;
5117 SilcBuffer packet, idp;
5118 unsigned char *channel_id;
5119 uint32 channel_id_len;
5120 SilcBuffer client_id_list;
5121 SilcBuffer client_mode_list;
5122 unsigned char lc[4];
5123 uint32 list_count = 0;
5124 uint16 ident = silc_command_get_ident(cmd->payload);
5127 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5129 /* Get Channel ID */
5130 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5132 /* Get channel name */
5133 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5135 if (!channel_id && !channel_name) {
5136 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5137 SILC_STATUS_ERR_NO_CHANNEL_ID);
5142 id = silc_id_payload_parse_id(channel_id, channel_id_len);
5144 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5145 SILC_STATUS_ERR_NO_CHANNEL_ID);
5150 /* If we are server and we don't know about this channel we will send
5151 the command to our router. If we know about the channel then we also
5152 have the list of users already. */
5154 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5156 channel = silc_idlist_find_channel_by_name(server->local_list,
5157 channel_name, NULL);
5159 if (!channel || channel->disabled) {
5160 if (server->server_type != SILC_ROUTER && !server->standalone &&
5164 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5165 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5167 /* Send USERS command */
5168 silc_server_packet_send(server, server->router->connection,
5169 SILC_PACKET_COMMAND, cmd->packet->flags,
5170 tmpbuf->data, tmpbuf->len, TRUE);
5172 /* Reprocess this packet after received reply */
5173 silc_server_command_pending(server, SILC_COMMAND_USERS,
5174 silc_command_get_ident(cmd->payload),
5175 silc_server_command_users,
5176 silc_server_command_dup(cmd));
5177 cmd->pending = TRUE;
5178 silc_command_set_ident(cmd->payload, ident);
5179 silc_buffer_free(tmpbuf);
5184 /* Check the global list as well. */
5186 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5188 channel = silc_idlist_find_channel_by_name(server->global_list,
5189 channel_name, NULL);
5191 /* Channel really does not exist */
5192 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5193 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5198 /* If the channel is private or secret do not send anything, unless the
5199 user requesting this command is on the channel. */
5200 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5201 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5202 && !silc_server_client_on_channel(cmd->sock->user_data, channel)) {
5203 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5204 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5209 (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
5210 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5211 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5216 /* Get the users list */
5217 silc_server_get_users_on_channel(server, channel, &client_id_list,
5218 &client_mode_list, &list_count);
5221 SILC_PUT32_MSB(list_count, lc);
5224 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5225 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5226 SILC_STATUS_OK, ident, 4,
5227 2, idp->data, idp->len,
5229 4, client_id_list->data,
5230 client_id_list->len,
5231 5, client_mode_list->data,
5232 client_mode_list->len);
5233 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5234 packet->data, packet->len, FALSE);
5236 silc_buffer_free(idp);
5237 silc_buffer_free(packet);
5238 silc_buffer_free(client_id_list);
5239 silc_buffer_free(client_mode_list);
5243 silc_server_command_free(cmd);
5246 /* Server side of command GETKEY. This fetches the client's public key
5247 from the server where to the client is connected. */
5249 SILC_SERVER_CMD_FUNC(getkey)
5251 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5252 SilcServer server = cmd->server;
5254 SilcClientEntry client;
5255 SilcServerEntry server_entry;
5256 SilcClientID *client_id = NULL;
5257 SilcServerID *server_id = NULL;
5258 SilcIDPayload idp = NULL;
5259 uint16 ident = silc_command_get_ident(cmd->payload);
5260 unsigned char *tmp, *pkdata;
5261 uint32 tmp_len, pklen;
5262 SilcBuffer pk = NULL;
5264 SilcPublicKey public_key;
5266 SILC_LOG_DEBUG(("Start"));
5268 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5270 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5271 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5274 idp = silc_id_payload_parse(tmp, tmp_len);
5276 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5277 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5281 id_type = silc_id_payload_get_type(idp);
5282 if (id_type == SILC_ID_CLIENT) {
5283 client_id = silc_id_payload_get_id(idp);
5285 /* If the client is not found from local list there is no chance it
5286 would be locally connected client so send the command further. */
5287 client = silc_idlist_find_client_by_id(server->local_list,
5288 client_id, TRUE, NULL);
5290 client = silc_idlist_find_client_by_id(server->global_list,
5291 client_id, TRUE, NULL);
5293 if ((!client && !cmd->pending && !server->standalone) ||
5294 (client && !client->connection && !cmd->pending) ||
5295 (client && !client->data.public_key && !cmd->pending)) {
5298 SilcSocketConnection dest_sock;
5300 dest_sock = silc_server_get_client_route(server, NULL, 0,
5305 old_ident = silc_command_get_ident(cmd->payload);
5306 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5307 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5309 silc_server_packet_send(server, dest_sock,
5310 SILC_PACKET_COMMAND, cmd->packet->flags,
5311 tmpbuf->data, tmpbuf->len, TRUE);
5313 /* Reprocess this packet after received reply from router */
5314 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5315 silc_command_get_ident(cmd->payload),
5316 silc_server_command_getkey,
5317 silc_server_command_dup(cmd));
5318 cmd->pending = TRUE;
5319 silc_command_set_ident(cmd->payload, old_ident);
5320 silc_buffer_free(tmpbuf);
5325 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5326 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5330 /* The client is locally connected, just get the public key and
5331 send it back. If they key does not exist then do not send it,
5332 send just OK reply */
5333 public_key = client->data.public_key;
5338 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5339 pk = silc_buffer_alloc(4 + tmp_len);
5340 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5341 silc_buffer_format(pk,
5342 SILC_STR_UI_SHORT(tmp_len),
5343 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5344 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5350 } else if (id_type == SILC_ID_SERVER) {
5351 server_id = silc_id_payload_get_id(idp);
5353 /* If the server is not found from local list there is no chance it
5354 would be locally connected server so send the command further. */
5355 server_entry = silc_idlist_find_server_by_id(server->local_list,
5356 server_id, TRUE, NULL);
5358 server_entry = silc_idlist_find_server_by_id(server->global_list,
5359 server_id, TRUE, NULL);
5361 if (server_entry != server->id_entry &&
5362 ((!server_entry && !cmd->pending && !server->standalone) ||
5363 (server_entry && !server_entry->connection && !cmd->pending &&
5364 !server->standalone) ||
5365 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5366 !server->standalone))) {
5370 old_ident = silc_command_get_ident(cmd->payload);
5371 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5372 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5374 silc_server_packet_send(server, server->router->connection,
5375 SILC_PACKET_COMMAND, cmd->packet->flags,
5376 tmpbuf->data, tmpbuf->len, TRUE);
5378 /* Reprocess this packet after received reply from router */
5379 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5380 silc_command_get_ident(cmd->payload),
5381 silc_server_command_getkey,
5382 silc_server_command_dup(cmd));
5383 cmd->pending = TRUE;
5384 silc_command_set_ident(cmd->payload, old_ident);
5385 silc_buffer_free(tmpbuf);
5389 if (!server_entry) {
5390 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5391 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5395 /* If they key does not exist then do not send it, send just OK reply */
5396 public_key = (!server_entry->data.public_key ?
5397 (server_entry == server->id_entry ? server->public_key :
5398 NULL) : server_entry->data.public_key);
5403 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5404 pk = silc_buffer_alloc(4 + tmp_len);
5405 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5406 silc_buffer_format(pk,
5407 SILC_STR_UI_SHORT(tmp_len),
5408 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5409 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5419 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5420 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5421 SILC_STATUS_OK, ident,
5425 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5426 packet->data, packet->len, FALSE);
5427 silc_buffer_free(packet);
5430 silc_buffer_free(pk);
5434 silc_id_payload_free(idp);
5435 silc_free(client_id);
5436 silc_free(server_id);
5437 silc_server_command_free(cmd);