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 SilcUInt32 *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 SilcUInt32 *client_id_count,
483 SilcUInt32 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 SilcUInt32 *res_argv_lens;
553 SilcUInt32 *res_argv_types;
555 } *SilcServerResolveContext;
558 silc_server_command_whois_check(SilcServerCommandContext cmd,
559 SilcClientEntry *clients,
560 SilcUInt32 clients_count)
562 SilcServer server = cmd->server;
563 SilcClientEntry entry;
564 SilcServerResolveContext resolve = NULL, r = NULL;
565 SilcUInt32 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 SilcUInt32 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 SilcUInt16 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;
833 SilcUInt16 old_ident;
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 SilcUInt32 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 SilcUInt32 clients_count)
1040 SilcServer server = cmd->server;
1042 SilcClientEntry entry;
1044 for (i = 0; i < clients_count; i++) {
1047 if (!entry->nickname || !entry->username) {
1049 SilcUInt16 old_ident;
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 SilcUInt32 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 SilcUInt16 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 SilcUInt32 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) {
1197 SilcUInt16 old_ident;
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;
1299 SilcUInt16 old_ident;
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 SilcUInt32 *clients_count,
1325 SilcServerEntry **servers,
1326 SilcUInt32 *servers_count,
1327 SilcChannelEntry **channels,
1328 SilcUInt32 *channels_count,
1331 SilcServer server = cmd->server;
1334 SilcUInt32 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 SilcUInt32 clients_count)
1598 SilcServer server = cmd->server;
1599 SilcClientEntry entry;
1600 SilcServerResolveContext resolve = NULL, r = NULL;
1601 SilcUInt32 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 SilcUInt32 clients_count,
1734 SilcServerEntry *servers,
1735 SilcUInt32 servers_count,
1736 SilcChannelEntry *channels,
1737 SilcUInt32 channels_count,
1740 SilcServer server = cmd->server;
1741 int i, k, len, valid_count;
1742 SilcBuffer packet, idp;
1743 SilcCommandStatus status;
1744 SilcUInt16 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, (SilcUInt32 *)&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)
1927 SilcUInt32 count = 0;
1929 SilcClientEntry *clients = NULL;
1930 SilcServerEntry *servers = NULL;
1931 SilcChannelEntry *channels = NULL;
1932 SilcUInt32 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;
1988 SilcUInt32 nick_len;
1990 SilcUInt16 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,
2080 SilcUInt32 lch_count,
2081 SilcChannelEntry *gch,
2082 SilcUInt32 gch_count)
2085 SilcBuffer packet, idp;
2086 SilcChannelEntry entry;
2087 SilcCommandStatus status;
2088 SilcUInt16 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 SilcUInt32 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) {
2210 SilcUInt16 old_ident;
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 SilcUInt32 argc, tmp_len;
2274 SilcUInt16 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 SilcUInt16 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 SilcUInt32 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 SilcUInt16 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 */
2874 SilcUInt16 old_ident;
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 */
2898 SilcUInt16 old_ident;
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,
3003 SilcUInt32 auth_len)
3005 SilcSocketConnection sock = cmd->sock;
3007 SilcUInt32 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 SilcUInt16 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 SilcUInt32 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_memdup(tmp, tmp_len);
3147 if (!passphrase || !channel->passphrase ||
3148 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3149 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3150 SILC_STATUS_ERR_BAD_PASSWORD);
3156 * Client is allowed to join to the channel. Make it happen.
3159 /* Check whether the client already is on the channel */
3160 if (silc_server_client_on_channel(client, channel)) {
3161 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3162 SILC_STATUS_ERR_USER_ON_CHANNEL);
3166 /* Generate new channel key as protocol dictates */
3168 if (!silc_server_create_channel_key(server, channel, 0))
3171 /* Send the channel key. This is broadcasted to the channel but is not
3172 sent to the client who is joining to the channel. */
3173 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3174 silc_server_send_channel_key(server, NULL, channel,
3175 server->server_type == SILC_ROUTER ?
3176 FALSE : !server->standalone);
3179 /* Join the client to the channel by adding it to channel's user list.
3180 Add also the channel to client entry's channels list for fast cross-
3182 chl = silc_calloc(1, sizeof(*chl));
3184 chl->client = client;
3185 chl->channel = channel;
3186 silc_hash_table_add(channel->user_list, client, chl);
3187 silc_hash_table_add(client->channels, channel, chl);
3188 channel->user_count++;
3190 /* Get users on the channel */
3191 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3194 /* Encode Client ID Payload of the original client who wants to join */
3195 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3197 /* Encode command reply packet */
3198 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3199 SILC_PUT32_MSB(channel->mode, mode);
3200 SILC_PUT32_MSB(created, tmp2);
3201 SILC_PUT32_MSB(user_count, tmp3);
3203 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3204 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3205 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
3206 strlen(channel->channel_key->
3208 channel->channel_key->cipher->name,
3209 channel->key_len / 8, channel->key);
3214 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3215 SILC_STATUS_OK, ident, 13,
3216 2, channel->channel_name,
3217 strlen(channel->channel_name),
3218 3, chidp->data, chidp->len,
3219 4, clidp->data, clidp->len,
3222 7, keyp ? keyp->data : NULL,
3223 keyp ? keyp->len : 0,
3224 8, channel->ban_list,
3226 strlen(channel->ban_list) : 0,
3227 9, channel->invite_list,
3228 channel->invite_list ?
3229 strlen(channel->invite_list) : 0,
3232 strlen(channel->topic) : 0,
3233 11, silc_hmac_get_name(channel->hmac),
3234 strlen(silc_hmac_get_name(channel->
3237 13, user_list->data, user_list->len,
3238 14, mode_list->data,
3241 /* Send command reply */
3242 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3243 reply->data, reply->len, FALSE);
3245 /* Send JOIN notify to locally connected clients on the channel. If
3246 we are normal server then router will send or have sent JOIN notify
3247 already. However since we've added the client already to our channel
3248 we'll ignore it (in packet_receive.c) so we must send it here. If
3249 we are router then this will send it to local clients and local
3251 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3252 SILC_NOTIFY_TYPE_JOIN, 2,
3253 clidp->data, clidp->len,
3254 chidp->data, chidp->len);
3256 if (!cmd->pending) {
3257 /* Send JOIN notify packet to our primary router */
3258 if (!server->standalone)
3259 silc_server_send_notify_join(server, server->router->connection,
3260 server->server_type == SILC_ROUTER ?
3261 TRUE : FALSE, channel, client->id);
3264 /* Distribute the channel key to all backup routers. */
3265 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3266 keyp->data, keyp->len, FALSE, TRUE);
3269 /* If client became founder by providing correct founder auth data
3270 notify the mode change to the channel. */
3272 SILC_PUT32_MSB(chl->mode, mode);
3273 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3274 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3275 clidp->data, clidp->len,
3276 mode, 4, clidp->data, clidp->len);
3278 /* Set CUMODE notify type to network */
3279 if (!server->standalone)
3280 silc_server_send_notify_cumode(server, server->router->connection,
3281 server->server_type == SILC_ROUTER ?
3282 TRUE : FALSE, channel,
3283 chl->mode, client->id, SILC_ID_CLIENT,
3287 silc_buffer_free(reply);
3288 silc_buffer_free(clidp);
3289 silc_buffer_free(chidp);
3290 silc_buffer_free(keyp);
3291 silc_buffer_free(user_list);
3292 silc_buffer_free(mode_list);
3295 silc_free(passphrase);
3298 /* Server side of command JOIN. Joins client into requested channel. If
3299 the channel does not exist it will be created. */
3301 SILC_SERVER_CMD_FUNC(join)
3303 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3304 SilcServer server = cmd->server;
3305 unsigned char *auth;
3306 SilcUInt32 tmp_len, auth_len;
3307 char *tmp, *channel_name = NULL, *cipher, *hmac;
3308 SilcChannelEntry channel;
3309 SilcUInt32 umode = 0;
3310 bool created = FALSE, create_key = TRUE;
3311 SilcClientID *client_id;
3313 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3315 /* Get channel name */
3316 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3318 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3319 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3325 channel_name[255] = '\0';
3327 if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
3328 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3329 SILC_STATUS_ERR_BAD_CHANNEL);
3333 /* Get Client ID of the client who is joining to the channel */
3334 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3336 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3337 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3340 client_id = silc_id_payload_parse_id(tmp, tmp_len);
3342 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3343 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3347 /* Get cipher, hmac name and auth payload */
3348 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3349 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3350 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3352 /* See if the channel exists */
3353 channel = silc_idlist_find_channel_by_name(server->local_list,
3354 channel_name, NULL);
3356 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3357 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3358 client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
3360 if (!channel || channel->disabled) {
3361 /* Channel not found */
3363 /* If we are standalone server we don't have a router, we just create
3364 the channel by ourselves. */
3365 if (server->standalone) {
3366 channel = silc_server_create_new_channel(server, server->id, cipher,
3367 hmac, channel_name, TRUE);
3369 silc_server_command_send_status_reply(
3370 cmd, SILC_COMMAND_JOIN,
3371 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3375 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3381 /* The channel does not exist on our server. If we are normal server
3382 we will send JOIN command to our router which will handle the
3383 joining procedure (either creates the channel if it doesn't exist
3384 or joins the client to it). */
3385 if (server->server_type != SILC_ROUTER) {
3387 SilcUInt16 old_ident;
3389 /* If this is pending command callback then we've resolved
3390 it and it didn't work, return since we've notified the
3391 client already in the command reply callback. */
3395 old_ident = silc_command_get_ident(cmd->payload);
3396 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3397 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3399 /* Send JOIN command to our router */
3400 silc_server_packet_send(server, (SilcSocketConnection)
3401 server->router->connection,
3402 SILC_PACKET_COMMAND, cmd->packet->flags,
3403 tmpbuf->data, tmpbuf->len, TRUE);
3405 /* Reprocess this packet after received reply from router */
3406 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3407 silc_command_get_ident(cmd->payload),
3408 silc_server_command_join,
3409 silc_server_command_dup(cmd));
3410 cmd->pending = TRUE;
3411 silc_command_set_ident(cmd->payload, old_ident);
3412 silc_buffer_free(tmpbuf);
3416 /* We are router and the channel does not seem exist so we will check
3417 our global list as well for the channel. */
3418 channel = silc_idlist_find_channel_by_name(server->global_list,
3419 channel_name, NULL);
3421 /* Channel really does not exist, create it */
3422 channel = silc_server_create_new_channel(server, server->id, cipher,
3423 hmac, channel_name, TRUE);
3425 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3426 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3430 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3438 /* Channel not found */
3440 /* If the command came from router and we are normal server then
3441 something went wrong with the joining as the channel was not found.
3442 We can't do anything else but ignore this. */
3443 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3444 server->server_type != SILC_ROUTER)
3447 /* We are router and the channel does not seem exist so we will check
3448 our global list as well for the channel. */
3449 channel = silc_idlist_find_channel_by_name(server->global_list,
3450 channel_name, NULL);
3452 /* Channel really does not exist, create it */
3453 channel = silc_server_create_new_channel(server, server->id, cipher,
3454 hmac, channel_name, TRUE);
3456 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3457 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3461 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3468 /* Check whether the channel was created by our router */
3469 if (cmd->pending && context2) {
3470 SilcServerCommandReplyContext reply =
3471 (SilcServerCommandReplyContext)context2;
3473 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3474 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3475 SILC_GET32_MSB(created, tmp);
3476 if (silc_argument_get_arg_type(reply->args, 7, NULL))
3477 create_key = FALSE; /* Router returned the key already */
3480 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
3481 !silc_hash_table_count(channel->user_list))
3485 /* If the channel does not have global users and is also empty the client
3486 will be the channel founder and operator. */
3487 if (!channel->global_users && !silc_hash_table_count(channel->user_list))
3488 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3490 /* Join to the channel */
3491 silc_server_command_join_channel(server, cmd, channel, client_id,
3492 created, create_key, umode,
3495 silc_free(client_id);
3498 silc_server_command_free(cmd);
3501 /* Server side of command MOTD. Sends server's current "message of the
3502 day" to the client. */
3504 SILC_SERVER_CMD_FUNC(motd)
3506 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3507 SilcServer server = cmd->server;
3508 SilcBuffer packet, idp;
3509 char *motd, *dest_server;
3510 SilcUInt32 motd_len;
3511 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3513 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3515 /* Get server name */
3516 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3518 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3519 SILC_STATUS_ERR_NO_SUCH_SERVER);
3523 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3526 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3528 if (server->config && server->config->server_info &&
3529 server->config->server_info->motd_file) {
3531 motd = silc_file_readfile(server->config->server_info->motd_file, &motd_len);
3536 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3537 SILC_STATUS_OK, ident, 2,
3542 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3543 SILC_STATUS_OK, ident, 1,
3547 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3548 packet->data, packet->len, FALSE);
3549 silc_buffer_free(packet);
3550 silc_buffer_free(idp);
3552 SilcServerEntry entry;
3554 /* Check whether we have this server cached */
3555 entry = silc_idlist_find_server_by_name(server->global_list,
3556 dest_server, TRUE, NULL);
3558 entry = silc_idlist_find_server_by_name(server->local_list,
3559 dest_server, TRUE, NULL);
3562 if (server->server_type != SILC_SERVER && !cmd->pending &&
3563 entry && !entry->motd) {
3564 /* Send to the server */
3566 SilcUInt16 old_ident;
3568 old_ident = silc_command_get_ident(cmd->payload);
3569 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3570 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3572 silc_server_packet_send(server, entry->connection,
3573 SILC_PACKET_COMMAND, cmd->packet->flags,
3574 tmpbuf->data, tmpbuf->len, TRUE);
3576 /* Reprocess this packet after received reply from router */
3577 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3578 silc_command_get_ident(cmd->payload),
3579 silc_server_command_motd,
3580 silc_server_command_dup(cmd));
3581 cmd->pending = TRUE;
3582 silc_command_set_ident(cmd->payload, old_ident);
3583 silc_buffer_free(tmpbuf);
3587 if (!entry && !cmd->pending && !server->standalone) {
3588 /* Send to the primary router */
3590 SilcUInt16 old_ident;
3592 old_ident = silc_command_get_ident(cmd->payload);
3593 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3594 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3596 silc_server_packet_send(server, server->router->connection,
3597 SILC_PACKET_COMMAND, cmd->packet->flags,
3598 tmpbuf->data, tmpbuf->len, TRUE);
3600 /* Reprocess this packet after received reply from router */
3601 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3602 silc_command_get_ident(cmd->payload),
3603 silc_server_command_motd,
3604 silc_server_command_dup(cmd));
3605 cmd->pending = TRUE;
3606 silc_command_set_ident(cmd->payload, old_ident);
3607 silc_buffer_free(tmpbuf);
3612 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3613 SILC_STATUS_ERR_NO_SUCH_SERVER);
3617 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3618 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3619 SILC_STATUS_OK, ident, 2,
3623 strlen(entry->motd) : 0);
3624 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3625 packet->data, packet->len, FALSE);
3626 silc_buffer_free(packet);
3627 silc_buffer_free(idp);
3631 silc_server_command_free(cmd);
3634 /* Server side of command UMODE. Client can use this command to set/unset
3635 user mode. Client actually cannot set itself to be as server/router
3636 operator so this can be used only to unset the modes. */
3638 SILC_SERVER_CMD_FUNC(umode)
3640 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3641 SilcServer server = cmd->server;
3642 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3644 unsigned char *tmp_mask;
3646 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3648 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3651 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 2, 2);
3653 /* Get the client's mode mask */
3654 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3656 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3657 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3660 SILC_GET32_MSB(mask, tmp_mask);
3666 if (mask & SILC_UMODE_SERVER_OPERATOR) {
3667 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR)) {
3668 /* Cannot operator mode */
3669 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3670 SILC_STATUS_ERR_PERM_DENIED);
3674 /* Remove the server operator rights */
3675 if (client->mode & SILC_UMODE_SERVER_OPERATOR) {
3676 client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3677 if (client->connection)
3678 server->stat.my_server_ops--;
3679 if (server->server_type == SILC_ROUTER)
3680 server->stat.server_ops--;
3684 if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3685 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
3686 /* Cannot operator mode */
3687 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3688 SILC_STATUS_ERR_PERM_DENIED);
3692 /* Remove the router operator rights */
3693 if (client->mode & SILC_UMODE_ROUTER_OPERATOR) {
3694 client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3695 if (client->connection)
3696 server->stat.my_router_ops--;
3697 if (server->server_type == SILC_ROUTER)
3698 server->stat.router_ops--;
3702 if (mask & SILC_UMODE_GONE) {
3703 client->mode |= SILC_UMODE_GONE;
3705 if (client->mode & SILC_UMODE_GONE)
3706 /* Remove the gone status */
3707 client->mode &= ~SILC_UMODE_GONE;
3710 /* Send UMODE change to primary router */
3711 if (!server->standalone)
3712 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3713 client->id, client->mode);
3715 /* Send command reply to sender */
3716 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3717 SILC_STATUS_OK, ident, 1,
3719 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3720 packet->data, packet->len, FALSE);
3721 silc_buffer_free(packet);
3724 silc_server_command_free(cmd);
3727 /* Checks that client has rights to add or remove channel modes. If any
3728 of the checks fails FALSE is returned. */
3730 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3731 SilcChannelClientEntry client,
3734 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3735 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3737 /* Check whether has rights to change anything */
3738 if (!is_op && !is_fo)
3741 /* Check whether has rights to change everything */
3745 /* We know that client is channel operator, check that they are not
3746 changing anything that requires channel founder rights. Rest of the
3747 modes are available automatically for channel operator. */
3749 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3750 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3751 if (is_op && !is_fo)
3754 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3755 if (is_op && !is_fo)
3760 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3761 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE))
3762 if (is_op && !is_fo)
3765 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3766 if (is_op && !is_fo)
3771 if (mode & SILC_CHANNEL_MODE_CIPHER) {
3772 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER))
3773 if (is_op && !is_fo)
3776 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3777 if (is_op && !is_fo)
3782 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3783 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH))
3784 if (is_op && !is_fo)
3787 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3788 if (is_op && !is_fo)
3796 /* Server side command of CMODE. Changes channel mode */
3798 SILC_SERVER_CMD_FUNC(cmode)
3800 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3801 SilcServer server = cmd->server;
3802 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3803 SilcIDListData idata = (SilcIDListData)client;
3804 SilcChannelID *channel_id;
3805 SilcChannelEntry channel;
3806 SilcChannelClientEntry chl;
3807 SilcBuffer packet, cidp;
3808 unsigned char *tmp, *tmp_id, *tmp_mask;
3809 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3810 SilcUInt32 mode_mask, tmp_len, tmp_len2;
3811 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3813 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 2, 7);
3815 /* Get Channel ID */
3816 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3818 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3819 SILC_STATUS_ERR_NO_CHANNEL_ID);
3822 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3824 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3825 SILC_STATUS_ERR_NO_CHANNEL_ID);
3829 /* Get the channel mode mask */
3830 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3832 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3833 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3836 SILC_GET32_MSB(mode_mask, tmp_mask);
3838 /* Get channel entry */
3839 channel = silc_idlist_find_channel_by_id(server->local_list,
3842 channel = silc_idlist_find_channel_by_id(server->global_list,
3845 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3846 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3851 /* Check whether this client is on the channel */
3852 if (!silc_server_client_on_channel(client, channel)) {
3853 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3854 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3858 /* Get entry to the channel user list */
3859 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
3861 /* Check that client has rights to change any requested channel modes */
3862 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3863 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3864 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3869 * Check the modes. Modes that requires nothing special operation are
3873 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3874 /* Channel uses private keys to protect traffic. Client(s) has set the
3875 key locally they want to use, server does not know that key. */
3876 /* Nothing interesting to do here */
3878 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3879 /* The mode is removed and we need to generate and distribute
3880 new channel key. Clients are not using private channel keys
3881 anymore after this. */
3883 /* Re-generate channel key */
3884 if (!silc_server_create_channel_key(server, channel, 0))
3887 /* Send the channel key. This sends it to our local clients and if
3888 we are normal server to our router as well. */
3889 silc_server_send_channel_key(server, NULL, channel,
3890 server->server_type == SILC_ROUTER ?
3891 FALSE : !server->standalone);
3893 cipher = channel->channel_key->cipher->name;
3894 hmac = (char *)silc_hmac_get_name(channel->hmac);
3898 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3899 /* User limit is set on channel */
3900 SilcUInt32 user_limit;
3902 /* Get user limit */
3903 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3905 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3906 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3907 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3911 SILC_GET32_MSB(user_limit, tmp);
3912 channel->user_limit = user_limit;
3915 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3916 /* User limit mode is unset. Remove user limit */
3917 channel->user_limit = 0;
3920 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3921 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3922 /* Passphrase has been set to channel */
3924 /* Get the passphrase */
3925 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3927 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3928 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3932 /* Save the passphrase */
3933 passphrase = channel->passphrase = strdup(tmp);
3936 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3937 /* Passphrase mode is unset. remove the passphrase */
3938 if (channel->passphrase) {
3939 silc_free(channel->passphrase);
3940 channel->passphrase = NULL;
3945 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3946 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3947 /* Cipher to use protect the traffic */
3948 SilcCipher newkey, oldkey;
3951 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3953 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3954 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3958 /* Delete old cipher and allocate the new one */
3959 if (!silc_cipher_alloc(cipher, &newkey)) {
3960 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3961 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3965 oldkey = channel->channel_key;
3966 channel->channel_key = newkey;
3968 /* Re-generate channel key */
3969 if (!silc_server_create_channel_key(server, channel, 0)) {
3970 /* We don't have new key, revert to old one */
3971 channel->channel_key = oldkey;
3975 /* Remove old channel key for good */
3976 silc_cipher_free(oldkey);
3978 /* Send the channel key. This sends it to our local clients and if
3979 we are normal server to our router as well. */
3980 silc_server_send_channel_key(server, NULL, channel,
3981 server->server_type == SILC_ROUTER ?
3982 FALSE : !server->standalone);
3985 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3986 /* Cipher mode is unset. Remove the cipher and revert back to
3988 SilcCipher newkey, oldkey;
3989 cipher = channel->cipher;
3991 /* Delete old cipher and allocate default one */
3992 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
3993 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3994 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3998 oldkey = channel->channel_key;
3999 channel->channel_key = newkey;
4001 /* Re-generate channel key */
4002 if (!silc_server_create_channel_key(server, channel, 0)) {
4003 /* We don't have new key, revert to old one */
4004 channel->channel_key = oldkey;
4008 /* Remove old channel key for good */
4009 silc_cipher_free(oldkey);
4011 /* Send the channel key. This sends it to our local clients and if
4012 we are normal server to our router as well. */
4013 silc_server_send_channel_key(server, NULL, channel,
4014 server->server_type == SILC_ROUTER ?
4015 FALSE : !server->standalone);
4019 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
4020 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
4021 /* HMAC to use protect the traffic */
4022 unsigned char hash[32];
4026 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4028 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4029 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4033 /* Delete old hmac and allocate the new one */
4034 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4035 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4036 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4040 silc_hmac_free(channel->hmac);
4041 channel->hmac = newhmac;
4043 /* Set the HMAC key out of current channel key. The client must do
4045 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4046 channel->key_len / 8, hash);
4047 silc_hmac_set_key(channel->hmac, hash,
4048 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4049 memset(hash, 0, sizeof(hash));
4052 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4053 /* Hmac mode is unset. Remove the hmac and revert back to
4056 unsigned char hash[32];
4057 hmac = channel->hmac_name;
4059 /* Delete old hmac and allocate default one */
4060 silc_hmac_free(channel->hmac);
4061 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4062 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4063 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4067 silc_hmac_free(channel->hmac);
4068 channel->hmac = newhmac;
4070 /* Set the HMAC key out of current channel key. The client must do
4072 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4073 channel->key_len / 8,
4075 silc_hmac_set_key(channel->hmac, hash,
4076 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4077 memset(hash, 0, sizeof(hash));
4081 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4082 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4083 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4084 /* Set the founder authentication */
4085 SilcAuthPayload auth;
4087 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4089 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4090 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4094 auth = silc_auth_payload_parse(tmp, tmp_len);
4096 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4097 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4101 /* Save the public key */
4102 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
4103 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
4106 channel->founder_method = silc_auth_get_method(auth);
4108 if (channel->founder_method == SILC_AUTH_PASSWORD) {
4109 tmp = silc_auth_get_data(auth, &tmp_len);
4110 channel->founder_passwd = silc_memdup(tmp, tmp_len);
4111 channel->founder_passwd_len = tmp_len;
4113 /* Verify the payload before setting the mode */
4114 if (!silc_auth_verify(auth, channel->founder_method,
4115 channel->founder_key, 0, idata->hash,
4116 client->id, SILC_ID_CLIENT)) {
4117 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4118 SILC_STATUS_ERR_AUTH_FAILED);
4123 silc_auth_payload_free(auth);
4127 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4128 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4129 if (channel->founder_key)
4130 silc_pkcs_public_key_free(channel->founder_key);
4131 if (channel->founder_passwd) {
4132 silc_free(channel->founder_passwd);
4133 channel->founder_passwd = NULL;
4139 /* Finally, set the mode */
4140 channel->mode = mode_mask;
4142 /* Send CMODE_CHANGE notify. */
4143 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4144 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4145 SILC_NOTIFY_TYPE_CMODE_CHANGE, 5,
4146 cidp->data, cidp->len,
4148 cipher, cipher ? strlen(cipher) : 0,
4149 hmac, hmac ? strlen(hmac) : 0,
4150 passphrase, passphrase ?
4151 strlen(passphrase) : 0);
4153 /* Set CMODE notify type to network */
4154 if (!server->standalone)
4155 silc_server_send_notify_cmode(server, server->router->connection,
4156 server->server_type == SILC_ROUTER ?
4157 TRUE : FALSE, channel,
4158 mode_mask, client->id, SILC_ID_CLIENT,
4159 cipher, hmac, passphrase);
4161 /* Send command reply to sender */
4162 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4163 SILC_STATUS_OK, ident, 2,
4164 2, tmp_id, tmp_len2,
4166 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4167 packet->data, packet->len, FALSE);
4169 silc_buffer_free(packet);
4170 silc_free(channel_id);
4171 silc_buffer_free(cidp);
4174 silc_server_command_free(cmd);
4177 /* Server side of CUMODE command. Changes client's mode on a channel. */
4179 SILC_SERVER_CMD_FUNC(cumode)
4181 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4182 SilcServer server = cmd->server;
4183 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4184 SilcIDListData idata = (SilcIDListData)client;
4185 SilcChannelID *channel_id;
4186 SilcClientID *client_id;
4187 SilcChannelEntry channel;
4188 SilcClientEntry target_client;
4189 SilcChannelClientEntry chl;
4190 SilcBuffer packet, idp;
4191 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4192 SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4194 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4196 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4198 /* Get Channel ID */
4199 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4201 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4202 SILC_STATUS_ERR_NO_CHANNEL_ID);
4205 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
4207 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4208 SILC_STATUS_ERR_NO_CHANNEL_ID);
4212 /* Get channel entry */
4213 channel = silc_idlist_find_channel_by_id(server->local_list,
4216 channel = silc_idlist_find_channel_by_id(server->global_list,
4219 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4220 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4225 /* Check whether sender is on the channel */
4226 if (!silc_server_client_on_channel(client, channel)) {
4227 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4228 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4232 /* Check that client has rights to change other's rights */
4233 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4234 sender_mask = chl->mode;
4236 /* Get the target client's channel mode mask */
4237 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4239 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4240 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4243 SILC_GET32_MSB(target_mask, tmp_mask);
4245 /* Get target Client ID */
4246 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4248 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4249 SILC_STATUS_ERR_NO_CLIENT_ID);
4252 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
4254 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4255 SILC_STATUS_ERR_NO_CLIENT_ID);
4259 /* Get target client's entry */
4260 target_client = silc_idlist_find_client_by_id(server->local_list,
4261 client_id, TRUE, NULL);
4262 if (!target_client) {
4263 target_client = silc_idlist_find_client_by_id(server->global_list,
4264 client_id, TRUE, NULL);
4267 if (target_client != client &&
4268 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4269 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4270 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4271 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4275 /* Check whether target client is on the channel */
4276 if (target_client != client) {
4277 if (!silc_server_client_on_channel(target_client, channel)) {
4278 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4279 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4283 /* Get entry to the channel user list */
4284 silc_hash_table_find(channel->user_list, target_client, NULL,
4292 /* If the target client is founder, no one else can change their mode
4294 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4295 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4296 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4300 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4301 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4302 /* The client tries to claim the founder rights. */
4303 unsigned char *tmp_auth;
4304 SilcUInt32 tmp_auth_len, auth_len;
4307 if (target_client != client) {
4308 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4309 SILC_STATUS_ERR_NOT_YOU);
4313 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4314 !channel->founder_key || !idata->public_key ||
4315 !silc_pkcs_public_key_compare(channel->founder_key,
4316 idata->public_key)) {
4317 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4318 SILC_STATUS_ERR_NOT_YOU);
4322 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4324 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4325 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4329 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4330 (void *)channel->founder_passwd : (void *)channel->founder_key);
4331 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4332 channel->founder_passwd_len : 0);
4334 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4335 channel->founder_method, auth, auth_len,
4336 idata->hash, client->id, SILC_ID_CLIENT)) {
4337 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4338 SILC_STATUS_ERR_AUTH_FAILED);
4342 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4346 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4347 if (target_client == client) {
4348 /* Remove channel founder rights from itself */
4349 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4352 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4353 SILC_STATUS_ERR_NOT_YOU);
4359 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4360 /* Promote to operator */
4361 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4362 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4363 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4364 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4365 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4369 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4373 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4374 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4375 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4376 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4377 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4381 /* Demote to normal user */
4382 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4387 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4388 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4390 /* Send notify to channel, notify only if mode was actually changed. */
4392 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4393 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4394 idp->data, idp->len,
4398 /* Set CUMODE notify type to network */
4399 if (!server->standalone)
4400 silc_server_send_notify_cumode(server, server->router->connection,
4401 server->server_type == SILC_ROUTER ?
4402 TRUE : FALSE, channel,
4403 target_mask, client->id,
4408 /* Send command reply to sender */
4409 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4410 SILC_STATUS_OK, ident, 3,
4412 3, tmp_ch_id, tmp_ch_len,
4413 4, tmp_id, tmp_len);
4414 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4415 packet->data, packet->len, FALSE);
4417 silc_buffer_free(packet);
4418 silc_free(channel_id);
4419 silc_free(client_id);
4420 silc_buffer_free(idp);
4423 silc_server_command_free(cmd);
4426 /* Server side of KICK command. Kicks client out of channel. */
4428 SILC_SERVER_CMD_FUNC(kick)
4430 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4431 SilcServer server = cmd->server;
4432 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4433 SilcClientEntry target_client;
4434 SilcChannelID *channel_id;
4435 SilcClientID *client_id;
4436 SilcChannelEntry channel;
4437 SilcChannelClientEntry chl;
4439 SilcUInt32 tmp_len, target_idp_len;
4440 unsigned char *tmp, *comment, *target_idp;
4442 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4444 /* Get Channel ID */
4445 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4447 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4448 SILC_STATUS_ERR_NO_CHANNEL_ID);
4451 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
4453 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4454 SILC_STATUS_ERR_NO_CHANNEL_ID);
4458 /* Get channel entry */
4459 channel = silc_idlist_find_channel_by_id(server->local_list,
4462 channel = silc_idlist_find_channel_by_id(server->local_list,
4465 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4466 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4471 /* Check whether sender is on the channel */
4472 if (!silc_server_client_on_channel(client, channel)) {
4473 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4474 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4478 /* Check that the kicker is channel operator or channel founder */
4479 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4480 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4481 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4482 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4486 /* Get target Client ID */
4487 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4489 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4490 SILC_STATUS_ERR_NO_CLIENT_ID);
4493 client_id = silc_id_payload_parse_id(target_idp, target_idp_len);
4495 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4496 SILC_STATUS_ERR_NO_CLIENT_ID);
4500 /* Get target client's entry */
4501 target_client = silc_idlist_find_client_by_id(server->local_list,
4502 client_id, TRUE, NULL);
4503 if (!target_client) {
4504 target_client = silc_idlist_find_client_by_id(server->global_list,
4505 client_id, TRUE, NULL);
4508 /* Check that the target client is not channel founder. Channel founder
4509 cannot be kicked from the channel. */
4510 silc_hash_table_find(channel->user_list, target_client, NULL, (void *)&chl);
4511 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4512 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4513 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4517 /* Check whether target client is on the channel */
4518 if (!silc_server_client_on_channel(target_client, channel)) {
4519 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4520 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4526 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4530 /* Send command reply to sender */
4531 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4534 /* Send KICKED notify to local clients on the channel */
4535 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4536 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4537 SILC_NOTIFY_TYPE_KICKED, 3,
4538 target_idp, target_idp_len,
4539 comment, comment ? strlen(comment) : 0,
4540 idp->data, idp->len);
4541 silc_buffer_free(idp);
4543 /* Remove the client from the channel. If the channel does not exist
4544 after removing the client then the client kicked itself off the channel
4545 and we don't have to send anything after that. */
4546 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4547 target_client, FALSE))
4550 /* Send KICKED notify to primary route */
4551 if (!server->standalone)
4552 silc_server_send_notify_kicked(server, server->router->connection,
4553 server->server_type == SILC_ROUTER ?
4554 TRUE : FALSE, channel,
4555 target_client->id, client->id, comment);
4557 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4558 /* Re-generate channel key */
4559 if (!silc_server_create_channel_key(server, channel, 0))
4562 /* Send the channel key to the channel. The key of course is not sent
4563 to the client who was kicked off the channel. */
4564 silc_server_send_channel_key(server, target_client->connection, channel,
4565 server->server_type == SILC_ROUTER ?
4566 FALSE : !server->standalone);
4570 silc_server_command_free(cmd);
4573 /* Server side of OPER command. Client uses this comand to obtain server
4574 operator privileges to this server/router. */
4576 SILC_SERVER_CMD_FUNC(oper)
4578 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4579 SilcServer server = cmd->server;
4580 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4581 unsigned char *username, *auth;
4583 SilcServerConfigAdmin *admin;
4584 SilcIDListData idata = (SilcIDListData)client;
4585 bool result = FALSE;
4587 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4589 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4592 /* Get the username */
4593 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4595 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4596 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4600 /* Get the admin configuration */
4601 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4602 username, client->nickname);
4604 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4605 username, client->nickname);
4607 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4608 SILC_STATUS_ERR_AUTH_FAILED);
4613 /* Get the authentication payload */
4614 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4616 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4617 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4621 /* Verify the authentication data. If both passphrase and public key
4622 is set then try both of them. */
4623 if (admin->passphrase)
4624 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4625 admin->passphrase, admin->passphrase_len,
4626 idata->hash, client->id, SILC_ID_CLIENT);
4627 if (!result && admin->publickey)
4628 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4629 admin->publickey, 0,
4630 idata->hash, client->id, SILC_ID_CLIENT);
4632 /* Authentication failed */
4633 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4634 SILC_STATUS_ERR_AUTH_FAILED);
4638 /* Client is now server operator */
4639 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4641 /* Update statistics */
4642 if (client->connection)
4643 server->stat.my_server_ops++;
4644 if (server->server_type == SILC_ROUTER)
4645 server->stat.server_ops++;
4647 /* Send UMODE change to primary router */
4648 if (!server->standalone)
4649 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4650 client->id, client->mode);
4652 /* Send reply to the sender */
4653 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4657 silc_server_command_free(cmd);
4660 /* Server side of SILCOPER command. Client uses this comand to obtain router
4661 operator privileges to this router. */
4663 SILC_SERVER_CMD_FUNC(silcoper)
4665 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4666 SilcServer server = cmd->server;
4667 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4668 unsigned char *username, *auth;
4670 SilcServerConfigAdmin *admin;
4671 SilcIDListData idata = (SilcIDListData)client;
4672 bool result = FALSE;
4674 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4676 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4679 if (server->server_type != SILC_ROUTER) {
4680 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4681 SILC_STATUS_ERR_AUTH_FAILED);
4685 /* Get the username */
4686 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4688 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4689 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4693 /* Get the admin configuration */
4694 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4695 username, client->nickname);
4697 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4698 username, client->nickname);
4700 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4701 SILC_STATUS_ERR_AUTH_FAILED);
4706 /* Get the authentication payload */
4707 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4709 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4710 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4714 /* Verify the authentication data. If both passphrase and public key
4715 is set then try both of them. */
4716 if (admin->passphrase)
4717 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4718 admin->passphrase, admin->passphrase_len,
4719 idata->hash, client->id, SILC_ID_CLIENT);
4720 if (!result && admin->publickey)
4721 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4722 admin->publickey, 0,
4723 idata->hash, client->id, SILC_ID_CLIENT);
4725 /* Authentication failed */
4726 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4727 SILC_STATUS_ERR_AUTH_FAILED);
4731 /* Client is now router operator */
4732 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4734 /* Update statistics */
4735 if (client->connection)
4736 server->stat.my_router_ops++;
4737 if (server->server_type == SILC_ROUTER)
4738 server->stat.router_ops++;
4740 /* Send UMODE change to primary router */
4741 if (!server->standalone)
4742 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4743 client->id, client->mode);
4745 /* Send reply to the sender */
4746 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4750 silc_server_command_free(cmd);
4753 /* Server side command of CONNECT. Connects us to the specified remote
4754 server or router. */
4756 SILC_SERVER_CMD_FUNC(connect)
4758 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4759 SilcServer server = cmd->server;
4760 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4761 unsigned char *tmp, *host;
4763 SilcUInt32 port = SILC_PORT;
4765 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CONNECT, cmd, 1, 2);
4767 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4770 /* Check whether client has the permissions. */
4771 if (client->mode == SILC_UMODE_NONE) {
4772 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4773 SILC_STATUS_ERR_NO_SERVER_PRIV);
4777 if (server->server_type == SILC_ROUTER &&
4778 client->mode & SILC_UMODE_SERVER_OPERATOR) {
4779 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4780 SILC_STATUS_ERR_NO_ROUTER_PRIV);
4784 /* Get the remote server */
4785 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4787 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4788 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4793 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4795 SILC_GET32_MSB(port, tmp);
4797 /* Create the connection. It is done with timeout and is async. */
4798 silc_server_create_connection(server, host, port);
4800 /* Send reply to the sender */
4801 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4805 silc_server_command_free(cmd);
4808 /* Server side of command BAN. This is used to manage the ban list of the
4809 channel. To add clients and remove clients from the ban list. */
4811 SILC_SERVER_CMD_FUNC(ban)
4813 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4814 SilcServer server = cmd->server;
4815 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4817 SilcChannelEntry channel;
4818 SilcChannelClientEntry chl;
4819 SilcChannelID *channel_id = NULL;
4820 unsigned char *id, *add, *del;
4821 SilcUInt32 id_len, tmp_len;
4822 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4824 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4827 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4829 /* Get Channel ID */
4830 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4832 channel_id = silc_id_payload_parse_id(id, id_len);
4834 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4835 SILC_STATUS_ERR_NO_CHANNEL_ID);
4840 /* Get channel entry. The server must know about the channel since the
4841 client is expected to be on the channel. */
4842 channel = silc_idlist_find_channel_by_id(server->local_list,
4845 channel = silc_idlist_find_channel_by_id(server->global_list,
4848 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4849 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4854 /* Check whether this client is on the channel */
4855 if (!silc_server_client_on_channel(client, channel)) {
4856 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4857 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4861 /* Get entry to the channel user list */
4862 if (!silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl)) {
4863 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4864 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4868 /* The client must be at least channel operator. */
4869 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4870 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4871 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4875 /* Get the new ban and add it to the ban list */
4876 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4878 if (!channel->ban_list)
4879 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4881 channel->ban_list = silc_realloc(channel->ban_list,
4882 sizeof(*channel->ban_list) *
4884 strlen(channel->ban_list) + 2));
4885 if (add[tmp_len - 1] == ',')
4886 add[tmp_len - 1] = '\0';
4888 strncat(channel->ban_list, add, tmp_len);
4889 strncat(channel->ban_list, ",", 1);
4892 /* Get the ban to be removed and remove it from the list */
4893 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4894 if (del && channel->ban_list) {
4895 char *start, *end, *n;
4897 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4898 silc_free(channel->ban_list);
4899 channel->ban_list = NULL;
4901 start = strstr(channel->ban_list, del);
4902 if (start && strlen(start) >= tmp_len) {
4903 end = start + tmp_len;
4904 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4905 strncat(n, channel->ban_list, start - channel->ban_list);
4906 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4908 silc_free(channel->ban_list);
4909 channel->ban_list = n;
4914 /* Send the BAN notify type to our primary router. */
4915 if (!server->standalone && (add || del))
4916 silc_server_send_notify_ban(server, server->router->connection,
4917 server->server_type == SILC_ROUTER ?
4918 TRUE : FALSE, channel, add, del);
4920 /* Send the reply back to the client */
4922 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4923 SILC_STATUS_OK, ident, 2,
4925 3, channel->ban_list,
4927 strlen(channel->ban_list) -1 : 0);
4928 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4929 packet->data, packet->len, FALSE);
4931 silc_buffer_free(packet);
4934 silc_free(channel_id);
4935 silc_server_command_free(cmd);
4938 /* Server side command of CLOSE. Closes connection to a specified server. */
4940 SILC_SERVER_CMD_FUNC(close)
4942 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4943 SilcServer server = cmd->server;
4944 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4945 SilcServerEntry server_entry;
4946 SilcSocketConnection sock;
4949 unsigned char *name;
4950 SilcUInt32 port = SILC_PORT;
4952 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CLOSE, cmd, 1, 2);
4954 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4957 /* Check whether client has the permissions. */
4958 if (client->mode == SILC_UMODE_NONE) {
4959 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4960 SILC_STATUS_ERR_NO_SERVER_PRIV);
4964 /* Get the remote server */
4965 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4967 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4968 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4973 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4975 SILC_GET32_MSB(port, tmp);
4977 server_entry = silc_idlist_find_server_by_conn(server->local_list,
4978 name, port, FALSE, NULL);
4980 server_entry = silc_idlist_find_server_by_conn(server->global_list,
4981 name, port, FALSE, NULL);
4982 if (!server_entry) {
4983 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4984 SILC_STATUS_ERR_NO_SERVER_ID);
4988 /* Send reply to the sender */
4989 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4992 /* Close the connection to the server */
4993 sock = (SilcSocketConnection)server_entry->connection;
4995 /* If we shutdown primary router connection manually then don't trigger
4996 any reconnect or backup router connections, by setting the router
4998 if (server->router == server_entry) {
4999 server->id_entry->router = NULL;
5000 server->router = NULL;
5001 server->standalone = TRUE;
5003 silc_server_free_sock_user_data(server, sock, NULL);
5004 silc_server_close_connection(server, sock);
5007 silc_server_command_free(cmd);
5010 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
5011 active connections. */
5013 SILC_SERVER_CMD_FUNC(shutdown)
5015 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5016 SilcServer server = cmd->server;
5017 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5019 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
5021 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5024 /* Check whether client has the permission. */
5025 if (client->mode == SILC_UMODE_NONE) {
5026 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
5027 SILC_STATUS_ERR_NO_SERVER_PRIV);
5031 /* Send reply to the sender */
5032 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
5035 /* Then, gracefully, or not, bring the server down. */
5036 silc_server_stop(server);
5040 silc_server_command_free(cmd);
5043 /* Server side command of LEAVE. Removes client from a channel. */
5045 SILC_SERVER_CMD_FUNC(leave)
5047 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5048 SilcServer server = cmd->server;
5049 SilcSocketConnection sock = cmd->sock;
5050 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
5051 SilcChannelID *id = NULL;
5052 SilcChannelEntry channel;
5056 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
5058 /* Get Channel ID */
5059 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
5061 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5062 SILC_STATUS_ERR_NO_CHANNEL_ID);
5065 id = silc_id_payload_parse_id(tmp, len);
5067 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5068 SILC_STATUS_ERR_NO_CHANNEL_ID);
5072 /* Get channel entry */
5073 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5075 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5077 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5078 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5083 /* Check whether this client is on the channel */
5084 if (!silc_server_client_on_channel(id_entry, channel)) {
5085 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5086 SILC_STATUS_ERR_NOT_ON_CHANNEL);
5090 /* Notify routers that they should remove this client from their list
5091 of clients on the channel. Send LEAVE notify type. */
5092 if (!server->standalone)
5093 silc_server_send_notify_leave(server, server->router->connection,
5094 server->server_type == SILC_ROUTER ?
5095 TRUE : FALSE, channel, id_entry->id);
5097 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5100 /* Remove client from channel */
5101 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5103 /* If the channel does not exist anymore we won't send anything */
5106 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5107 /* Re-generate channel key */
5108 if (!silc_server_create_channel_key(server, channel, 0))
5111 /* Send the channel key */
5112 silc_server_send_channel_key(server, NULL, channel,
5113 server->server_type == SILC_ROUTER ?
5114 FALSE : !server->standalone);
5119 silc_server_command_free(cmd);
5122 /* Server side of command USERS. Resolves clients and their USERS currently
5123 joined on the requested channel. The list of Client ID's and their modes
5124 on the channel is sent back. */
5126 SILC_SERVER_CMD_FUNC(users)
5128 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5129 SilcServer server = cmd->server;
5130 SilcChannelEntry channel;
5131 SilcChannelID *id = NULL;
5132 SilcBuffer packet, idp;
5133 unsigned char *channel_id;
5134 SilcUInt32 channel_id_len;
5135 SilcBuffer client_id_list;
5136 SilcBuffer client_mode_list;
5137 unsigned char lc[4];
5138 SilcUInt32 list_count = 0;
5139 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5142 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5144 /* Get Channel ID */
5145 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5147 /* Get channel name */
5148 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5150 if (!channel_id && !channel_name) {
5151 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5152 SILC_STATUS_ERR_NO_CHANNEL_ID);
5157 id = silc_id_payload_parse_id(channel_id, channel_id_len);
5159 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5160 SILC_STATUS_ERR_NO_CHANNEL_ID);
5165 /* If we are server and we don't know about this channel we will send
5166 the command to our router. If we know about the channel then we also
5167 have the list of users already. */
5169 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5171 channel = silc_idlist_find_channel_by_name(server->local_list,
5172 channel_name, NULL);
5174 if (!channel || channel->disabled) {
5175 if (server->server_type != SILC_ROUTER && !server->standalone &&
5179 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5180 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5182 /* Send USERS command */
5183 silc_server_packet_send(server, server->router->connection,
5184 SILC_PACKET_COMMAND, cmd->packet->flags,
5185 tmpbuf->data, tmpbuf->len, TRUE);
5187 /* Reprocess this packet after received reply */
5188 silc_server_command_pending(server, SILC_COMMAND_USERS,
5189 silc_command_get_ident(cmd->payload),
5190 silc_server_command_users,
5191 silc_server_command_dup(cmd));
5192 cmd->pending = TRUE;
5193 silc_command_set_ident(cmd->payload, ident);
5194 silc_buffer_free(tmpbuf);
5199 /* Check the global list as well. */
5201 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5203 channel = silc_idlist_find_channel_by_name(server->global_list,
5204 channel_name, NULL);
5206 /* Channel really does not exist */
5207 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5208 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5213 /* If the channel is private or secret do not send anything, unless the
5214 user requesting this command is on the channel. */
5215 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5216 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5217 && !silc_server_client_on_channel(cmd->sock->user_data, channel)) {
5218 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5219 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5224 (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
5225 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5226 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5231 /* Get the users list */
5232 silc_server_get_users_on_channel(server, channel, &client_id_list,
5233 &client_mode_list, &list_count);
5236 SILC_PUT32_MSB(list_count, lc);
5239 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5240 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5241 SILC_STATUS_OK, ident, 4,
5242 2, idp->data, idp->len,
5244 4, client_id_list->data,
5245 client_id_list->len,
5246 5, client_mode_list->data,
5247 client_mode_list->len);
5248 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5249 packet->data, packet->len, FALSE);
5251 silc_buffer_free(idp);
5252 silc_buffer_free(packet);
5253 silc_buffer_free(client_id_list);
5254 silc_buffer_free(client_mode_list);
5258 silc_server_command_free(cmd);
5261 /* Server side of command GETKEY. This fetches the client's public key
5262 from the server where to the client is connected. */
5264 SILC_SERVER_CMD_FUNC(getkey)
5266 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5267 SilcServer server = cmd->server;
5269 SilcClientEntry client;
5270 SilcServerEntry server_entry;
5271 SilcClientID *client_id = NULL;
5272 SilcServerID *server_id = NULL;
5273 SilcIDPayload idp = NULL;
5274 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5275 unsigned char *tmp, *pkdata;
5276 SilcUInt32 tmp_len, pklen;
5277 SilcBuffer pk = NULL;
5279 SilcPublicKey public_key;
5281 SILC_LOG_DEBUG(("Start"));
5283 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5285 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5286 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5289 idp = silc_id_payload_parse(tmp, tmp_len);
5291 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5292 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5296 id_type = silc_id_payload_get_type(idp);
5297 if (id_type == SILC_ID_CLIENT) {
5298 client_id = silc_id_payload_get_id(idp);
5300 /* If the client is not found from local list there is no chance it
5301 would be locally connected client so send the command further. */
5302 client = silc_idlist_find_client_by_id(server->local_list,
5303 client_id, TRUE, NULL);
5305 client = silc_idlist_find_client_by_id(server->global_list,
5306 client_id, TRUE, NULL);
5308 if ((!client && !cmd->pending && !server->standalone) ||
5309 (client && !client->connection && !cmd->pending) ||
5310 (client && !client->data.public_key && !cmd->pending)) {
5312 SilcUInt16 old_ident;
5313 SilcSocketConnection dest_sock;
5315 dest_sock = silc_server_get_client_route(server, NULL, 0,
5320 old_ident = silc_command_get_ident(cmd->payload);
5321 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5322 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5324 silc_server_packet_send(server, dest_sock,
5325 SILC_PACKET_COMMAND, cmd->packet->flags,
5326 tmpbuf->data, tmpbuf->len, TRUE);
5328 /* Reprocess this packet after received reply from router */
5329 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5330 silc_command_get_ident(cmd->payload),
5331 silc_server_command_getkey,
5332 silc_server_command_dup(cmd));
5333 cmd->pending = TRUE;
5334 silc_command_set_ident(cmd->payload, old_ident);
5335 silc_buffer_free(tmpbuf);
5340 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5341 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5345 /* The client is locally connected, just get the public key and
5346 send it back. If they key does not exist then do not send it,
5347 send just OK reply */
5348 public_key = client->data.public_key;
5353 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5354 pk = silc_buffer_alloc(4 + tmp_len);
5355 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5356 silc_buffer_format(pk,
5357 SILC_STR_UI_SHORT(tmp_len),
5358 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5359 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5365 } else if (id_type == SILC_ID_SERVER) {
5366 server_id = silc_id_payload_get_id(idp);
5368 /* If the server is not found from local list there is no chance it
5369 would be locally connected server so send the command further. */
5370 server_entry = silc_idlist_find_server_by_id(server->local_list,
5371 server_id, TRUE, NULL);
5373 server_entry = silc_idlist_find_server_by_id(server->global_list,
5374 server_id, TRUE, NULL);
5376 if (server_entry != server->id_entry &&
5377 ((!server_entry && !cmd->pending && !server->standalone) ||
5378 (server_entry && !server_entry->connection && !cmd->pending &&
5379 !server->standalone) ||
5380 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5381 !server->standalone))) {
5383 SilcUInt16 old_ident;
5385 old_ident = silc_command_get_ident(cmd->payload);
5386 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5387 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5389 silc_server_packet_send(server, server->router->connection,
5390 SILC_PACKET_COMMAND, cmd->packet->flags,
5391 tmpbuf->data, tmpbuf->len, TRUE);
5393 /* Reprocess this packet after received reply from router */
5394 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5395 silc_command_get_ident(cmd->payload),
5396 silc_server_command_getkey,
5397 silc_server_command_dup(cmd));
5398 cmd->pending = TRUE;
5399 silc_command_set_ident(cmd->payload, old_ident);
5400 silc_buffer_free(tmpbuf);
5404 if (!server_entry) {
5405 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5406 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5410 /* If they key does not exist then do not send it, send just OK reply */
5411 public_key = (!server_entry->data.public_key ?
5412 (server_entry == server->id_entry ? server->public_key :
5413 NULL) : server_entry->data.public_key);
5418 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5419 pk = silc_buffer_alloc(4 + tmp_len);
5420 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5421 silc_buffer_format(pk,
5422 SILC_STR_UI_SHORT(tmp_len),
5423 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5424 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5434 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5435 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5436 SILC_STATUS_OK, ident,
5440 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5441 packet->data, packet->len, FALSE);
5442 silc_buffer_free(packet);
5445 silc_buffer_free(pk);
5449 silc_id_payload_free(idp);
5450 silc_free(client_id);
5451 silc_free(server_id);
5452 silc_server_command_free(cmd);