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 = entry->user_count;
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);
3190 channel->user_count++;
3192 /* Get users on the channel */
3193 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3196 /* Encode Client ID Payload of the original client who wants to join */
3197 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3199 /* Encode command reply packet */
3200 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3201 SILC_PUT32_MSB(channel->mode, mode);
3202 SILC_PUT32_MSB(created, tmp2);
3203 SILC_PUT32_MSB(user_count, tmp3);
3205 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3206 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3207 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
3208 strlen(channel->channel_key->
3210 channel->channel_key->cipher->name,
3211 channel->key_len / 8, channel->key);
3216 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3217 SILC_STATUS_OK, ident, 13,
3218 2, channel->channel_name,
3219 strlen(channel->channel_name),
3220 3, chidp->data, chidp->len,
3221 4, clidp->data, clidp->len,
3224 7, keyp ? keyp->data : NULL,
3225 keyp ? keyp->len : 0,
3226 8, channel->ban_list,
3228 strlen(channel->ban_list) : 0,
3229 9, channel->invite_list,
3230 channel->invite_list ?
3231 strlen(channel->invite_list) : 0,
3234 strlen(channel->topic) : 0,
3235 11, silc_hmac_get_name(channel->hmac),
3236 strlen(silc_hmac_get_name(channel->
3239 13, user_list->data, user_list->len,
3240 14, mode_list->data,
3243 /* Send command reply */
3244 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3245 reply->data, reply->len, FALSE);
3247 /* Send JOIN notify to locally connected clients on the channel. If
3248 we are normal server then router will send or have sent JOIN notify
3249 already. However since we've added the client already to our channel
3250 we'll ignore it (in packet_receive.c) so we must send it here. If
3251 we are router then this will send it to local clients and local
3253 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3254 SILC_NOTIFY_TYPE_JOIN, 2,
3255 clidp->data, clidp->len,
3256 chidp->data, chidp->len);
3258 if (!cmd->pending) {
3259 /* Send JOIN notify packet to our primary router */
3260 if (!server->standalone)
3261 silc_server_send_notify_join(server, server->router->connection,
3262 server->server_type == SILC_ROUTER ?
3263 TRUE : FALSE, channel, client->id);
3266 /* Distribute the channel key to all backup routers. */
3267 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3268 keyp->data, keyp->len, FALSE, TRUE);
3271 /* If client became founder by providing correct founder auth data
3272 notify the mode change to the channel. */
3274 SILC_PUT32_MSB(chl->mode, mode);
3275 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3276 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3277 clidp->data, clidp->len,
3278 mode, 4, clidp->data, clidp->len);
3280 /* Set CUMODE notify type to network */
3281 if (!server->standalone)
3282 silc_server_send_notify_cumode(server, server->router->connection,
3283 server->server_type == SILC_ROUTER ?
3284 TRUE : FALSE, channel,
3285 chl->mode, client->id, SILC_ID_CLIENT,
3289 silc_buffer_free(reply);
3290 silc_buffer_free(clidp);
3291 silc_buffer_free(chidp);
3292 silc_buffer_free(keyp);
3293 silc_buffer_free(user_list);
3294 silc_buffer_free(mode_list);
3297 silc_free(passphrase);
3300 /* Server side of command JOIN. Joins client into requested channel. If
3301 the channel does not exist it will be created. */
3303 SILC_SERVER_CMD_FUNC(join)
3305 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3306 SilcServer server = cmd->server;
3307 unsigned char *auth;
3308 uint32 tmp_len, auth_len;
3309 char *tmp, *channel_name = NULL, *cipher, *hmac;
3310 SilcChannelEntry channel;
3312 bool created = FALSE, create_key = TRUE;
3313 SilcClientID *client_id;
3315 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3317 /* Get channel name */
3318 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3320 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3321 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3327 channel_name[255] = '\0';
3329 if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
3330 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3331 SILC_STATUS_ERR_BAD_CHANNEL);
3335 /* Get Client ID of the client who is joining to the channel */
3336 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3338 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3339 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3342 client_id = silc_id_payload_parse_id(tmp, tmp_len);
3344 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3345 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3349 /* Get cipher, hmac name and auth payload */
3350 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3351 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3352 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3354 /* See if the channel exists */
3355 channel = silc_idlist_find_channel_by_name(server->local_list,
3356 channel_name, NULL);
3358 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3359 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3360 client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
3362 if (!channel || channel->disabled) {
3363 /* Channel not found */
3365 /* If we are standalone server we don't have a router, we just create
3366 the channel by ourselves. */
3367 if (server->standalone) {
3368 channel = silc_server_create_new_channel(server, server->id, cipher,
3369 hmac, channel_name, TRUE);
3371 silc_server_command_send_status_reply(
3372 cmd, SILC_COMMAND_JOIN,
3373 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3377 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3383 /* The channel does not exist on our server. If we are normal server
3384 we will send JOIN command to our router which will handle the
3385 joining procedure (either creates the channel if it doesn't exist
3386 or joins the client to it). */
3387 if (server->server_type != SILC_ROUTER) {
3391 /* If this is pending command callback then we've resolved
3392 it and it didn't work, return since we've notified the
3393 client already in the command reply callback. */
3397 old_ident = silc_command_get_ident(cmd->payload);
3398 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3399 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3401 /* Send JOIN command to our router */
3402 silc_server_packet_send(server, (SilcSocketConnection)
3403 server->router->connection,
3404 SILC_PACKET_COMMAND, cmd->packet->flags,
3405 tmpbuf->data, tmpbuf->len, TRUE);
3407 /* Reprocess this packet after received reply from router */
3408 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3409 silc_command_get_ident(cmd->payload),
3410 silc_server_command_join,
3411 silc_server_command_dup(cmd));
3412 cmd->pending = TRUE;
3413 silc_command_set_ident(cmd->payload, old_ident);
3414 silc_buffer_free(tmpbuf);
3418 /* We are router and the channel does not seem exist so we will check
3419 our global list as well for the channel. */
3420 channel = silc_idlist_find_channel_by_name(server->global_list,
3421 channel_name, NULL);
3423 /* Channel really does not exist, create it */
3424 channel = silc_server_create_new_channel(server, server->id, cipher,
3425 hmac, channel_name, TRUE);
3427 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3428 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3432 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3440 /* Channel not found */
3442 /* If the command came from router and we are normal server then
3443 something went wrong with the joining as the channel was not found.
3444 We can't do anything else but ignore this. */
3445 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3446 server->server_type != SILC_ROUTER)
3449 /* We are router and the channel does not seem exist so we will check
3450 our global list as well for the channel. */
3451 channel = silc_idlist_find_channel_by_name(server->global_list,
3452 channel_name, NULL);
3454 /* Channel really does not exist, create it */
3455 channel = silc_server_create_new_channel(server, server->id, cipher,
3456 hmac, channel_name, TRUE);
3458 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3459 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3463 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3470 /* Check whether the channel was created by our router */
3471 if (cmd->pending && context2) {
3472 SilcServerCommandReplyContext reply =
3473 (SilcServerCommandReplyContext)context2;
3475 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3476 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3477 SILC_GET32_MSB(created, tmp);
3478 if (silc_argument_get_arg_type(reply->args, 7, NULL))
3479 create_key = FALSE; /* Router returned the key already */
3482 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
3483 !silc_hash_table_count(channel->user_list))
3487 /* If the channel does not have global users and is also empty the client
3488 will be the channel founder and operator. */
3489 if (!channel->global_users && !silc_hash_table_count(channel->user_list))
3490 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3492 /* Join to the channel */
3493 silc_server_command_join_channel(server, cmd, channel, client_id,
3494 created, create_key, umode,
3497 silc_free(client_id);
3500 silc_server_command_free(cmd);
3503 /* Server side of command MOTD. Sends server's current "message of the
3504 day" to the client. */
3506 SILC_SERVER_CMD_FUNC(motd)
3508 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3509 SilcServer server = cmd->server;
3510 SilcBuffer packet, idp;
3511 char *motd, *dest_server;
3513 uint16 ident = silc_command_get_ident(cmd->payload);
3515 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3517 /* Get server name */
3518 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3520 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3521 SILC_STATUS_ERR_NO_SUCH_SERVER);
3525 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3528 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3530 if (server->config && server->config->server_info &&
3531 server->config->server_info->motd_file) {
3533 motd = silc_file_readfile(server->config->server_info->motd_file, &motd_len);
3538 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3539 SILC_STATUS_OK, ident, 2,
3544 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3545 SILC_STATUS_OK, ident, 1,
3549 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3550 packet->data, packet->len, FALSE);
3551 silc_buffer_free(packet);
3552 silc_buffer_free(idp);
3554 SilcServerEntry entry;
3556 /* Check whether we have this server cached */
3557 entry = silc_idlist_find_server_by_name(server->global_list,
3558 dest_server, TRUE, NULL);
3560 entry = silc_idlist_find_server_by_name(server->local_list,
3561 dest_server, TRUE, NULL);
3564 if (server->server_type != SILC_SERVER && !cmd->pending &&
3565 entry && !entry->motd) {
3566 /* Send to the server */
3570 old_ident = silc_command_get_ident(cmd->payload);
3571 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3572 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3574 silc_server_packet_send(server, entry->connection,
3575 SILC_PACKET_COMMAND, cmd->packet->flags,
3576 tmpbuf->data, tmpbuf->len, TRUE);
3578 /* Reprocess this packet after received reply from router */
3579 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3580 silc_command_get_ident(cmd->payload),
3581 silc_server_command_motd,
3582 silc_server_command_dup(cmd));
3583 cmd->pending = TRUE;
3584 silc_command_set_ident(cmd->payload, old_ident);
3585 silc_buffer_free(tmpbuf);
3589 if (!entry && !cmd->pending && !server->standalone) {
3590 /* Send to the primary router */
3594 old_ident = silc_command_get_ident(cmd->payload);
3595 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3596 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3598 silc_server_packet_send(server, server->router->connection,
3599 SILC_PACKET_COMMAND, cmd->packet->flags,
3600 tmpbuf->data, tmpbuf->len, TRUE);
3602 /* Reprocess this packet after received reply from router */
3603 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3604 silc_command_get_ident(cmd->payload),
3605 silc_server_command_motd,
3606 silc_server_command_dup(cmd));
3607 cmd->pending = TRUE;
3608 silc_command_set_ident(cmd->payload, old_ident);
3609 silc_buffer_free(tmpbuf);
3614 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3615 SILC_STATUS_ERR_NO_SUCH_SERVER);
3619 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3620 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3621 SILC_STATUS_OK, ident, 2,
3625 strlen(entry->motd) : 0);
3626 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3627 packet->data, packet->len, FALSE);
3628 silc_buffer_free(packet);
3629 silc_buffer_free(idp);
3633 silc_server_command_free(cmd);
3636 /* Server side of command UMODE. Client can use this command to set/unset
3637 user mode. Client actually cannot set itself to be as server/router
3638 operator so this can be used only to unset the modes. */
3640 SILC_SERVER_CMD_FUNC(umode)
3642 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3643 SilcServer server = cmd->server;
3644 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3646 unsigned char *tmp_mask;
3648 uint16 ident = silc_command_get_ident(cmd->payload);
3650 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3653 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 2, 2);
3655 /* Get the client's mode mask */
3656 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3658 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3659 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3662 SILC_GET32_MSB(mask, tmp_mask);
3668 if (mask & SILC_UMODE_SERVER_OPERATOR) {
3669 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR)) {
3670 /* Cannot operator mode */
3671 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3672 SILC_STATUS_ERR_PERM_DENIED);
3676 /* Remove the server operator rights */
3677 if (client->mode & SILC_UMODE_SERVER_OPERATOR) {
3678 client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3679 if (client->connection)
3680 server->stat.my_server_ops--;
3681 if (server->server_type == SILC_ROUTER)
3682 server->stat.server_ops--;
3686 if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3687 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
3688 /* Cannot operator mode */
3689 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3690 SILC_STATUS_ERR_PERM_DENIED);
3694 /* Remove the router operator rights */
3695 if (client->mode & SILC_UMODE_ROUTER_OPERATOR) {
3696 client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3697 if (client->connection)
3698 server->stat.my_router_ops--;
3699 if (server->server_type == SILC_ROUTER)
3700 server->stat.router_ops--;
3704 if (mask & SILC_UMODE_GONE) {
3705 client->mode |= SILC_UMODE_GONE;
3707 if (client->mode & SILC_UMODE_GONE)
3708 /* Remove the gone status */
3709 client->mode &= ~SILC_UMODE_GONE;
3712 /* Send UMODE change to primary router */
3713 if (!server->standalone)
3714 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3715 client->id, client->mode);
3717 /* Send command reply to sender */
3718 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3719 SILC_STATUS_OK, ident, 1,
3721 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3722 packet->data, packet->len, FALSE);
3723 silc_buffer_free(packet);
3726 silc_server_command_free(cmd);
3729 /* Checks that client has rights to add or remove channel modes. If any
3730 of the checks fails FALSE is returned. */
3732 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3733 SilcChannelClientEntry client,
3736 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3737 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3739 /* Check whether has rights to change anything */
3740 if (!is_op && !is_fo)
3743 /* Check whether has rights to change everything */
3747 /* We know that client is channel operator, check that they are not
3748 changing anything that requires channel founder rights. Rest of the
3749 modes are available automatically for channel operator. */
3751 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3752 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3753 if (is_op && !is_fo)
3756 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3757 if (is_op && !is_fo)
3762 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3763 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE))
3764 if (is_op && !is_fo)
3767 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3768 if (is_op && !is_fo)
3773 if (mode & SILC_CHANNEL_MODE_CIPHER) {
3774 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER))
3775 if (is_op && !is_fo)
3778 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3779 if (is_op && !is_fo)
3784 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3785 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH))
3786 if (is_op && !is_fo)
3789 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3790 if (is_op && !is_fo)
3798 /* Server side command of CMODE. Changes channel mode */
3800 SILC_SERVER_CMD_FUNC(cmode)
3802 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3803 SilcServer server = cmd->server;
3804 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3805 SilcIDListData idata = (SilcIDListData)client;
3806 SilcChannelID *channel_id;
3807 SilcChannelEntry channel;
3808 SilcChannelClientEntry chl;
3809 SilcBuffer packet, cidp;
3810 unsigned char *tmp, *tmp_id, *tmp_mask;
3811 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3812 uint32 mode_mask, tmp_len, tmp_len2;
3813 uint16 ident = silc_command_get_ident(cmd->payload);
3815 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 2, 7);
3817 /* Get Channel ID */
3818 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3820 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3821 SILC_STATUS_ERR_NO_CHANNEL_ID);
3824 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3826 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3827 SILC_STATUS_ERR_NO_CHANNEL_ID);
3831 /* Get the channel mode mask */
3832 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3834 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3835 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3838 SILC_GET32_MSB(mode_mask, tmp_mask);
3840 /* Get channel entry */
3841 channel = silc_idlist_find_channel_by_id(server->local_list,
3844 channel = silc_idlist_find_channel_by_id(server->global_list,
3847 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3848 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3853 /* Check whether this client is on the channel */
3854 if (!silc_server_client_on_channel(client, channel)) {
3855 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3856 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3860 /* Get entry to the channel user list */
3861 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
3863 /* Check that client has rights to change any requested channel modes */
3864 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3865 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3866 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3871 * Check the modes. Modes that requires nothing special operation are
3875 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3876 /* Channel uses private keys to protect traffic. Client(s) has set the
3877 key locally they want to use, server does not know that key. */
3878 /* Nothing interesting to do here */
3880 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3881 /* The mode is removed and we need to generate and distribute
3882 new channel key. Clients are not using private channel keys
3883 anymore after this. */
3885 /* Re-generate channel key */
3886 if (!silc_server_create_channel_key(server, channel, 0))
3889 /* Send the channel key. This sends it to our local clients and if
3890 we are normal server to our router as well. */
3891 silc_server_send_channel_key(server, NULL, channel,
3892 server->server_type == SILC_ROUTER ?
3893 FALSE : !server->standalone);
3895 cipher = channel->channel_key->cipher->name;
3896 hmac = (char *)silc_hmac_get_name(channel->hmac);
3900 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3901 /* User limit is set on channel */
3904 /* Get user limit */
3905 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3907 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3908 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3909 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3913 SILC_GET32_MSB(user_limit, tmp);
3914 channel->user_limit = user_limit;
3917 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3918 /* User limit mode is unset. Remove user limit */
3919 channel->user_limit = 0;
3922 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3923 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3924 /* Passphrase has been set to channel */
3926 /* Get the passphrase */
3927 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3929 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3930 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3934 /* Save the passphrase */
3935 passphrase = channel->passphrase = strdup(tmp);
3938 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3939 /* Passphrase mode is unset. remove the passphrase */
3940 if (channel->passphrase) {
3941 silc_free(channel->passphrase);
3942 channel->passphrase = NULL;
3947 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3948 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3949 /* Cipher to use protect the traffic */
3950 SilcCipher newkey, oldkey;
3953 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3955 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3956 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3960 /* Delete old cipher and allocate the new one */
3961 if (!silc_cipher_alloc(cipher, &newkey)) {
3962 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3963 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3967 oldkey = channel->channel_key;
3968 channel->channel_key = newkey;
3970 /* Re-generate channel key */
3971 if (!silc_server_create_channel_key(server, channel, 0)) {
3972 /* We don't have new key, revert to old one */
3973 channel->channel_key = oldkey;
3977 /* Remove old channel key for good */
3978 silc_cipher_free(oldkey);
3980 /* Send the channel key. This sends it to our local clients and if
3981 we are normal server to our router as well. */
3982 silc_server_send_channel_key(server, NULL, channel,
3983 server->server_type == SILC_ROUTER ?
3984 FALSE : !server->standalone);
3987 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3988 /* Cipher mode is unset. Remove the cipher and revert back to
3990 SilcCipher newkey, oldkey;
3991 cipher = channel->cipher;
3993 /* Delete old cipher and allocate default one */
3994 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
3995 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3996 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4000 oldkey = channel->channel_key;
4001 channel->channel_key = newkey;
4003 /* Re-generate channel key */
4004 if (!silc_server_create_channel_key(server, channel, 0)) {
4005 /* We don't have new key, revert to old one */
4006 channel->channel_key = oldkey;
4010 /* Remove old channel key for good */
4011 silc_cipher_free(oldkey);
4013 /* Send the channel key. This sends it to our local clients and if
4014 we are normal server to our router as well. */
4015 silc_server_send_channel_key(server, NULL, channel,
4016 server->server_type == SILC_ROUTER ?
4017 FALSE : !server->standalone);
4021 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
4022 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
4023 /* HMAC to use protect the traffic */
4024 unsigned char hash[32];
4028 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4030 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4031 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4035 /* Delete old hmac and allocate the new one */
4036 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4037 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4038 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4042 silc_hmac_free(channel->hmac);
4043 channel->hmac = newhmac;
4045 /* Set the HMAC key out of current channel key. The client must do
4047 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4048 channel->key_len / 8, hash);
4049 silc_hmac_set_key(channel->hmac, hash,
4050 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4051 memset(hash, 0, sizeof(hash));
4054 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4055 /* Hmac mode is unset. Remove the hmac and revert back to
4058 unsigned char hash[32];
4059 hmac = channel->hmac_name;
4061 /* Delete old hmac and allocate default one */
4062 silc_hmac_free(channel->hmac);
4063 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4064 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4065 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4069 silc_hmac_free(channel->hmac);
4070 channel->hmac = newhmac;
4072 /* Set the HMAC key out of current channel key. The client must do
4074 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4075 channel->key_len / 8,
4077 silc_hmac_set_key(channel->hmac, hash,
4078 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4079 memset(hash, 0, sizeof(hash));
4083 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4084 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4085 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4086 /* Set the founder authentication */
4087 SilcAuthPayload auth;
4089 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4091 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4092 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4096 auth = silc_auth_payload_parse(tmp, tmp_len);
4098 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4099 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4103 /* Save the public key */
4104 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
4105 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
4108 channel->founder_method = silc_auth_get_method(auth);
4110 if (channel->founder_method == SILC_AUTH_PASSWORD) {
4111 tmp = silc_auth_get_data(auth, &tmp_len);
4112 channel->founder_passwd =
4113 silc_calloc(tmp_len + 1, sizeof(*channel->founder_passwd));
4114 memcpy(channel->founder_passwd, tmp, tmp_len);
4115 channel->founder_passwd_len = tmp_len;
4117 /* Verify the payload before setting the mode */
4118 if (!silc_auth_verify(auth, channel->founder_method,
4119 channel->founder_key, 0, idata->hash,
4120 client->id, SILC_ID_CLIENT)) {
4121 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4122 SILC_STATUS_ERR_AUTH_FAILED);
4127 silc_auth_payload_free(auth);
4131 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4132 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4133 if (channel->founder_key)
4134 silc_pkcs_public_key_free(channel->founder_key);
4135 if (channel->founder_passwd) {
4136 silc_free(channel->founder_passwd);
4137 channel->founder_passwd = NULL;
4143 /* Finally, set the mode */
4144 channel->mode = mode_mask;
4146 /* Send CMODE_CHANGE notify. */
4147 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4148 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4149 SILC_NOTIFY_TYPE_CMODE_CHANGE, 5,
4150 cidp->data, cidp->len,
4152 cipher, cipher ? strlen(cipher) : 0,
4153 hmac, hmac ? strlen(hmac) : 0,
4154 passphrase, passphrase ?
4155 strlen(passphrase) : 0);
4157 /* Set CMODE notify type to network */
4158 if (!server->standalone)
4159 silc_server_send_notify_cmode(server, server->router->connection,
4160 server->server_type == SILC_ROUTER ?
4161 TRUE : FALSE, channel,
4162 mode_mask, client->id, SILC_ID_CLIENT,
4163 cipher, hmac, passphrase);
4165 /* Send command reply to sender */
4166 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4167 SILC_STATUS_OK, ident, 2,
4168 2, tmp_id, tmp_len2,
4170 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4171 packet->data, packet->len, FALSE);
4173 silc_buffer_free(packet);
4174 silc_free(channel_id);
4175 silc_buffer_free(cidp);
4178 silc_server_command_free(cmd);
4181 /* Server side of CUMODE command. Changes client's mode on a channel. */
4183 SILC_SERVER_CMD_FUNC(cumode)
4185 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4186 SilcServer server = cmd->server;
4187 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4188 SilcIDListData idata = (SilcIDListData)client;
4189 SilcChannelID *channel_id;
4190 SilcClientID *client_id;
4191 SilcChannelEntry channel;
4192 SilcClientEntry target_client;
4193 SilcChannelClientEntry chl;
4194 SilcBuffer packet, idp;
4195 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4196 uint32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4198 uint16 ident = silc_command_get_ident(cmd->payload);
4200 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4202 /* Get Channel ID */
4203 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4205 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4206 SILC_STATUS_ERR_NO_CHANNEL_ID);
4209 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
4211 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4212 SILC_STATUS_ERR_NO_CHANNEL_ID);
4216 /* Get channel entry */
4217 channel = silc_idlist_find_channel_by_id(server->local_list,
4220 channel = silc_idlist_find_channel_by_id(server->global_list,
4223 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4224 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4229 /* Check whether sender is on the channel */
4230 if (!silc_server_client_on_channel(client, channel)) {
4231 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4232 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4236 /* Check that client has rights to change other's rights */
4237 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4238 sender_mask = chl->mode;
4240 /* Get the target client's channel mode mask */
4241 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4243 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4244 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4247 SILC_GET32_MSB(target_mask, tmp_mask);
4249 /* Get target Client ID */
4250 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4252 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4253 SILC_STATUS_ERR_NO_CLIENT_ID);
4256 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
4258 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4259 SILC_STATUS_ERR_NO_CLIENT_ID);
4263 /* Get target client's entry */
4264 target_client = silc_idlist_find_client_by_id(server->local_list,
4265 client_id, TRUE, NULL);
4266 if (!target_client) {
4267 target_client = silc_idlist_find_client_by_id(server->global_list,
4268 client_id, TRUE, NULL);
4271 if (target_client != client &&
4272 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4273 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4274 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4275 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4279 /* Check whether target client is on the channel */
4280 if (target_client != client) {
4281 if (!silc_server_client_on_channel(target_client, channel)) {
4282 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4283 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4287 /* Get entry to the channel user list */
4288 silc_hash_table_find(channel->user_list, target_client, NULL,
4296 /* If the target client is founder, no one else can change their mode
4298 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4299 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4300 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4304 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4305 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4306 /* The client tries to claim the founder rights. */
4307 unsigned char *tmp_auth;
4308 uint32 tmp_auth_len, auth_len;
4311 if (target_client != client) {
4312 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4313 SILC_STATUS_ERR_NOT_YOU);
4317 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4318 !channel->founder_key || !idata->public_key ||
4319 !silc_pkcs_public_key_compare(channel->founder_key,
4320 idata->public_key)) {
4321 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4322 SILC_STATUS_ERR_NOT_YOU);
4326 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4328 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4329 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4333 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4334 (void *)channel->founder_passwd : (void *)channel->founder_key);
4335 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4336 channel->founder_passwd_len : 0);
4338 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4339 channel->founder_method, auth, auth_len,
4340 idata->hash, client->id, SILC_ID_CLIENT)) {
4341 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4342 SILC_STATUS_ERR_AUTH_FAILED);
4346 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4350 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4351 if (target_client == client) {
4352 /* Remove channel founder rights from itself */
4353 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4356 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4357 SILC_STATUS_ERR_NOT_YOU);
4363 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4364 /* Promote to operator */
4365 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4366 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4367 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4368 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4369 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4373 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4377 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4378 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4379 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4380 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4381 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4385 /* Demote to normal user */
4386 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4391 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4392 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4394 /* Send notify to channel, notify only if mode was actually changed. */
4396 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4397 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4398 idp->data, idp->len,
4402 /* Set CUMODE notify type to network */
4403 if (!server->standalone)
4404 silc_server_send_notify_cumode(server, server->router->connection,
4405 server->server_type == SILC_ROUTER ?
4406 TRUE : FALSE, channel,
4407 target_mask, client->id,
4412 /* Send command reply to sender */
4413 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4414 SILC_STATUS_OK, ident, 3,
4416 3, tmp_ch_id, tmp_ch_len,
4417 4, tmp_id, tmp_len);
4418 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4419 packet->data, packet->len, FALSE);
4421 silc_buffer_free(packet);
4422 silc_free(channel_id);
4423 silc_free(client_id);
4424 silc_buffer_free(idp);
4427 silc_server_command_free(cmd);
4430 /* Server side of KICK command. Kicks client out of channel. */
4432 SILC_SERVER_CMD_FUNC(kick)
4434 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4435 SilcServer server = cmd->server;
4436 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4437 SilcClientEntry target_client;
4438 SilcChannelID *channel_id;
4439 SilcClientID *client_id;
4440 SilcChannelEntry channel;
4441 SilcChannelClientEntry chl;
4443 uint32 tmp_len, target_idp_len;
4444 unsigned char *tmp, *comment, *target_idp;
4446 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4448 /* Get Channel ID */
4449 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4451 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4452 SILC_STATUS_ERR_NO_CHANNEL_ID);
4455 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
4457 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4458 SILC_STATUS_ERR_NO_CHANNEL_ID);
4462 /* Get channel entry */
4463 channel = silc_idlist_find_channel_by_id(server->local_list,
4466 channel = silc_idlist_find_channel_by_id(server->local_list,
4469 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4470 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4475 /* Check whether sender is on the channel */
4476 if (!silc_server_client_on_channel(client, channel)) {
4477 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4478 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4482 /* Check that the kicker is channel operator or channel founder */
4483 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4484 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4485 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4486 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4490 /* Get target Client ID */
4491 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4493 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4494 SILC_STATUS_ERR_NO_CLIENT_ID);
4497 client_id = silc_id_payload_parse_id(target_idp, target_idp_len);
4499 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4500 SILC_STATUS_ERR_NO_CLIENT_ID);
4504 /* Get target client's entry */
4505 target_client = silc_idlist_find_client_by_id(server->local_list,
4506 client_id, TRUE, NULL);
4507 if (!target_client) {
4508 target_client = silc_idlist_find_client_by_id(server->global_list,
4509 client_id, TRUE, NULL);
4512 /* Check that the target client is not channel founder. Channel founder
4513 cannot be kicked from the channel. */
4514 silc_hash_table_find(channel->user_list, target_client, NULL, (void *)&chl);
4515 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4516 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4517 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4521 /* Check whether target client is on the channel */
4522 if (!silc_server_client_on_channel(target_client, channel)) {
4523 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4524 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4530 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4534 /* Send command reply to sender */
4535 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4538 /* Send KICKED notify to local clients on the channel */
4539 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4540 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4541 SILC_NOTIFY_TYPE_KICKED, 3,
4542 target_idp, target_idp_len,
4543 comment, comment ? strlen(comment) : 0,
4544 idp->data, idp->len);
4545 silc_buffer_free(idp);
4547 /* Remove the client from the channel. If the channel does not exist
4548 after removing the client then the client kicked itself off the channel
4549 and we don't have to send anything after that. */
4550 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4551 target_client, FALSE))
4554 /* Send KICKED notify to primary route */
4555 if (!server->standalone)
4556 silc_server_send_notify_kicked(server, server->router->connection,
4557 server->server_type == SILC_ROUTER ?
4558 TRUE : FALSE, channel,
4559 target_client->id, client->id, comment);
4561 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4562 /* Re-generate channel key */
4563 if (!silc_server_create_channel_key(server, channel, 0))
4566 /* Send the channel key to the channel. The key of course is not sent
4567 to the client who was kicked off the channel. */
4568 silc_server_send_channel_key(server, target_client->connection, channel,
4569 server->server_type == SILC_ROUTER ?
4570 FALSE : !server->standalone);
4574 silc_server_command_free(cmd);
4577 /* Server side of OPER command. Client uses this comand to obtain server
4578 operator privileges to this server/router. */
4580 SILC_SERVER_CMD_FUNC(oper)
4582 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4583 SilcServer server = cmd->server;
4584 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4585 unsigned char *username, *auth;
4587 SilcServerConfigAdmin *admin;
4588 SilcIDListData idata = (SilcIDListData)client;
4589 bool result = FALSE;
4591 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4593 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4596 /* Get the username */
4597 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4599 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4600 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4604 /* Get the admin configuration */
4605 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4606 username, client->nickname);
4608 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4609 username, client->nickname);
4611 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4612 SILC_STATUS_ERR_AUTH_FAILED);
4617 /* Get the authentication payload */
4618 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4620 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4621 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4625 /* Verify the authentication data. If both passphrase and public key
4626 is set then try both of them. */
4627 if (admin->passphrase)
4628 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4629 admin->passphrase, admin->passphrase_len,
4630 idata->hash, client->id, SILC_ID_CLIENT);
4631 if (!result && admin->publickey)
4632 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4633 admin->publickey, 0,
4634 idata->hash, client->id, SILC_ID_CLIENT);
4636 /* Authentication failed */
4637 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4638 SILC_STATUS_ERR_AUTH_FAILED);
4642 /* Client is now server operator */
4643 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4645 /* Update statistics */
4646 if (client->connection)
4647 server->stat.my_server_ops++;
4648 if (server->server_type == SILC_ROUTER)
4649 server->stat.server_ops++;
4651 /* Send UMODE change to primary router */
4652 if (!server->standalone)
4653 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4654 client->id, client->mode);
4656 /* Send reply to the sender */
4657 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4661 silc_server_command_free(cmd);
4664 /* Server side of SILCOPER command. Client uses this comand to obtain router
4665 operator privileges to this router. */
4667 SILC_SERVER_CMD_FUNC(silcoper)
4669 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4670 SilcServer server = cmd->server;
4671 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4672 unsigned char *username, *auth;
4674 SilcServerConfigAdmin *admin;
4675 SilcIDListData idata = (SilcIDListData)client;
4676 bool result = FALSE;
4678 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4680 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4683 if (server->server_type != SILC_ROUTER) {
4684 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4685 SILC_STATUS_ERR_AUTH_FAILED);
4689 /* Get the username */
4690 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4692 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4693 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4697 /* Get the admin configuration */
4698 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4699 username, client->nickname);
4701 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4702 username, client->nickname);
4704 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4705 SILC_STATUS_ERR_AUTH_FAILED);
4710 /* Get the authentication payload */
4711 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4713 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4714 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4718 /* Verify the authentication data. If both passphrase and public key
4719 is set then try both of them. */
4720 if (admin->passphrase)
4721 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4722 admin->passphrase, admin->passphrase_len,
4723 idata->hash, client->id, SILC_ID_CLIENT);
4724 if (!result && admin->publickey)
4725 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4726 admin->publickey, 0,
4727 idata->hash, client->id, SILC_ID_CLIENT);
4729 /* Authentication failed */
4730 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4731 SILC_STATUS_ERR_AUTH_FAILED);
4735 /* Client is now router operator */
4736 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4738 /* Update statistics */
4739 if (client->connection)
4740 server->stat.my_router_ops++;
4741 if (server->server_type == SILC_ROUTER)
4742 server->stat.router_ops++;
4744 /* Send UMODE change to primary router */
4745 if (!server->standalone)
4746 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4747 client->id, client->mode);
4749 /* Send reply to the sender */
4750 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4754 silc_server_command_free(cmd);
4757 /* Server side command of CONNECT. Connects us to the specified remote
4758 server or router. */
4760 SILC_SERVER_CMD_FUNC(connect)
4762 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4763 SilcServer server = cmd->server;
4764 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4765 unsigned char *tmp, *host;
4767 uint32 port = SILC_PORT;
4769 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CONNECT, cmd, 1, 2);
4771 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4774 /* Check whether client has the permissions. */
4775 if (client->mode == SILC_UMODE_NONE) {
4776 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4777 SILC_STATUS_ERR_NO_SERVER_PRIV);
4781 if (server->server_type == SILC_ROUTER &&
4782 client->mode & SILC_UMODE_SERVER_OPERATOR) {
4783 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4784 SILC_STATUS_ERR_NO_ROUTER_PRIV);
4788 /* Get the remote server */
4789 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4791 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4792 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4797 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4799 SILC_GET32_MSB(port, tmp);
4801 /* Create the connection. It is done with timeout and is async. */
4802 silc_server_create_connection(server, host, port);
4804 /* Send reply to the sender */
4805 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4809 silc_server_command_free(cmd);
4812 /* Server side of command BAN. This is used to manage the ban list of the
4813 channel. To add clients and remove clients from the ban list. */
4815 SILC_SERVER_CMD_FUNC(ban)
4817 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4818 SilcServer server = cmd->server;
4819 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4821 SilcChannelEntry channel;
4822 SilcChannelClientEntry chl;
4823 SilcChannelID *channel_id = NULL;
4824 unsigned char *id, *add, *del;
4825 uint32 id_len, tmp_len;
4826 uint16 ident = silc_command_get_ident(cmd->payload);
4828 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4831 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4833 /* Get Channel ID */
4834 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4836 channel_id = silc_id_payload_parse_id(id, id_len);
4838 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4839 SILC_STATUS_ERR_NO_CHANNEL_ID);
4844 /* Get channel entry. The server must know about the channel since the
4845 client is expected to be on the channel. */
4846 channel = silc_idlist_find_channel_by_id(server->local_list,
4849 channel = silc_idlist_find_channel_by_id(server->global_list,
4852 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4853 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4858 /* Check whether this client is on the channel */
4859 if (!silc_server_client_on_channel(client, channel)) {
4860 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4861 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4865 /* Get entry to the channel user list */
4866 if (!silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl)) {
4867 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4868 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4872 /* The client must be at least channel operator. */
4873 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4874 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4875 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4879 /* Get the new ban and add it to the ban list */
4880 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4882 if (!channel->ban_list)
4883 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4885 channel->ban_list = silc_realloc(channel->ban_list,
4886 sizeof(*channel->ban_list) *
4888 strlen(channel->ban_list) + 2));
4889 if (add[tmp_len - 1] == ',')
4890 add[tmp_len - 1] = '\0';
4892 strncat(channel->ban_list, add, tmp_len);
4893 strncat(channel->ban_list, ",", 1);
4896 /* Get the ban to be removed and remove it from the list */
4897 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4898 if (del && channel->ban_list) {
4899 char *start, *end, *n;
4901 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4902 silc_free(channel->ban_list);
4903 channel->ban_list = NULL;
4905 start = strstr(channel->ban_list, del);
4906 if (start && strlen(start) >= tmp_len) {
4907 end = start + tmp_len;
4908 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4909 strncat(n, channel->ban_list, start - channel->ban_list);
4910 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4912 silc_free(channel->ban_list);
4913 channel->ban_list = n;
4918 /* Send the BAN notify type to our primary router. */
4919 if (!server->standalone && (add || del))
4920 silc_server_send_notify_ban(server, server->router->connection,
4921 server->server_type == SILC_ROUTER ?
4922 TRUE : FALSE, channel, add, del);
4924 /* Send the reply back to the client */
4926 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4927 SILC_STATUS_OK, ident, 2,
4929 3, channel->ban_list,
4931 strlen(channel->ban_list) -1 : 0);
4932 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4933 packet->data, packet->len, FALSE);
4935 silc_buffer_free(packet);
4938 silc_free(channel_id);
4939 silc_server_command_free(cmd);
4942 /* Server side command of CLOSE. Closes connection to a specified server. */
4944 SILC_SERVER_CMD_FUNC(close)
4946 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4947 SilcServer server = cmd->server;
4948 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4949 SilcServerEntry server_entry;
4950 SilcSocketConnection sock;
4953 unsigned char *name;
4954 uint32 port = SILC_PORT;
4956 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CLOSE, cmd, 1, 2);
4958 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4961 /* Check whether client has the permissions. */
4962 if (client->mode == SILC_UMODE_NONE) {
4963 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4964 SILC_STATUS_ERR_NO_SERVER_PRIV);
4968 /* Get the remote server */
4969 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4971 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4972 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4977 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4979 SILC_GET32_MSB(port, tmp);
4981 server_entry = silc_idlist_find_server_by_conn(server->local_list,
4982 name, port, FALSE, NULL);
4984 server_entry = silc_idlist_find_server_by_conn(server->global_list,
4985 name, port, FALSE, NULL);
4986 if (!server_entry) {
4987 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4988 SILC_STATUS_ERR_NO_SERVER_ID);
4992 /* Send reply to the sender */
4993 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4996 /* Close the connection to the server */
4997 sock = (SilcSocketConnection)server_entry->connection;
4999 /* If we shutdown primary router connection manually then don't trigger
5000 any reconnect or backup router connections, by setting the router
5002 if (server->router == server_entry) {
5003 server->id_entry->router = NULL;
5004 server->router = NULL;
5005 server->standalone = TRUE;
5007 silc_server_free_sock_user_data(server, sock, NULL);
5008 silc_server_close_connection(server, sock);
5011 silc_server_command_free(cmd);
5014 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
5015 active connections. */
5017 SILC_SERVER_CMD_FUNC(shutdown)
5019 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5020 SilcServer server = cmd->server;
5021 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5023 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
5025 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5028 /* Check whether client has the permission. */
5029 if (client->mode == SILC_UMODE_NONE) {
5030 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
5031 SILC_STATUS_ERR_NO_SERVER_PRIV);
5035 /* Send reply to the sender */
5036 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
5039 /* Then, gracefully, or not, bring the server down. */
5040 silc_server_stop(server);
5044 silc_server_command_free(cmd);
5047 /* Server side command of LEAVE. Removes client from a channel. */
5049 SILC_SERVER_CMD_FUNC(leave)
5051 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5052 SilcServer server = cmd->server;
5053 SilcSocketConnection sock = cmd->sock;
5054 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
5055 SilcChannelID *id = NULL;
5056 SilcChannelEntry channel;
5060 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
5062 /* Get Channel ID */
5063 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
5065 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5066 SILC_STATUS_ERR_NO_CHANNEL_ID);
5069 id = silc_id_payload_parse_id(tmp, len);
5071 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5072 SILC_STATUS_ERR_NO_CHANNEL_ID);
5076 /* Get channel entry */
5077 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5079 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5081 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5082 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5087 /* Check whether this client is on the channel */
5088 if (!silc_server_client_on_channel(id_entry, channel)) {
5089 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5090 SILC_STATUS_ERR_NOT_ON_CHANNEL);
5094 /* Notify routers that they should remove this client from their list
5095 of clients on the channel. Send LEAVE notify type. */
5096 if (!server->standalone)
5097 silc_server_send_notify_leave(server, server->router->connection,
5098 server->server_type == SILC_ROUTER ?
5099 TRUE : FALSE, channel, id_entry->id);
5101 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5104 /* Remove client from channel */
5105 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5107 /* If the channel does not exist anymore we won't send anything */
5110 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5111 /* Re-generate channel key */
5112 if (!silc_server_create_channel_key(server, channel, 0))
5115 /* Send the channel key */
5116 silc_server_send_channel_key(server, NULL, channel,
5117 server->server_type == SILC_ROUTER ?
5118 FALSE : !server->standalone);
5123 silc_server_command_free(cmd);
5126 /* Server side of command USERS. Resolves clients and their USERS currently
5127 joined on the requested channel. The list of Client ID's and their modes
5128 on the channel is sent back. */
5130 SILC_SERVER_CMD_FUNC(users)
5132 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5133 SilcServer server = cmd->server;
5134 SilcChannelEntry channel;
5135 SilcChannelID *id = NULL;
5136 SilcBuffer packet, idp;
5137 unsigned char *channel_id;
5138 uint32 channel_id_len;
5139 SilcBuffer client_id_list;
5140 SilcBuffer client_mode_list;
5141 unsigned char lc[4];
5142 uint32 list_count = 0;
5143 uint16 ident = silc_command_get_ident(cmd->payload);
5146 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5148 /* Get Channel ID */
5149 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5151 /* Get channel name */
5152 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5154 if (!channel_id && !channel_name) {
5155 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5156 SILC_STATUS_ERR_NO_CHANNEL_ID);
5161 id = silc_id_payload_parse_id(channel_id, channel_id_len);
5163 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5164 SILC_STATUS_ERR_NO_CHANNEL_ID);
5169 /* If we are server and we don't know about this channel we will send
5170 the command to our router. If we know about the channel then we also
5171 have the list of users already. */
5173 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5175 channel = silc_idlist_find_channel_by_name(server->local_list,
5176 channel_name, NULL);
5178 if (!channel || channel->disabled) {
5179 if (server->server_type != SILC_ROUTER && !server->standalone &&
5183 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5184 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5186 /* Send USERS command */
5187 silc_server_packet_send(server, server->router->connection,
5188 SILC_PACKET_COMMAND, cmd->packet->flags,
5189 tmpbuf->data, tmpbuf->len, TRUE);
5191 /* Reprocess this packet after received reply */
5192 silc_server_command_pending(server, SILC_COMMAND_USERS,
5193 silc_command_get_ident(cmd->payload),
5194 silc_server_command_users,
5195 silc_server_command_dup(cmd));
5196 cmd->pending = TRUE;
5197 silc_command_set_ident(cmd->payload, ident);
5198 silc_buffer_free(tmpbuf);
5203 /* Check the global list as well. */
5205 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5207 channel = silc_idlist_find_channel_by_name(server->global_list,
5208 channel_name, NULL);
5210 /* Channel really does not exist */
5211 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5212 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5217 /* If the channel is private or secret do not send anything, unless the
5218 user requesting this command is on the channel. */
5219 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5220 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5221 && !silc_server_client_on_channel(cmd->sock->user_data, channel)) {
5222 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5223 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5228 (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
5229 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5230 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5235 /* Get the users list */
5236 silc_server_get_users_on_channel(server, channel, &client_id_list,
5237 &client_mode_list, &list_count);
5240 SILC_PUT32_MSB(list_count, lc);
5243 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5244 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5245 SILC_STATUS_OK, ident, 4,
5246 2, idp->data, idp->len,
5248 4, client_id_list->data,
5249 client_id_list->len,
5250 5, client_mode_list->data,
5251 client_mode_list->len);
5252 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5253 packet->data, packet->len, FALSE);
5255 silc_buffer_free(idp);
5256 silc_buffer_free(packet);
5257 silc_buffer_free(client_id_list);
5258 silc_buffer_free(client_mode_list);
5262 silc_server_command_free(cmd);
5265 /* Server side of command GETKEY. This fetches the client's public key
5266 from the server where to the client is connected. */
5268 SILC_SERVER_CMD_FUNC(getkey)
5270 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5271 SilcServer server = cmd->server;
5273 SilcClientEntry client;
5274 SilcServerEntry server_entry;
5275 SilcClientID *client_id = NULL;
5276 SilcServerID *server_id = NULL;
5277 SilcIDPayload idp = NULL;
5278 uint16 ident = silc_command_get_ident(cmd->payload);
5279 unsigned char *tmp, *pkdata;
5280 uint32 tmp_len, pklen;
5281 SilcBuffer pk = NULL;
5283 SilcPublicKey public_key;
5285 SILC_LOG_DEBUG(("Start"));
5287 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5289 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5290 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5293 idp = silc_id_payload_parse(tmp, tmp_len);
5295 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5296 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5300 id_type = silc_id_payload_get_type(idp);
5301 if (id_type == SILC_ID_CLIENT) {
5302 client_id = silc_id_payload_get_id(idp);
5304 /* If the client is not found from local list there is no chance it
5305 would be locally connected client so send the command further. */
5306 client = silc_idlist_find_client_by_id(server->local_list,
5307 client_id, TRUE, NULL);
5309 client = silc_idlist_find_client_by_id(server->global_list,
5310 client_id, TRUE, NULL);
5312 if ((!client && !cmd->pending && !server->standalone) ||
5313 (client && !client->connection && !cmd->pending) ||
5314 (client && !client->data.public_key && !cmd->pending)) {
5317 SilcSocketConnection dest_sock;
5319 dest_sock = silc_server_get_client_route(server, NULL, 0,
5324 old_ident = silc_command_get_ident(cmd->payload);
5325 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5326 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5328 silc_server_packet_send(server, dest_sock,
5329 SILC_PACKET_COMMAND, cmd->packet->flags,
5330 tmpbuf->data, tmpbuf->len, TRUE);
5332 /* Reprocess this packet after received reply from router */
5333 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5334 silc_command_get_ident(cmd->payload),
5335 silc_server_command_getkey,
5336 silc_server_command_dup(cmd));
5337 cmd->pending = TRUE;
5338 silc_command_set_ident(cmd->payload, old_ident);
5339 silc_buffer_free(tmpbuf);
5344 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5345 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5349 /* The client is locally connected, just get the public key and
5350 send it back. If they key does not exist then do not send it,
5351 send just OK reply */
5352 public_key = client->data.public_key;
5357 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5358 pk = silc_buffer_alloc(4 + tmp_len);
5359 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5360 silc_buffer_format(pk,
5361 SILC_STR_UI_SHORT(tmp_len),
5362 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5363 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5369 } else if (id_type == SILC_ID_SERVER) {
5370 server_id = silc_id_payload_get_id(idp);
5372 /* If the server is not found from local list there is no chance it
5373 would be locally connected server so send the command further. */
5374 server_entry = silc_idlist_find_server_by_id(server->local_list,
5375 server_id, TRUE, NULL);
5377 server_entry = silc_idlist_find_server_by_id(server->global_list,
5378 server_id, TRUE, NULL);
5380 if (server_entry != server->id_entry &&
5381 ((!server_entry && !cmd->pending && !server->standalone) ||
5382 (server_entry && !server_entry->connection && !cmd->pending &&
5383 !server->standalone) ||
5384 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5385 !server->standalone))) {
5389 old_ident = silc_command_get_ident(cmd->payload);
5390 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5391 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5393 silc_server_packet_send(server, server->router->connection,
5394 SILC_PACKET_COMMAND, cmd->packet->flags,
5395 tmpbuf->data, tmpbuf->len, TRUE);
5397 /* Reprocess this packet after received reply from router */
5398 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5399 silc_command_get_ident(cmd->payload),
5400 silc_server_command_getkey,
5401 silc_server_command_dup(cmd));
5402 cmd->pending = TRUE;
5403 silc_command_set_ident(cmd->payload, old_ident);
5404 silc_buffer_free(tmpbuf);
5408 if (!server_entry) {
5409 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5410 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5414 /* If they key does not exist then do not send it, send just OK reply */
5415 public_key = (!server_entry->data.public_key ?
5416 (server_entry == server->id_entry ? server->public_key :
5417 NULL) : server_entry->data.public_key);
5422 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5423 pk = silc_buffer_alloc(4 + tmp_len);
5424 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5425 silc_buffer_format(pk,
5426 SILC_STR_UI_SHORT(tmp_len),
5427 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5428 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5438 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5439 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5440 SILC_STATUS_OK, ident,
5444 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5445 packet->data, packet->len, FALSE);
5446 silc_buffer_free(packet);
5449 silc_buffer_free(pk);
5453 silc_id_payload_free(idp);
5454 silc_free(client_id);
5455 silc_free(server_id);
5456 silc_server_command_free(cmd);