5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2002 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,
34 silc_server_command_send_status_data(SilcServerCommandContext cmd,
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(stats, STATS, SILC_CF_LAG | SILC_CF_REG),
60 SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
61 SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
62 SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG_STRICT | SILC_CF_REG),
63 SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
64 SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
65 SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG_STRICT | SILC_CF_REG),
66 SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
67 SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
68 SILC_SERVER_CMD(ban, BAN, SILC_CF_LAG_STRICT | SILC_CF_REG),
69 SILC_SERVER_CMD(detach, DETACH, SILC_CF_LAG_STRICT | SILC_CF_REG),
70 SILC_SERVER_CMD(silcoper, SILCOPER,
71 SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
72 SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
73 SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
74 SILC_SERVER_CMD(getkey, GETKEY, SILC_CF_LAG | SILC_CF_REG),
76 SILC_SERVER_CMD(connect, PRIV_CONNECT,
77 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
78 SILC_SERVER_CMD(close, PRIV_CLOSE,
79 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
80 SILC_SERVER_CMD(shutdown, PRIV_SHUTDOWN, SILC_CF_LAG | SILC_CF_REG |
86 /* Performs several checks to the command. It first checks whether this
87 command was called as pending command callback. If it was then it checks
88 whether error occurred in the command reply where the pending command
91 It also checks that the requested command includes correct amount
93 #define SILC_SERVER_COMMAND_CHECK(command, context, min, max) \
97 SILC_LOG_DEBUG(("Start")); \
99 if (silc_server_command_pending_error_check(cmd, context2, command)) { \
100 silc_server_command_free(cmd); \
104 _argc = silc_argument_get_arg_num(cmd->args); \
106 silc_server_command_send_status_reply(cmd, command, \
107 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
108 silc_server_command_free(cmd); \
112 silc_server_command_send_status_reply(cmd, command, \
113 SILC_STATUS_ERR_TOO_MANY_PARAMS); \
114 silc_server_command_free(cmd); \
119 /* Returns TRUE if the connection is registered. Unregistered connections
120 usually cannot send commands hence the check. */
122 static int silc_server_is_registered(SilcServer server,
123 SilcSocketConnection sock,
124 SilcServerCommandContext cmd,
127 SilcIDListData idata = (SilcIDListData)sock->user_data;
132 if (idata->status & SILC_IDLIST_STATUS_REGISTERED)
135 silc_server_command_send_status_reply(cmd, command,
136 SILC_STATUS_ERR_NOT_REGISTERED);
140 /* Internal context to hold data when executed command with timeout. */
142 SilcServerCommandContext ctx;
143 SilcServerCommand *cmd;
144 } *SilcServerCommandTimeout;
146 /* Timeout callback to process commands with timeout for client. Client's
147 commands are always executed with timeout. */
149 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
151 SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
152 SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data;
155 silc_server_command_free(timeout->ctx);
159 /* Update access time */
160 client->last_command = time(NULL);
162 if (!(timeout->cmd->flags & SILC_CF_REG))
163 timeout->cmd->cb(timeout->ctx, NULL);
164 else if (silc_server_is_registered(timeout->ctx->server,
168 timeout->cmd->cb(timeout->ctx, NULL);
170 silc_server_command_free(timeout->ctx);
175 /* Processes received command packet. */
177 void silc_server_command_process(SilcServer server,
178 SilcSocketConnection sock,
179 SilcPacketContext *packet)
181 SilcServerCommandContext ctx;
182 SilcServerCommand *cmd;
185 /* Allocate command context. This must be free'd by the
186 command routine receiving it. */
187 ctx = silc_server_command_alloc();
188 ctx->server = server;
189 ctx->sock = silc_socket_dup(sock);
190 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
192 /* Parse the command payload in the packet */
193 ctx->payload = silc_command_payload_parse(packet->buffer->data,
194 packet->buffer->len);
196 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
197 silc_buffer_free(packet->buffer);
198 silc_packet_context_free(packet);
199 silc_socket_free(ctx->sock);
203 ctx->args = silc_command_get_args(ctx->payload);
205 /* Get the command */
206 command = silc_command_get(ctx->payload);
207 for (cmd = silc_command_list; cmd->cb; cmd++)
208 if (cmd->cmd == command)
211 if (!cmd || !cmd->cb) {
212 silc_server_command_send_status_reply(ctx, command,
213 SILC_STATUS_ERR_UNKNOWN_COMMAND);
214 silc_server_command_free(ctx);
218 /* Execute client's commands always with timeout. Normally they are
219 executed with zero (0) timeout but if client is sending command more
220 frequently than once in 2 seconds, then the timeout may be 0 to 2
222 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
223 SilcClientEntry client = (SilcClientEntry)sock->user_data;
224 SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
230 if (client->last_command && (time(NULL) - client->last_command) < 2) {
231 client->fast_command++;
234 client->fast_command = ((client->fast_command - 1) <= 0 ? 0 :
235 client->fast_command--);
239 if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
240 (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
241 silc_schedule_task_add(server->schedule, sock->sock,
242 silc_server_command_process_timeout,
244 2 - (time(NULL) - client->last_command), 0,
245 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
247 silc_schedule_task_add(server->schedule, sock->sock,
248 silc_server_command_process_timeout,
249 (void *)timeout, 0, 1,
250 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
254 /* Execute for server */
256 if (!(cmd->flags & SILC_CF_REG))
258 else if (silc_server_is_registered(server, sock, ctx, cmd->cmd))
261 silc_server_command_free(ctx);
264 /* Allocate Command Context */
266 SilcServerCommandContext silc_server_command_alloc()
268 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
273 /* Free's the command context allocated before executing the command */
275 void silc_server_command_free(SilcServerCommandContext ctx)
278 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
280 if (ctx->users < 1) {
282 silc_command_payload_free(ctx->payload);
284 silc_packet_context_free(ctx->packet);
286 silc_socket_free(ctx->sock); /* Decrease reference counter */
291 /* Duplicate Command Context by adding reference counter. The context won't
292 be free'd untill it hits zero. */
294 SilcServerCommandContext
295 silc_server_command_dup(SilcServerCommandContext ctx)
298 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
303 /* Add new pending command to be executed when reply to a command has been
304 received. The `reply_cmd' is the command that will call the `callback'
305 with `context' when reply has been received. It can be SILC_COMMAND_NONE
306 to match any command with the `ident'. If `ident' is non-zero
307 the `callback' will be executed when received reply with command
308 identifier `ident'. If there already exists pending command for the
309 specified command, ident, callback and context this function has no
312 bool silc_server_command_pending(SilcServer server,
313 SilcCommand reply_cmd,
315 SilcCommandCb callback,
318 SilcServerCommandPending *reply;
320 /* Check whether identical pending already exists for same command,
321 ident, callback and callback context. If it does then it would be
322 error to register it again. */
323 silc_dlist_start(server->pending_commands);
324 while ((reply = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
325 if (reply->reply_cmd == reply_cmd && reply->ident == ident &&
326 reply->callback == callback && reply->context == context)
330 reply = silc_calloc(1, sizeof(*reply));
331 reply->reply_cmd = reply_cmd;
332 reply->ident = ident;
333 reply->context = context;
334 reply->callback = callback;
335 silc_dlist_add(server->pending_commands, reply);
340 /* Deletes pending command by reply command type. */
342 void silc_server_command_pending_del(SilcServer server,
343 SilcCommand reply_cmd,
346 SilcServerCommandPending *r;
348 silc_dlist_start(server->pending_commands);
349 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
350 if (r->reply_cmd == reply_cmd && r->ident == ident) {
351 silc_dlist_del(server->pending_commands, r);
357 /* Checks for pending commands and marks callbacks to be called from
358 the command reply function. Returns TRUE if there were pending command. */
360 SilcServerCommandPendingCallbacks
361 silc_server_command_pending_check(SilcServer server,
362 SilcServerCommandReplyContext ctx,
365 SilcUInt32 *callbacks_count)
367 SilcServerCommandPending *r;
368 SilcServerCommandPendingCallbacks callbacks = NULL;
371 silc_dlist_start(server->pending_commands);
372 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
373 if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE)
374 && r->ident == ident) {
375 callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
376 callbacks[i].context = r->context;
377 callbacks[i].callback = r->callback;
383 *callbacks_count = i;
387 /* Sends simple status message as command reply packet */
390 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
396 SILC_LOG_DEBUG(("Sending command status %d", status));
399 silc_command_reply_payload_encode_va(command, status, 0,
400 silc_command_get_ident(cmd->payload),
402 silc_server_packet_send(cmd->server, cmd->sock,
403 SILC_PACKET_COMMAND_REPLY, 0,
404 buffer->data, buffer->len, FALSE);
405 silc_buffer_free(buffer);
408 /* Sends command status reply with one extra argument. The argument
409 type must be sent as argument. */
412 silc_server_command_send_status_data(SilcServerCommandContext cmd,
416 const unsigned char *arg,
421 SILC_LOG_DEBUG(("Sending command status %d", status));
424 silc_command_reply_payload_encode_va(command, status, 0,
425 silc_command_get_ident(cmd->payload),
426 1, arg_type, arg, arg_len);
427 silc_server_packet_send(cmd->server, cmd->sock,
428 SILC_PACKET_COMMAND_REPLY, 0,
429 buffer->data, buffer->len, FALSE);
430 silc_buffer_free(buffer);
433 /* This function can be called to check whether in the command reply
434 an error occurred. This function has no effect if this is called
435 when the command function was not called as pending command callback.
436 This returns TRUE if error had occurred. */
439 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
440 SilcServerCommandReplyContext cmdr,
443 if (!cmd->pending || !cmdr)
446 if (!silc_command_get_status(cmdr->payload, NULL, NULL)) {
449 /* Send the same command reply payload */
450 silc_command_set_ident(cmdr->payload,
451 silc_command_get_ident(cmd->payload));
452 buffer = silc_command_payload_encode_payload(cmdr->payload);
453 silc_server_packet_send(cmd->server, cmd->sock,
454 SILC_PACKET_COMMAND_REPLY, 0,
455 buffer->data, buffer->len, FALSE);
456 silc_buffer_free(buffer);
463 /******************************************************************************
467 ******************************************************************************/
470 silc_server_command_whois_parse(SilcServerCommandContext cmd,
471 SilcClientID ***client_id,
472 SilcUInt32 *client_id_count,
480 SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
483 /* If client ID is in the command it must be used instead of nickname */
484 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
486 /* No ID, get the nickname@server string and parse it. */
487 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
489 silc_parse_userfqdn(tmp, nickname, server_name);
491 silc_server_command_send_status_reply(cmd, command,
492 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
496 /* Command includes ID, we must use that. Also check whether the command
497 has more than one ID set - take them all. */
499 *client_id = silc_calloc(1, sizeof(**client_id));
500 (*client_id)[0] = silc_id_payload_parse_id(tmp, len, NULL);
501 if ((*client_id)[0] == NULL) {
502 silc_free(*client_id);
503 silc_server_command_send_status_reply(cmd, command,
504 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
507 *client_id_count = 1;
509 /* Take all ID's from the command packet */
511 for (k = 1, i = 1; i < argc; i++) {
512 tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
514 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
515 (*client_id_count + 1));
516 (*client_id)[k] = silc_id_payload_parse_id(tmp, len, NULL);
517 if ((*client_id)[k] == NULL) {
518 /* Cleanup all and fail */
519 for (i = 0; i < *client_id_count; i++)
520 silc_free((*client_id)[i]);
521 silc_free(*client_id);
522 silc_server_command_send_status_reply(
524 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
527 (*client_id_count)++;
534 /* Get the max count of reply messages allowed */
535 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
537 SILC_GET32_MSB(*count, tmp);
545 /* Resolve context used by both WHOIS and IDENTIFY commands */
547 SilcServerEntry router;
549 unsigned char **res_argv;
550 SilcUInt32 *res_argv_lens;
551 SilcUInt32 *res_argv_types;
553 } *SilcServerResolveContext;
556 silc_server_command_whois_check(SilcServerCommandContext cmd,
557 SilcClientEntry *clients,
558 SilcUInt32 clients_count)
560 SilcServer server = cmd->server;
561 SilcClientEntry entry;
562 SilcServerResolveContext resolve = NULL, r = NULL;
563 SilcUInt32 resolve_count = 0;
567 SILC_LOG_DEBUG(("Start"));
569 for (i = 0; i < clients_count; i++) {
574 if ((entry->nickname && entry->username && entry->userinfo) ||
575 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
579 /* If we are normal server, and we've not resolved this client from
580 router and it is global client, we'll check whether it is on some
581 channel. If not then we cannot be sure about its validity, and
582 we'll resolve it from router. */
583 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
584 entry->connection || silc_hash_table_count(entry->channels))
588 /* We need to resolve this entry since it is not complete */
590 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
591 /* The entry is being resolved (and we are not the resolver) so attach
592 to the command reply and we're done with this one. */
593 silc_server_command_pending(server, SILC_COMMAND_NONE,
594 entry->resolve_cmd_ident,
595 silc_server_command_whois,
596 silc_server_command_dup(cmd));
599 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
600 /* We've resolved this and it still is not ready. We'll return
601 and are that this will be handled again after it is resolved. */
602 for (i = 0; i < resolve_count; i++) {
603 for (k = 0; k < r->res_argc; k++)
604 silc_free(r->res_argv[k]);
605 silc_free(r->res_argv);
606 silc_free(r->res_argv_lens);
607 silc_free(r->res_argv_types);
612 /* We'll resolve this client */
616 for (k = 0; k < resolve_count; k++) {
617 if (resolve[k].router == entry->router) {
624 resolve = silc_realloc(resolve, sizeof(*resolve) *
625 (resolve_count + 1));
626 r = &resolve[resolve_count];
627 memset(r, 0, sizeof(*r));
628 r->router = entry->router;
629 r->ident = ++server->cmd_ident;
633 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
635 r->res_argv_lens = silc_realloc(r->res_argv_lens,
636 sizeof(*r->res_argv_lens) *
638 r->res_argv_types = silc_realloc(r->res_argv_types,
639 sizeof(*r->res_argv_types) *
641 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
642 r->res_argv[r->res_argc] = silc_calloc(idp->len,
643 sizeof(**r->res_argv));
644 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
645 r->res_argv_lens[r->res_argc] = idp->len;
646 r->res_argv_types[r->res_argc] = r->res_argc + 3;
648 silc_buffer_free(idp);
650 entry->resolve_cmd_ident = r->ident;
651 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
652 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
657 /* Do the resolving */
658 for (i = 0; i < resolve_count; i++) {
663 /* Send WHOIS request. We send WHOIS since we're doing the requesting
664 now anyway so make it a good one. */
665 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
666 r->res_argc, r->res_argv,
670 silc_server_packet_send(server, r->router->connection,
671 SILC_PACKET_COMMAND, cmd->packet->flags,
672 res_cmd->data, res_cmd->len, FALSE);
674 /* Reprocess this packet after received reply */
675 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
677 silc_server_command_whois,
678 silc_server_command_dup(cmd));
681 silc_buffer_free(res_cmd);
682 for (k = 0; k < r->res_argc; k++)
683 silc_free(r->res_argv[k]);
684 silc_free(r->res_argv);
685 silc_free(r->res_argv_lens);
686 silc_free(r->res_argv_types);
695 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
696 SilcClientEntry *clients,
697 SilcUInt32 clients_count,
699 const char *nickname,
700 SilcClientID **client_ids)
702 SilcServer server = cmd->server;
704 int i, k, len, valid_count;
705 SilcBuffer packet, idp, channels, umode_list = NULL;
706 SilcClientEntry entry;
708 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
709 char nh[256], uh[256];
710 unsigned char idle[4], mode[4];
711 unsigned char *fingerprint;
712 SilcSocketConnection hsock;
714 /* Process only valid clients and ignore those that are not registered. */
716 for (i = 0; i < clients_count; i++) {
717 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
724 /* No valid clients found, send error reply */
726 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
727 SILC_STATUS_ERR_NO_SUCH_NICK,
728 3, nickname, strlen(nickname));
729 } else if (client_ids && client_ids[0]) {
730 SilcBuffer idp = silc_id_payload_encode(client_ids[0], SILC_ID_CLIENT);
731 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
732 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
733 2, idp->data, idp->len);
734 silc_buffer_free(idp);
739 /* Start processing found clients. */
741 status = SILC_STATUS_LIST_START;
743 status = SILC_STATUS_OK;
745 for (i = 0, k = 0; i < clients_count; i++) {
751 status = SILC_STATUS_LIST_ITEM;
752 if (valid_count > 1 && k == valid_count - 1)
753 status = SILC_STATUS_LIST_END;
754 if (count && k - 1 == count)
755 status = SILC_STATUS_LIST_END;
757 /* Send WHOIS reply */
758 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
759 tmp = silc_argument_get_first_arg(cmd->args, NULL);
761 memset(uh, 0, sizeof(uh));
762 memset(nh, 0, sizeof(nh));
763 memset(idle, 0, sizeof(idle));
765 strncat(nh, entry->nickname, strlen(entry->nickname));
766 if (!strchr(entry->nickname, '@')) {
768 if (entry->servername) {
769 strncat(nh, entry->servername, strlen(entry->servername));
771 len = entry->router ? strlen(entry->router->server_name) :
772 strlen(server->server_name);
773 strncat(nh, entry->router ? entry->router->server_name :
774 server->server_name, len);
778 strncat(uh, entry->username, strlen(entry->username));
779 if (!strchr(entry->username, '@')) {
781 hsock = (SilcSocketConnection)entry->connection;
782 len = strlen(hsock->hostname);
783 strncat(uh, hsock->hostname, len);
786 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
787 channels = silc_server_get_client_channel_list(server, entry, FALSE,
790 channels = silc_server_get_client_channel_list(server, entry, TRUE,
793 if (entry->data.fingerprint[0] != 0 && entry->data.fingerprint[1] != 0)
794 fingerprint = entry->data.fingerprint;
798 SILC_PUT32_MSB(entry->mode, mode);
800 if (entry->connection) {
801 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
805 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
807 2, idp->data, idp->len,
811 strlen(entry->userinfo),
812 6, channels ? channels->data : NULL,
813 channels ? channels->len : 0,
817 fingerprint ? 20 : 0,
818 10, umode_list ? umode_list->data :
819 NULL, umode_list ? umode_list->len :
822 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
823 0, packet->data, packet->len, FALSE);
825 silc_buffer_free(packet);
826 silc_buffer_free(idp);
828 silc_buffer_free(channels);
830 silc_buffer_free(umode_list);
839 silc_server_command_whois_send_router(SilcServerCommandContext cmd)
841 SilcServer server = cmd->server;
843 SilcUInt16 old_ident;
845 old_ident = silc_command_get_ident(cmd->payload);
846 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
847 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
849 /* Send WHOIS command to our router */
850 silc_server_packet_send(server, (SilcSocketConnection)
851 server->router->connection,
852 SILC_PACKET_COMMAND, cmd->packet->flags,
853 tmpbuf->data, tmpbuf->len, TRUE);
855 /* Reprocess this packet after received reply from router */
856 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
857 silc_command_get_ident(cmd->payload),
858 silc_server_command_whois,
859 silc_server_command_dup(cmd));
861 silc_command_set_ident(cmd->payload, old_ident);
862 silc_buffer_free(tmpbuf);
866 silc_server_command_whois_process(SilcServerCommandContext cmd)
868 SilcServer server = cmd->server;
869 char *nick = NULL, *server_name = NULL;
871 SilcClientEntry *clients = NULL, entry;
872 SilcClientID **client_id = NULL;
873 SilcUInt32 client_id_count = 0, clients_count = 0;
875 bool check_global = FALSE;
877 /* Parse the whois request */
878 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
879 &nick, &server_name, &count,
883 /* Send the WHOIS request to the router only if it included nickname.
884 Since nicknames can be expanded into many clients we need to send it
885 to router. If the WHOIS included only client ID's we will check them
886 first locally since we just might have them. */
887 if (nick && !client_id_count && cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
888 server->server_type == SILC_SERVER && !cmd->pending &&
889 !server->standalone) {
890 silc_server_command_whois_send_router(cmd);
895 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
897 else if (server->server_type != SILC_SERVER)
900 /* Get all clients matching that ID or nickname from local list */
901 if (client_id_count) {
902 /* Check all Client ID's received in the command packet */
903 for (i = 0; i < client_id_count; i++) {
904 entry = silc_idlist_find_client_by_id(server->local_list,
905 client_id[i], TRUE, NULL);
906 if (!entry && check_global)
907 entry = silc_idlist_find_client_by_id(server->global_list,
908 client_id[i], TRUE, NULL);
910 clients = silc_realloc(clients, sizeof(*clients) *
911 (clients_count + 1));
912 clients[clients_count++] = entry;
914 /* If we are normal server and did not send the request first to router
915 do it now, since we do not have the Client ID information. */
916 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
917 server->server_type == SILC_SERVER && !cmd->pending &&
918 !server->standalone) {
919 silc_server_command_whois_send_router(cmd);
926 /* Find by nickname */
927 if (!silc_idlist_get_clients_by_hash(server->local_list,
928 nick, server->md5hash,
929 &clients, &clients_count))
930 silc_idlist_get_clients_by_nickname(server->local_list,
932 &clients, &clients_count);
934 if (!silc_idlist_get_clients_by_hash(server->global_list,
935 nick, server->md5hash,
936 &clients, &clients_count))
937 silc_idlist_get_clients_by_nickname(server->global_list,
939 &clients, &clients_count);
944 /* If we are normal server and did not send the request first to router
945 do it now, since we do not have the information. */
946 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
947 server->server_type == SILC_SERVER && !cmd->pending &&
948 !server->standalone) {
949 silc_server_command_whois_send_router(cmd);
954 /* Such client(s) really does not exist in the SILC network. */
955 if (!client_id_count) {
956 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
957 SILC_STATUS_ERR_NO_SUCH_NICK,
958 3, nick, strlen(nick));
960 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
961 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
962 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
963 2, idp->data, idp->len);
964 silc_buffer_free(idp);
969 /* Router always finds the client entry if it exists in the SILC network.
970 However, it might be incomplete entry and does not include all the
971 mandatory fields that WHOIS command reply requires. Check for these and
972 make query from the server who owns the client if some fields are
974 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
979 /* Send the command reply */
980 silc_server_command_whois_send_reply(cmd, clients, clients_count,
981 count, nick, client_id);
984 if (client_id_count) {
985 for (i = 0; i < client_id_count; i++)
986 silc_free(client_id[i]);
987 silc_free(client_id);
991 silc_free(server_name);
996 /* Server side of command WHOIS. Processes user's query and sends found
997 results as command replies back to the client. */
999 SILC_SERVER_CMD_FUNC(whois)
1001 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1004 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 3328);
1006 ret = silc_server_command_whois_process(cmd);
1007 silc_server_command_free(cmd);
1010 /******************************************************************************
1014 ******************************************************************************/
1017 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
1025 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1027 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
1028 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1032 /* Get the nickname@server string and parse it. */
1033 silc_parse_userfqdn(tmp, nickname, server_name);
1035 /* Get the max count of reply messages allowed */
1036 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1038 SILC_GET32_MSB(*count, tmp);
1047 silc_server_command_whowas_check(SilcServerCommandContext cmd,
1048 SilcClientEntry *clients,
1049 SilcUInt32 clients_count)
1051 SilcServer server = cmd->server;
1053 SilcClientEntry entry;
1055 for (i = 0; i < clients_count; i++) {
1058 if (!entry->nickname || !entry->username) {
1060 SilcUInt16 old_ident;
1065 old_ident = silc_command_get_ident(cmd->payload);
1066 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1067 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1069 /* Send WHOWAS command */
1070 silc_server_packet_send(server, entry->router->connection,
1071 SILC_PACKET_COMMAND, cmd->packet->flags,
1072 tmpbuf->data, tmpbuf->len, TRUE);
1074 /* Reprocess this packet after received reply */
1075 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1076 silc_command_get_ident(cmd->payload),
1077 silc_server_command_whowas,
1078 silc_server_command_dup(cmd));
1079 cmd->pending = TRUE;
1080 silc_command_set_ident(cmd->payload, old_ident);
1082 silc_buffer_free(tmpbuf);
1091 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1092 SilcClientEntry *clients,
1093 SilcUInt32 clients_count)
1095 SilcServer server = cmd->server;
1097 int i, k, count = 0, len;
1098 SilcBuffer packet, idp;
1099 SilcClientEntry entry = NULL;
1101 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1102 char nh[256], uh[256];
1105 status = SILC_STATUS_OK;
1107 /* Process only entries that are not registered anymore. */
1109 for (i = 0; i < clients_count; i++) {
1110 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1117 /* No valid entries found at all, just send error */
1120 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1122 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1123 SILC_STATUS_ERR_NO_SUCH_NICK,
1124 3, tmp, strlen(tmp));
1128 if (valid_count > 1)
1129 status = SILC_STATUS_LIST_START;
1131 for (i = 0, k = 0; i < clients_count; i++) {
1137 status = SILC_STATUS_LIST_ITEM;
1138 if (valid_count > 1 && k == valid_count - 1)
1139 status = SILC_STATUS_LIST_END;
1140 if (count && k - 1 == count)
1141 status = SILC_STATUS_LIST_END;
1142 if (count && k - 1 > count)
1145 /* Send WHOWAS reply */
1146 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1147 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1148 memset(uh, 0, sizeof(uh));
1149 memset(nh, 0, sizeof(nh));
1151 strncat(nh, entry->nickname, strlen(entry->nickname));
1152 if (!strchr(entry->nickname, '@')) {
1153 strncat(nh, "@", 1);
1154 if (entry->servername) {
1155 strncat(nh, entry->servername, strlen(entry->servername));
1157 len = entry->router ? strlen(entry->router->server_name) :
1158 strlen(server->server_name);
1159 strncat(nh, entry->router ? entry->router->server_name :
1160 server->server_name, len);
1164 strncat(uh, entry->username, strlen(entry->username));
1165 if (!strchr(entry->username, '@')) {
1166 strncat(uh, "@", 1);
1167 strcat(uh, "*private*");
1171 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1172 status, 0, ident, 4,
1173 2, idp->data, idp->len,
1178 strlen(entry->userinfo) : 0);
1179 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1180 0, packet->data, packet->len, FALSE);
1182 silc_buffer_free(packet);
1183 silc_buffer_free(idp);
1190 silc_server_command_whowas_process(SilcServerCommandContext cmd)
1192 SilcServer server = cmd->server;
1193 char *nick = NULL, *server_name = NULL;
1195 SilcClientEntry *clients = NULL;
1196 SilcUInt32 clients_count = 0;
1198 bool check_global = FALSE;
1200 /* Protocol dictates that we must always send the received WHOWAS request
1201 to our router if we are normal server, so let's do it now unless we
1202 are standalone. We will not send any replies to the client until we
1203 have received reply from the router. */
1204 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1205 server->server_type == SILC_SERVER && !cmd->pending &&
1206 !server->standalone) {
1208 SilcUInt16 old_ident;
1210 old_ident = silc_command_get_ident(cmd->payload);
1211 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1212 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1214 /* Send WHOWAS command to our router */
1215 silc_server_packet_send(server, (SilcSocketConnection)
1216 server->router->connection,
1217 SILC_PACKET_COMMAND, cmd->packet->flags,
1218 tmpbuf->data, tmpbuf->len, TRUE);
1220 /* Reprocess this packet after received reply from router */
1221 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1222 silc_command_get_ident(cmd->payload),
1223 silc_server_command_whowas,
1224 silc_server_command_dup(cmd));
1225 cmd->pending = TRUE;
1226 silc_command_set_ident(cmd->payload, old_ident);
1228 silc_buffer_free(tmpbuf);
1233 /* We are ready to process the command request. Let's search for the
1234 requested client and send reply to the requesting client. */
1236 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1237 check_global = TRUE;
1238 else if (server->server_type != SILC_SERVER)
1239 check_global = TRUE;
1241 /* Parse the whowas request */
1242 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1245 /* Get all clients matching that nickname from local list */
1246 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1248 &clients, &clients_count))
1249 silc_idlist_get_clients_by_hash(server->local_list,
1250 nick, server->md5hash,
1251 &clients, &clients_count);
1253 /* Check global list as well */
1255 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1257 &clients, &clients_count))
1258 silc_idlist_get_clients_by_hash(server->global_list,
1259 nick, server->md5hash,
1260 &clients, &clients_count);
1264 /* Such a client really does not exist in the SILC network. */
1265 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1266 SILC_STATUS_ERR_NO_SUCH_NICK,
1267 3, nick, strlen(nick));
1271 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1276 /* Send the command reply to the client */
1277 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1282 silc_free(server_name);
1286 /* Server side of command WHOWAS. */
1288 SILC_SERVER_CMD_FUNC(whowas)
1290 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1293 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1295 ret = silc_server_command_whowas_process(cmd);
1296 silc_server_command_free(cmd);
1299 /******************************************************************************
1303 ******************************************************************************/
1306 silc_server_command_identify_send_router(SilcServerCommandContext cmd)
1308 SilcServer server = cmd->server;
1310 SilcUInt16 old_ident;
1312 old_ident = silc_command_get_ident(cmd->payload);
1313 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1314 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1316 /* Send IDENTIFY command to our router */
1317 silc_server_packet_send(server, (SilcSocketConnection)
1318 server->router->connection,
1319 SILC_PACKET_COMMAND, cmd->packet->flags,
1320 tmpbuf->data, tmpbuf->len, TRUE);
1322 /* Reprocess this packet after received reply from router */
1323 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1324 silc_command_get_ident(cmd->payload),
1325 silc_server_command_identify,
1326 silc_server_command_dup(cmd));
1327 cmd->pending = TRUE;
1328 silc_command_set_ident(cmd->payload, old_ident);
1329 silc_buffer_free(tmpbuf);
1333 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1334 SilcClientEntry **clients,
1335 SilcUInt32 *clients_count,
1336 SilcServerEntry **servers,
1337 SilcUInt32 *servers_count,
1338 SilcChannelEntry **channels,
1339 SilcUInt32 *channels_count,
1342 SilcServer server = cmd->server;
1345 SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
1347 bool check_global = FALSE;
1352 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1353 check_global = TRUE;
1354 else if (server->server_type != SILC_SERVER)
1355 check_global = TRUE;
1357 /* If ID Payload is in the command it must be used instead of names */
1358 tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1360 /* No ID, get the names. */
1362 /* If we are normal server and have not resolved information from
1363 router yet, do so now. */
1364 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1365 server->server_type == SILC_SERVER && !cmd->pending &&
1366 !server->standalone) {
1367 silc_server_command_identify_send_router(cmd);
1371 /* Try to get nickname@server. */
1372 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1375 char *nick_server = NULL;
1377 silc_parse_userfqdn(tmp, &nick, &nick_server);
1379 if (!silc_idlist_get_clients_by_hash(server->local_list,
1380 nick, server->md5hash,
1381 clients, clients_count))
1382 silc_idlist_get_clients_by_nickname(server->local_list,
1384 clients, clients_count);
1386 if (!silc_idlist_get_clients_by_hash(server->global_list,
1387 nick, server->md5hash,
1388 clients, clients_count))
1389 silc_idlist_get_clients_by_nickname(server->global_list,
1391 clients, clients_count);
1395 silc_free(nick_server);
1398 /* the nickname does not exist, send error reply */
1399 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1400 SILC_STATUS_ERR_NO_SUCH_NICK,
1401 3, tmp, strlen(tmp));
1406 /* Try to get server name */
1407 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1409 entry = silc_idlist_find_server_by_name(server->local_list,
1411 if (!entry && check_global)
1412 entry = silc_idlist_find_server_by_name(server->global_list,
1415 *servers = silc_realloc(*servers, sizeof(**servers) *
1416 (*servers_count + 1));
1417 (*servers)[(*servers_count)++] = entry;
1421 /* the server does not exist, send error reply */
1422 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1423 SILC_STATUS_ERR_NO_SUCH_SERVER,
1424 3, tmp, strlen(tmp));
1429 /* Try to get channel name */
1430 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1432 entry = silc_idlist_find_channel_by_name(server->local_list,
1434 if (!entry && check_global)
1435 entry = silc_idlist_find_channel_by_name(server->global_list,
1438 *channels = silc_realloc(*channels, sizeof(**channels) *
1439 (*channels_count + 1));
1440 (*channels)[(*channels_count)++] = entry;
1444 /* The channel does not exist, send error reply */
1445 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1446 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1447 3, tmp, strlen(tmp));
1452 if (!(*clients) && !(*servers) && !(*channels)) {
1453 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1454 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1458 /* Command includes ID, we must use that. Also check whether the command
1459 has more than one ID set - take them all. */
1461 /* Take all ID's from the command packet */
1462 for (i = 0; i < argc; i++) {
1465 tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
1469 idp = silc_id_payload_parse(tmp, len);
1471 silc_free(*clients);
1472 silc_free(*servers);
1473 silc_free(*channels);
1474 silc_server_command_send_status_reply(
1475 cmd, SILC_COMMAND_IDENTIFY,
1476 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1480 id = silc_id_payload_get_id(idp);
1482 switch (silc_id_payload_get_type(idp)) {
1484 case SILC_ID_CLIENT:
1485 entry = (void *)silc_idlist_find_client_by_id(server->local_list,
1487 if (!entry && check_global)
1488 entry = (void *)silc_idlist_find_client_by_id(server->global_list,
1491 *clients = silc_realloc(*clients, sizeof(**clients) *
1492 (*clients_count + 1));
1493 (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
1495 /* If we are normal server and have not resolved information from
1496 router yet, do so now. */
1497 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1498 server->server_type == SILC_SERVER && !cmd->pending &&
1499 !server->standalone) {
1500 silc_server_command_identify_send_router(cmd);
1501 silc_free(*clients);
1502 silc_free(*servers);
1503 silc_free(*channels);
1506 silc_server_command_send_status_data(
1507 cmd, SILC_COMMAND_IDENTIFY,
1508 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1516 case SILC_ID_SERVER:
1517 entry = (void *)silc_idlist_find_server_by_id(server->local_list,
1519 if (!entry && check_global)
1520 entry = (void *)silc_idlist_find_server_by_id(server->global_list,
1523 *servers = silc_realloc(*servers, sizeof(**servers) *
1524 (*servers_count + 1));
1525 (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
1527 /* If we are normal server and have not resolved information from
1528 router yet, do so now. */
1529 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1530 server->server_type == SILC_SERVER && !cmd->pending &&
1531 !server->standalone) {
1532 silc_server_command_identify_send_router(cmd);
1533 silc_free(*clients);
1534 silc_free(*servers);
1535 silc_free(*channels);
1538 silc_server_command_send_status_data(
1539 cmd, SILC_COMMAND_IDENTIFY,
1540 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
1547 case SILC_ID_CHANNEL:
1548 entry = (void *)silc_idlist_find_channel_by_id(server->local_list,
1550 if (!entry && check_global)
1551 entry = (void *)silc_idlist_find_channel_by_id(server->global_list,
1554 *channels = silc_realloc(*channels, sizeof(**channels) *
1555 (*channels_count + 1));
1556 (*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
1558 /* If we are normal server and have not resolved information from
1559 router yet, do so now. */
1560 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1561 server->server_type == SILC_SERVER && !cmd->pending &&
1562 !server->standalone) {
1563 silc_server_command_identify_send_router(cmd);
1564 silc_free(*clients);
1565 silc_free(*servers);
1566 silc_free(*channels);
1569 silc_server_command_send_status_data(
1570 cmd, SILC_COMMAND_IDENTIFY,
1571 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
1584 silc_free(*clients);
1585 silc_free(*servers);
1586 silc_free(*channels);
1590 /* Get the max count of reply messages allowed */
1591 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1593 SILC_GET32_MSB(*count, tmp);
1601 /* Checks that all mandatory fields in client entry are present. If not
1602 then send WHOIS request to the server who owns the client. We use
1603 WHOIS because we want to get as much information as possible at once. */
1606 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1607 SilcClientEntry *clients,
1608 SilcUInt32 clients_count)
1610 SilcServer server = cmd->server;
1611 SilcClientEntry entry;
1612 SilcServerResolveContext resolve = NULL, r = NULL;
1613 SilcUInt32 resolve_count = 0;
1617 for (i = 0; i < clients_count; i++) {
1622 if (entry->nickname ||
1623 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1627 /* If we are normal server, and we've not resolved this client from
1628 router and it is global client, we'll check whether it is on some
1629 channel. If not then we cannot be sure about its validity, and
1630 we'll resolve it from router. */
1631 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
1632 entry->connection || silc_hash_table_count(entry->channels))
1636 /* We need to resolve this entry since it is not complete */
1638 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1639 /* The entry is being resolved (and we are not the resolver) so attach
1640 to the command reply and we're done with this one. */
1641 silc_server_command_pending(server, SILC_COMMAND_NONE,
1642 entry->resolve_cmd_ident,
1643 silc_server_command_identify,
1644 silc_server_command_dup(cmd));
1647 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1648 /* We've resolved this and it still is not ready. We'll return
1649 and are that this will be handled again after it is resolved. */
1650 for (i = 0; i < resolve_count; i++) {
1651 for (k = 0; k < r->res_argc; k++)
1652 silc_free(r->res_argv[k]);
1653 silc_free(r->res_argv);
1654 silc_free(r->res_argv_lens);
1655 silc_free(r->res_argv_types);
1660 /* We'll resolve this client */
1664 for (k = 0; k < resolve_count; k++) {
1665 if (resolve[k].router == entry->router) {
1672 resolve = silc_realloc(resolve, sizeof(*resolve) *
1673 (resolve_count + 1));
1674 r = &resolve[resolve_count];
1675 memset(r, 0, sizeof(*r));
1676 r->router = entry->router;
1677 r->ident = ++server->cmd_ident;
1681 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1683 r->res_argv_lens = silc_realloc(r->res_argv_lens,
1684 sizeof(*r->res_argv_lens) *
1686 r->res_argv_types = silc_realloc(r->res_argv_types,
1687 sizeof(*r->res_argv_types) *
1689 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1690 r->res_argv[r->res_argc] = silc_calloc(idp->len,
1691 sizeof(**r->res_argv));
1692 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1693 r->res_argv_lens[r->res_argc] = idp->len;
1694 r->res_argv_types[r->res_argc] = r->res_argc + 3;
1696 silc_buffer_free(idp);
1698 entry->resolve_cmd_ident = r->ident;
1699 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1700 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1705 /* Do the resolving */
1706 for (i = 0; i < resolve_count; i++) {
1711 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1712 now anyway so make it a good one. */
1713 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1714 r->res_argc, r->res_argv,
1718 silc_server_packet_send(server, r->router->connection,
1719 SILC_PACKET_COMMAND, cmd->packet->flags,
1720 res_cmd->data, res_cmd->len, FALSE);
1722 /* Reprocess this packet after received reply */
1723 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1725 silc_server_command_identify,
1726 silc_server_command_dup(cmd));
1727 cmd->pending = TRUE;
1729 silc_buffer_free(res_cmd);
1730 for (k = 0; k < r->res_argc; k++)
1731 silc_free(r->res_argv[k]);
1732 silc_free(r->res_argv);
1733 silc_free(r->res_argv_lens);
1734 silc_free(r->res_argv_types);
1743 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1744 SilcClientEntry *clients,
1745 SilcUInt32 clients_count,
1746 SilcServerEntry *servers,
1747 SilcUInt32 servers_count,
1748 SilcChannelEntry *channels,
1749 SilcUInt32 channels_count,
1752 SilcServer server = cmd->server;
1753 int i, k, len, valid_count;
1754 SilcBuffer packet, idp;
1756 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1757 char nh[256], uh[256];
1758 SilcSocketConnection hsock;
1760 status = SILC_STATUS_OK;
1763 SilcClientEntry entry;
1765 /* Process only valid entries. */
1767 for (i = 0; i < clients_count; i++) {
1768 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1775 /* No valid entries found at all, just send error */
1778 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1780 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1781 SILC_STATUS_ERR_NO_SUCH_NICK,
1782 3, tmp, strlen(tmp));
1784 tmp = silc_argument_get_arg_type(cmd->args, 5, (SilcUInt32 *)&len);
1785 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1786 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1792 /* Process all valid client entries and send command replies */
1794 if (valid_count > 1)
1795 status = SILC_STATUS_LIST_START;
1797 for (i = 0, k = 0; i < clients_count; i++) {
1803 status = SILC_STATUS_LIST_ITEM;
1804 if (valid_count > 1 && k == valid_count - 1
1805 && !servers_count && !channels_count)
1806 status = SILC_STATUS_LIST_END;
1807 if (count && k - 1 == count)
1808 status = SILC_STATUS_LIST_END;
1809 if (count && k - 1 > count)
1812 /* Send IDENTIFY reply */
1814 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1815 memset(uh, 0, sizeof(uh));
1816 memset(nh, 0, sizeof(nh));
1817 strncat(nh, entry->nickname, strlen(entry->nickname));
1818 if (!strchr(entry->nickname, '@')) {
1819 strncat(nh, "@", 1);
1820 if (entry->servername) {
1821 strncat(nh, entry->servername, strlen(entry->servername));
1823 len = entry->router ? strlen(entry->router->server_name) :
1824 strlen(server->server_name);
1825 strncat(nh, entry->router ? entry->router->server_name :
1826 server->server_name, len);
1830 if (!entry->username) {
1831 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1832 status, 0, ident, 2,
1833 2, idp->data, idp->len,
1836 strncat(uh, entry->username, strlen(entry->username));
1837 if (!strchr(entry->username, '@')) {
1838 strncat(uh, "@", 1);
1839 hsock = (SilcSocketConnection)entry->connection;
1840 len = strlen(hsock->hostname);
1841 strncat(uh, hsock->hostname, len);
1844 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1845 status, 0, ident, 3,
1846 2, idp->data, idp->len,
1851 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1852 0, packet->data, packet->len, FALSE);
1854 silc_buffer_free(packet);
1855 silc_buffer_free(idp);
1862 SilcServerEntry entry;
1864 if (status == SILC_STATUS_OK && servers_count > 1)
1865 status = SILC_STATUS_LIST_START;
1867 for (i = 0, k = 0; i < servers_count; i++) {
1871 status = SILC_STATUS_LIST_ITEM;
1872 if (servers_count > 1 && k == servers_count - 1 && !channels_count)
1873 status = SILC_STATUS_LIST_END;
1874 if (count && k - 1 == count)
1875 status = SILC_STATUS_LIST_END;
1876 if (count && k - 1 > count)
1879 /* Send IDENTIFY reply */
1880 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1882 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1883 status, 0, ident, 2,
1884 2, idp->data, idp->len,
1885 3, entry->server_name,
1886 entry->server_name ?
1887 strlen(entry->server_name) : 0);
1888 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1889 0, packet->data, packet->len, FALSE);
1891 silc_buffer_free(packet);
1892 silc_buffer_free(idp);
1899 SilcChannelEntry entry;
1901 if (status == SILC_STATUS_OK && channels_count > 1)
1902 status = SILC_STATUS_LIST_START;
1904 for (i = 0, k = 0; i < channels_count; i++) {
1905 entry = channels[i];
1908 status = SILC_STATUS_LIST_ITEM;
1909 if (channels_count > 1 && k == channels_count - 1)
1910 status = SILC_STATUS_LIST_END;
1911 if (count && k - 1 == count)
1912 status = SILC_STATUS_LIST_END;
1913 if (count && k - 1 > count)
1916 /* Send IDENTIFY reply */
1917 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1919 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1920 status, 0, ident, 2,
1921 2, idp->data, idp->len,
1922 3, entry->channel_name,
1923 entry->channel_name ?
1924 strlen(entry->channel_name): 0);
1925 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1926 0, packet->data, packet->len, FALSE);
1928 silc_buffer_free(packet);
1929 silc_buffer_free(idp);
1937 silc_server_command_identify_process(SilcServerCommandContext cmd)
1939 SilcUInt32 count = 0;
1941 SilcClientEntry *clients = NULL;
1942 SilcServerEntry *servers = NULL;
1943 SilcChannelEntry *channels = NULL;
1944 SilcUInt32 clients_count = 0, servers_count = 0, channels_count = 0;
1946 /* Parse the IDENTIFY request */
1947 ret = silc_server_command_identify_parse(cmd,
1948 &clients, &clients_count,
1949 &servers, &servers_count,
1950 &channels, &channels_count,
1956 /* Check that all mandatory fields are present and request those data
1957 from the server who owns the client if necessary. */
1958 if (clients && !silc_server_command_identify_check_client(cmd, clients,
1964 /* Send the command reply to the client */
1965 silc_server_command_identify_send_reply(cmd,
1966 clients, clients_count,
1967 servers, servers_count,
1968 channels, channels_count,
1974 silc_free(channels);
1978 SILC_SERVER_CMD_FUNC(identify)
1980 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1983 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1985 ret = silc_server_command_identify_process(cmd);
1986 silc_server_command_free(cmd);
1989 /* Server side of command NICK. Sets nickname for user. Setting
1990 nickname causes generation of a new client ID for the client. The
1991 new client ID is sent to the client after changing the nickname. */
1993 SILC_SERVER_CMD_FUNC(nick)
1995 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1996 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1997 SilcServer server = cmd->server;
1998 SilcBuffer packet, nidp, oidp = NULL;
1999 SilcClientID *new_id;
2000 SilcUInt32 nick_len;
2002 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2005 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2008 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
2010 /* Check nickname */
2011 nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
2014 if (silc_server_name_bad_chars(nick, nick_len) == TRUE) {
2015 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2016 SILC_STATUS_ERR_BAD_NICKNAME);
2020 /* Check for same nickname */
2021 if (!strcmp(client->nickname, nick)) {
2022 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2026 /* Create new Client ID */
2027 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
2029 cmd->server->md5hash, nick,
2033 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2034 SILC_STATUS_ERR_BAD_NICKNAME);
2037 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2040 /* Send notify about nickname change to our router. We send the new
2041 ID and ask to replace it with the old one. If we are router the
2042 packet is broadcasted. Send NICK_CHANGE notify. */
2043 if (!server->standalone)
2044 silc_server_send_notify_nick_change(server, server->router->connection,
2045 server->server_type == SILC_SERVER ?
2046 FALSE : TRUE, client->id,
2049 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2051 /* Remove old cache entry */
2052 silc_idcache_del_by_context(server->local_list->clients, client);
2055 silc_free(client->id);
2057 /* Save the nickname as this client is our local client */
2058 silc_free(client->nickname);
2060 client->nickname = strdup(nick);
2061 client->id = new_id;
2063 /* Update client cache */
2064 silc_idcache_add(server->local_list->clients, client->nickname,
2065 client->id, (void *)client, 0, NULL);
2067 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2069 /* Send NICK_CHANGE notify to the client's channels */
2070 silc_server_send_notify_on_channels(server, NULL, client,
2071 SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
2072 oidp->data, oidp->len,
2073 nidp->data, nidp->len,
2075 strlen(client->nickname));
2078 /* Send the new Client ID as reply command back to client */
2079 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
2080 SILC_STATUS_OK, 0, ident, 1,
2081 2, nidp->data, nidp->len);
2082 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2083 0, packet->data, packet->len, FALSE);
2085 silc_buffer_free(packet);
2086 silc_buffer_free(nidp);
2088 silc_buffer_free(oidp);
2091 silc_server_command_free(cmd);
2094 /* Sends the LIST command reply */
2097 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2098 SilcChannelEntry *lch,
2099 SilcUInt32 lch_count,
2100 SilcChannelEntry *gch,
2101 SilcUInt32 gch_count)
2104 SilcBuffer packet, idp;
2105 SilcChannelEntry entry;
2107 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2109 unsigned char usercount[4];
2111 int valid_lcount = 0, valid_rcount = 0;
2113 for (i = 0; i < lch_count; i++) {
2114 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2119 for (i = 0; i < gch_count; i++) {
2120 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2126 status = SILC_STATUS_OK;
2127 if ((lch_count + gch_count) > 1)
2128 status = SILC_STATUS_LIST_START;
2131 for (i = 0, k = 0; i < lch_count; i++) {
2137 status = SILC_STATUS_LIST_ITEM;
2138 if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
2139 status = SILC_STATUS_LIST_END;
2141 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2143 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2144 topic = "*private*";
2145 memset(usercount, 0, sizeof(usercount));
2147 topic = entry->topic;
2148 users = silc_hash_table_count(entry->user_list);
2149 SILC_PUT32_MSB(users, usercount);
2152 /* Send the reply */
2154 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2155 status, 0, ident, 4,
2156 2, idp->data, idp->len,
2157 3, entry->channel_name,
2158 strlen(entry->channel_name),
2159 4, topic, topic ? strlen(topic) : 0,
2161 silc_server_packet_send(cmd->server, cmd->sock,
2162 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2163 packet->len, FALSE);
2164 silc_buffer_free(packet);
2165 silc_buffer_free(idp);
2170 for (i = 0, k = 0; i < gch_count; i++) {
2176 status = SILC_STATUS_LIST_ITEM;
2177 if (valid_rcount > 1 && k == valid_rcount - 1)
2178 status = SILC_STATUS_LIST_END;
2180 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2182 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2183 topic = "*private*";
2184 memset(usercount, 0, sizeof(usercount));
2186 topic = entry->topic;
2187 users = entry->user_count;
2188 SILC_PUT32_MSB(users, usercount);
2191 /* Send the reply */
2193 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2194 status, 0, ident, 4,
2195 2, idp->data, idp->len,
2196 3, entry->channel_name,
2197 strlen(entry->channel_name),
2198 4, topic, topic ? strlen(topic) : 0,
2200 silc_server_packet_send(cmd->server, cmd->sock,
2201 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2202 packet->len, FALSE);
2203 silc_buffer_free(packet);
2204 silc_buffer_free(idp);
2209 /* Server side of LIST command. This lists the channel of the requested
2210 server. Secret channels are not listed. */
2212 SILC_SERVER_CMD_FUNC(list)
2214 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2215 SilcServer server = cmd->server;
2216 SilcChannelID *channel_id = NULL;
2219 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2220 SilcUInt32 lch_count = 0, gch_count = 0;
2222 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2224 /* If we are normal server, send the command to router, since we
2225 want to know all channels in the network. */
2226 if (!cmd->pending && server->server_type == SILC_SERVER &&
2227 !server->standalone) {
2229 SilcUInt16 old_ident;
2231 old_ident = silc_command_get_ident(cmd->payload);
2232 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2233 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2234 silc_server_packet_send(server, server->router->connection,
2235 SILC_PACKET_COMMAND, cmd->packet->flags,
2236 tmpbuf->data, tmpbuf->len, TRUE);
2238 /* Reprocess this packet after received reply from router */
2239 silc_server_command_pending(server, SILC_COMMAND_LIST,
2240 silc_command_get_ident(cmd->payload),
2241 silc_server_command_list,
2242 silc_server_command_dup(cmd));
2243 cmd->pending = TRUE;
2244 silc_command_set_ident(cmd->payload, old_ident);
2245 silc_buffer_free(tmpbuf);
2249 /* Get Channel ID */
2250 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2252 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2254 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2255 SILC_STATUS_ERR_NO_CHANNEL_ID);
2260 /* Get the channels from local list */
2261 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2264 /* Get the channels from global list */
2265 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2268 /* Send the reply */
2269 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2270 gchannels, gch_count);
2272 silc_free(lchannels);
2273 silc_free(gchannels);
2276 silc_server_command_free(cmd);
2279 /* Server side of TOPIC command. Sets topic for channel and/or returns
2280 current topic to client. */
2282 SILC_SERVER_CMD_FUNC(topic)
2284 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2285 SilcServer server = cmd->server;
2286 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2287 SilcChannelID *channel_id;
2288 SilcChannelEntry channel;
2289 SilcChannelClientEntry chl;
2290 SilcBuffer packet, idp;
2292 SilcUInt32 argc, tmp_len;
2293 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2295 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2297 argc = silc_argument_get_arg_num(cmd->args);
2299 /* Get Channel ID */
2300 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2302 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2303 SILC_STATUS_ERR_NO_CHANNEL_ID);
2306 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2308 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2309 SILC_STATUS_ERR_NO_CHANNEL_ID);
2313 /* Check whether the channel exists */
2314 channel = silc_idlist_find_channel_by_id(server->local_list,
2317 channel = silc_idlist_find_channel_by_id(server->global_list,
2320 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2321 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2328 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2330 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2331 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2335 if (strlen(tmp) > 256) {
2336 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2337 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2341 /* See whether the client is on channel and has rights to change topic */
2342 if (!silc_server_client_on_channel(client, channel, &chl)) {
2343 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2344 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2348 if (chl->mode == SILC_CHANNEL_UMODE_NONE &&
2349 channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2350 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2351 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2355 /* Set the topic for channel */
2356 silc_free(channel->topic);
2357 channel->topic = strdup(tmp);
2359 /* Send TOPIC_SET notify type to the network */
2360 if (!server->standalone)
2361 silc_server_send_notify_topic_set(server, server->router->connection,
2362 server->server_type == SILC_ROUTER ?
2363 TRUE : FALSE, channel,
2364 client->id, SILC_ID_CLIENT,
2367 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2369 /* Send notify about topic change to all clients on the channel */
2370 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2371 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2372 idp->data, idp->len,
2373 channel->topic, strlen(channel->topic));
2374 silc_buffer_free(idp);
2377 /* Send the topic to client as reply packet */
2378 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2379 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2380 SILC_STATUS_OK, 0, ident, 2,
2381 2, idp->data, idp->len,
2384 strlen(channel->topic) : 0);
2385 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2386 0, packet->data, packet->len, FALSE);
2388 silc_buffer_free(packet);
2389 silc_buffer_free(idp);
2390 silc_free(channel_id);
2393 silc_server_command_free(cmd);
2396 /* Server side of INVITE command. Invites some client to join some channel.
2397 This command is also used to manage the invite list of the channel. */
2399 SILC_SERVER_CMD_FUNC(invite)
2401 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2402 SilcServer server = cmd->server;
2403 SilcSocketConnection sock = cmd->sock, dest_sock;
2404 SilcChannelClientEntry chl;
2405 SilcClientEntry sender, dest;
2406 SilcClientID *dest_id = NULL;
2407 SilcChannelEntry channel;
2408 SilcChannelID *channel_id = NULL;
2409 SilcIDListData idata;
2410 SilcBuffer idp, idp2, packet;
2411 unsigned char *tmp, *add, *del;
2413 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2415 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2417 /* Get Channel ID */
2418 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2420 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2421 SILC_STATUS_ERR_NO_CHANNEL_ID);
2424 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
2426 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2427 SILC_STATUS_ERR_NO_CHANNEL_ID);
2431 /* Get the channel entry */
2432 channel = silc_idlist_find_channel_by_id(server->local_list,
2435 channel = silc_idlist_find_channel_by_id(server->global_list,
2438 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2439 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2444 /* Check whether the sender of this command is on the channel. */
2445 sender = (SilcClientEntry)sock->user_data;
2446 if (!silc_server_client_on_channel(sender, channel, &chl)) {
2447 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2448 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2452 /* Check whether the channel is invite-only channel. If yes then the
2453 sender of this command must be at least channel operator. */
2454 if (chl->mode == SILC_CHANNEL_UMODE_NONE &&
2455 channel->mode & SILC_CHANNEL_MODE_INVITE) {
2456 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2457 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2461 /* Get destination client ID */
2462 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2467 dest_id = silc_id_payload_parse_id(tmp, len, NULL);
2469 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2470 SILC_STATUS_ERR_NO_CLIENT_ID);
2474 /* Get the client entry */
2475 dest = silc_server_get_client_resolve(server, dest_id, FALSE, &resolve);
2477 if (server->server_type != SILC_SERVER || !resolve) {
2478 silc_server_command_send_status_reply(
2479 cmd, SILC_COMMAND_INVITE,
2480 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2484 /* The client info is being resolved. Reprocess this packet after
2485 receiving the reply to the query. */
2486 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2488 silc_server_command_invite,
2489 silc_server_command_dup(cmd));
2490 cmd->pending = TRUE;
2491 silc_free(channel_id);
2496 /* Check whether the requested client is already on the channel. */
2497 if (silc_server_client_on_channel(dest, channel, NULL)) {
2498 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2499 SILC_STATUS_ERR_USER_ON_CHANNEL);
2503 /* Get route to the client */
2504 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id,
2507 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2508 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2512 memset(invite, 0, sizeof(invite));
2513 strncat(invite, dest->nickname, strlen(dest->nickname));
2514 strncat(invite, "!", 1);
2515 strncat(invite, dest->username, strlen(dest->username));
2516 if (!strchr(dest->username, '@')) {
2517 strncat(invite, "@", 1);
2518 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2521 len = strlen(invite);
2522 if (!channel->invite_list)
2523 channel->invite_list = silc_calloc(len + 2,
2524 sizeof(*channel->invite_list));
2526 channel->invite_list = silc_realloc(channel->invite_list,
2527 sizeof(*channel->invite_list) *
2529 strlen(channel->invite_list) + 2));
2530 strncat(channel->invite_list, invite, len);
2531 strncat(channel->invite_list, ",", 1);
2533 /* Send notify to the client that is invited to the channel */
2534 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2535 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2536 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2538 SILC_NOTIFY_TYPE_INVITE, 3,
2539 idp->data, idp->len,
2540 channel->channel_name,
2541 strlen(channel->channel_name),
2542 idp2->data, idp2->len);
2543 silc_buffer_free(idp);
2544 silc_buffer_free(idp2);
2547 /* Add the client to the invite list of the channel */
2548 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2550 if (!channel->invite_list)
2551 channel->invite_list = silc_calloc(len + 2,
2552 sizeof(*channel->invite_list));
2554 channel->invite_list = silc_realloc(channel->invite_list,
2555 sizeof(*channel->invite_list) *
2557 strlen(channel->invite_list) + 2));
2558 if (add[len - 1] == ',')
2559 add[len - 1] = '\0';
2561 strncat(channel->invite_list, add, len);
2562 strncat(channel->invite_list, ",", 1);
2565 /* Get the invite to be removed and remove it from the list */
2566 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2567 if (del && channel->invite_list) {
2568 char *start, *end, *n;
2570 if (!strncmp(channel->invite_list, del,
2571 strlen(channel->invite_list) - 1)) {
2572 silc_free(channel->invite_list);
2573 channel->invite_list = NULL;
2575 start = strstr(channel->invite_list, del);
2576 if (start && strlen(start) >= len) {
2578 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2579 strncat(n, channel->invite_list, start - channel->invite_list);
2580 strncat(n, end + 1, ((channel->invite_list +
2581 strlen(channel->invite_list)) - end) - 1);
2582 silc_free(channel->invite_list);
2583 channel->invite_list = n;
2588 /* Send notify to the primary router */
2589 if (!server->standalone)
2590 silc_server_send_notify_invite(server, server->router->connection,
2591 server->server_type == SILC_ROUTER ?
2592 TRUE : FALSE, channel,
2593 sender->id, add, del);
2595 /* Send command reply */
2596 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2600 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2601 SILC_STATUS_OK, 0, ident, 2,
2603 3, channel->invite_list,
2604 channel->invite_list ?
2605 strlen(channel->invite_list) : 0);
2608 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2609 SILC_STATUS_OK, 0, ident, 1,
2611 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2612 packet->data, packet->len, FALSE);
2613 silc_buffer_free(packet);
2617 silc_free(channel_id);
2618 silc_server_command_free(cmd);
2623 SilcSocketConnection sock;
2627 /* Quits connection to client. This gets called if client won't
2628 close the connection even when it has issued QUIT command. */
2630 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2632 QuitInternal q = (QuitInternal)context;
2634 /* Free all client specific data, such as client entry and entires
2635 on channels this client may be on. */
2636 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2638 q->sock->user_data = NULL;
2640 /* Close the connection on our side */
2641 silc_server_close_connection(q->server, q->sock);
2643 silc_free(q->signoff);
2647 /* Quits SILC session. This is the normal way to disconnect client. */
2649 SILC_SERVER_CMD_FUNC(quit)
2651 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2652 SilcServer server = cmd->server;
2653 SilcSocketConnection sock = cmd->sock;
2655 unsigned char *tmp = NULL;
2658 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2660 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2664 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2668 q = silc_calloc(1, sizeof(*q));
2671 q->signoff = tmp ? strdup(tmp) : NULL;
2673 /* We quit the connection with little timeout */
2674 silc_schedule_task_add(server->schedule, sock->sock,
2675 silc_server_command_quit_cb, (void *)q,
2676 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2679 silc_server_command_free(cmd);
2682 /* Server side of command KILL. This command is used by router operator
2683 to remove an client from the SILC Network temporarily. */
2685 SILC_SERVER_CMD_FUNC(kill)
2687 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2688 SilcServer server = cmd->server;
2689 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2690 SilcClientEntry remote_client;
2691 SilcClientID *client_id;
2692 unsigned char *tmp, *comment;
2693 SilcUInt32 tmp_len, tmp_len2;
2696 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2698 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2701 /* KILL command works only on router */
2702 if (server->server_type != SILC_ROUTER) {
2703 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2704 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2708 /* Check whether client has the permissions. */
2709 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2710 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2711 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2715 /* Get the client ID */
2716 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2718 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2719 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2722 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2724 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2725 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2729 /* Get the client entry */
2730 remote_client = silc_idlist_find_client_by_id(server->local_list,
2731 client_id, TRUE, NULL);
2733 if (!remote_client) {
2734 remote_client = silc_idlist_find_client_by_id(server->global_list,
2735 client_id, TRUE, NULL);
2737 if (!remote_client) {
2738 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2739 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2745 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2749 /* Send reply to the sender */
2750 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2753 /* Now do the killing */
2754 silc_server_kill_client(server, remote_client, comment, client->id,
2758 silc_server_command_free(cmd);
2761 /* Server side of command INFO. This sends information about us to
2762 the client. If client requested specific server we will send the
2763 command to that server. */
2765 SILC_SERVER_CMD_FUNC(info)
2767 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2768 SilcServer server = cmd->server;
2769 SilcBuffer packet, idp;
2772 char *dest_server, *server_info = NULL, *server_name;
2773 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2774 SilcServerEntry entry = NULL;
2775 SilcServerID *server_id = NULL;
2777 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2779 /* Get server name */
2780 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2783 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2785 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2787 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2788 SILC_STATUS_ERR_NO_SERVER_ID);
2794 /* Check whether we have this server cached */
2795 entry = silc_idlist_find_server_by_id(server->local_list,
2796 server_id, TRUE, NULL);
2798 entry = silc_idlist_find_server_by_id(server->global_list,
2799 server_id, TRUE, NULL);
2800 if (!entry && server->server_type != SILC_SERVER) {
2801 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2802 SILC_STATUS_ERR_NO_SUCH_SERVER);
2808 /* Some buggy servers has sent request to router about themselves. */
2809 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2812 if ((!dest_server && !server_id && !entry) || (entry &&
2813 entry == server->id_entry) ||
2814 (dest_server && !cmd->pending &&
2815 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2816 /* Send our reply */
2817 char info_string[256];
2819 memset(info_string, 0, sizeof(info_string));
2820 snprintf(info_string, sizeof(info_string),
2821 "location: %s server: %s admin: %s <%s>",
2822 server->config->server_info->location,
2823 server->config->server_info->server_type,
2824 server->config->server_info->admin,
2825 server->config->server_info->email);
2827 server_info = info_string;
2828 entry = server->id_entry;
2830 /* Check whether we have this server cached */
2831 if (!entry && dest_server) {
2832 entry = silc_idlist_find_server_by_name(server->global_list,
2833 dest_server, TRUE, NULL);
2835 entry = silc_idlist_find_server_by_name(server->local_list,
2836 dest_server, TRUE, NULL);
2840 if (!cmd->pending &&
2841 server->server_type != SILC_SERVER && entry && !entry->server_info) {
2842 /* Send to the server */
2844 SilcUInt16 old_ident;
2846 old_ident = silc_command_get_ident(cmd->payload);
2847 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2848 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2850 silc_server_packet_send(server, entry->connection,
2851 SILC_PACKET_COMMAND, cmd->packet->flags,
2852 tmpbuf->data, tmpbuf->len, TRUE);
2854 /* Reprocess this packet after received reply from router */
2855 silc_server_command_pending(server, SILC_COMMAND_INFO,
2856 silc_command_get_ident(cmd->payload),
2857 silc_server_command_info,
2858 silc_server_command_dup(cmd));
2859 cmd->pending = TRUE;
2860 silc_command_set_ident(cmd->payload, old_ident);
2861 silc_buffer_free(tmpbuf);
2865 if (!entry && !cmd->pending && !server->standalone) {
2866 /* Send to the primary router */
2868 SilcUInt16 old_ident;
2870 old_ident = silc_command_get_ident(cmd->payload);
2871 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2872 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2874 silc_server_packet_send(server, server->router->connection,
2875 SILC_PACKET_COMMAND, cmd->packet->flags,
2876 tmpbuf->data, tmpbuf->len, TRUE);
2878 /* Reprocess this packet after received reply from router */
2879 silc_server_command_pending(server, SILC_COMMAND_INFO,
2880 silc_command_get_ident(cmd->payload),
2881 silc_server_command_info,
2882 silc_server_command_dup(cmd));
2883 cmd->pending = TRUE;
2884 silc_command_set_ident(cmd->payload, old_ident);
2885 silc_buffer_free(tmpbuf);
2890 silc_free(server_id);
2893 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2894 SILC_STATUS_ERR_NO_SUCH_SERVER);
2898 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2900 server_info = entry->server_info;
2901 server_name = entry->server_name;
2903 /* Send the reply */
2904 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2905 SILC_STATUS_OK, 0, ident, 3,
2906 2, idp->data, idp->len,
2908 strlen(server_name),
2911 strlen(server_info) : 0);
2912 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2913 packet->data, packet->len, FALSE);
2915 silc_buffer_free(packet);
2916 silc_buffer_free(idp);
2919 silc_server_command_free(cmd);
2922 /* Server side of command PING. This just replies to the ping. */
2924 SILC_SERVER_CMD_FUNC(ping)
2926 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2927 SilcServer server = cmd->server;
2932 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
2935 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2937 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2938 SILC_STATUS_ERR_NO_SERVER_ID);
2941 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2945 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2946 /* Send our reply */
2947 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2950 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2951 SILC_STATUS_ERR_NO_SUCH_SERVER);
2958 silc_server_command_free(cmd);
2961 /* Server side of command STATS. */
2963 SILC_SERVER_CMD_FUNC(stats)
2965 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2966 SilcServer server = cmd->server;
2967 SilcServerID *server_id;
2970 SilcBuffer packet, stats;
2971 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2974 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1);
2977 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2979 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2980 SILC_STATUS_ERR_NO_SERVER_ID);
2983 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2987 /* The ID must be ours */
2988 if (!SILC_ID_SERVER_COMPARE(server->id, server_id)) {
2989 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2990 SILC_STATUS_ERR_NO_SUCH_SERVER);
2991 silc_free(server_id);
2994 silc_free(server_id);
2996 /* If we are router then just send everything we got. If we are normal
2997 server then we'll send this to our router to get all the latest
2998 statistical information. */
2999 if (!cmd->pending && server->server_type != SILC_ROUTER &&
3000 !server->standalone) {
3001 /* Send request to our router */
3002 SilcBuffer idp = silc_id_payload_encode(server->router->id,
3004 packet = silc_command_payload_encode_va(SILC_COMMAND_STATS,
3005 ++server->cmd_ident, 1,
3006 1, idp->data, idp->len);
3007 silc_server_packet_send(server, server->router->connection,
3008 SILC_PACKET_COMMAND, 0, packet->data,
3009 packet->len, FALSE);
3011 /* Reprocess this packet after received reply from router */
3012 silc_server_command_pending(server, SILC_COMMAND_STATS,
3014 silc_server_command_stats,
3015 silc_server_command_dup(cmd));
3016 cmd->pending = TRUE;
3017 silc_buffer_free(packet);
3018 silc_buffer_free(idp);
3022 /* Send our reply to sender */
3023 uptime = time(NULL) - server->starttime;
3025 stats = silc_buffer_alloc_size(60);
3026 silc_buffer_format(stats,
3027 SILC_STR_UI_INT(server->starttime),
3028 SILC_STR_UI_INT(uptime),
3029 SILC_STR_UI_INT(server->stat.my_clients),
3030 SILC_STR_UI_INT(server->stat.my_channels),
3031 SILC_STR_UI_INT(server->stat.my_server_ops),
3032 SILC_STR_UI_INT(server->stat.my_router_ops),
3033 SILC_STR_UI_INT(server->stat.cell_clients),
3034 SILC_STR_UI_INT(server->stat.cell_channels),
3035 SILC_STR_UI_INT(server->stat.cell_servers),
3036 SILC_STR_UI_INT(server->stat.clients),
3037 SILC_STR_UI_INT(server->stat.channels),
3038 SILC_STR_UI_INT(server->stat.servers),
3039 SILC_STR_UI_INT(server->stat.routers),
3040 SILC_STR_UI_INT(server->stat.server_ops),
3041 SILC_STR_UI_INT(server->stat.router_ops),
3044 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_STATS,
3045 SILC_STATUS_OK, 0, ident, 2,
3047 3, stats->data, stats->len);
3048 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
3049 0, packet->data, packet->len, FALSE);
3050 silc_buffer_free(packet);
3051 silc_buffer_free(stats);
3054 silc_server_command_free(cmd);
3057 /* Internal routine to join channel. The channel sent to this function
3058 has been either created or resolved from ID lists. This joins the sent
3059 client to the channel. */
3061 static void silc_server_command_join_channel(SilcServer server,
3062 SilcServerCommandContext cmd,
3063 SilcChannelEntry channel,
3064 SilcClientID *client_id,
3068 const unsigned char *auth,
3069 SilcUInt32 auth_len)
3071 SilcSocketConnection sock = cmd->sock;
3073 SilcUInt32 tmp_len, user_count;
3074 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
3075 SilcClientEntry client;
3076 SilcChannelClientEntry chl;
3077 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
3078 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3079 char check[512], check2[512];
3080 bool founder = FALSE;
3083 SILC_LOG_DEBUG(("Start"));
3088 /* Get the client entry */
3089 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3090 client = (SilcClientEntry)sock->user_data;
3092 client = silc_server_get_client_resolve(server, client_id, FALSE,
3099 silc_server_command_send_status_reply(
3100 cmd, SILC_COMMAND_JOIN,
3101 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3105 /* The client info is being resolved. Reprocess this packet after
3106 receiving the reply to the query. */
3107 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
3109 silc_server_command_join,
3110 silc_server_command_dup(cmd));
3111 cmd->pending = TRUE;
3115 cmd->pending = FALSE;
3119 * Check founder auth payload if provided. If client can gain founder
3120 * privileges it can override various conditions on joining the channel,
3121 * and can have directly the founder mode set on the channel.
3123 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3124 SilcIDListData idata = (SilcIDListData)client;
3126 if (channel->founder_key && idata->public_key &&
3127 silc_pkcs_public_key_compare(channel->founder_key,
3128 idata->public_key)) {
3129 void *auth_data = (channel->founder_method == SILC_AUTH_PASSWORD ?
3130 (void *)channel->founder_passwd :
3131 (void *)channel->founder_key);
3132 SilcUInt32 auth_data_len =
3133 (channel->founder_method == SILC_AUTH_PASSWORD ?
3134 channel->founder_passwd_len : 0);
3136 /* Check whether the client is to become founder */
3137 if (silc_auth_verify_data(auth, auth_len, channel->founder_method,
3138 auth_data, auth_data_len,
3139 idata->hash, client->id, SILC_ID_CLIENT)) {
3140 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3147 * Check channel modes
3151 memset(check, 0, sizeof(check));
3152 memset(check2, 0, sizeof(check2));
3153 strncat(check, client->nickname, strlen(client->nickname));
3154 strncat(check, "!", 1);
3155 strncat(check, client->username, strlen(client->username));
3156 if (!strchr(client->username, '@')) {
3157 strncat(check, "@", 1);
3158 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3161 strncat(check2, client->nickname, strlen(client->nickname));
3162 if (!strchr(client->nickname, '@')) {
3163 strncat(check2, "@", 1);
3164 strncat(check2, server->server_name, strlen(server->server_name));
3166 strncat(check2, "!", 1);
3167 strncat(check2, client->username, strlen(client->username));
3168 if (!strchr(client->username, '@')) {
3169 strncat(check2, "@", 1);
3170 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3173 /* Check invite list if channel is invite-only channel */
3174 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3175 if (!channel->invite_list ||
3176 (!silc_string_match(channel->invite_list, check) &&
3177 !silc_string_match(channel->invite_list, check2))) {
3178 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3179 SILC_STATUS_ERR_NOT_INVITED);
3184 /* Check ban list if it exists. If the client's nickname, server,
3185 username and/or hostname is in the ban list the access to the
3186 channel is denied. */
3187 if (channel->ban_list) {
3188 if (silc_string_match(channel->ban_list, check) ||
3189 silc_string_match(channel->ban_list, check2)) {
3190 silc_server_command_send_status_reply(
3191 cmd, SILC_COMMAND_JOIN,
3192 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
3197 /* Check user count limit if set. */
3198 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3199 if (silc_hash_table_count(channel->user_list) + 1 >
3200 channel->user_limit) {
3201 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3202 SILC_STATUS_ERR_CHANNEL_IS_FULL);
3208 /* Check the channel passphrase if set. */
3209 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3210 /* Get passphrase */
3211 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3213 passphrase = silc_memdup(tmp, tmp_len);
3215 if (!passphrase || !channel->passphrase ||
3216 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3217 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3218 SILC_STATUS_ERR_BAD_PASSWORD);
3224 * Client is allowed to join to the channel. Make it happen.
3227 /* Check whether the client already is on the channel */
3228 if (silc_server_client_on_channel(client, channel, NULL)) {
3229 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3230 SILC_STATUS_ERR_USER_ON_CHANNEL);
3234 /* Generate new channel key as protocol dictates */
3236 if (!silc_server_create_channel_key(server, channel, 0))
3239 /* Send the channel key. This is broadcasted to the channel but is not
3240 sent to the client who is joining to the channel. */
3241 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3242 silc_server_send_channel_key(server, NULL, channel,
3243 server->server_type == SILC_ROUTER ?
3244 FALSE : !server->standalone);
3247 /* Join the client to the channel by adding it to channel's user list.
3248 Add also the channel to client entry's channels list for fast cross-
3250 chl = silc_calloc(1, sizeof(*chl));
3252 chl->client = client;
3253 chl->channel = channel;
3254 silc_hash_table_add(channel->user_list, client, chl);
3255 silc_hash_table_add(client->channels, channel, chl);
3256 channel->user_count++;
3258 /* Get users on the channel */
3259 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3262 /* Encode Client ID Payload of the original client who wants to join */
3263 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3265 /* Encode command reply packet */
3266 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3267 SILC_PUT32_MSB(channel->mode, mode);
3268 SILC_PUT32_MSB(created, tmp2);
3269 SILC_PUT32_MSB(user_count, tmp3);
3271 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3272 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3273 keyp = silc_channel_key_payload_encode(silc_id_get_len(channel->id,
3276 strlen(channel->channel_key->
3278 channel->channel_key->cipher->name,
3279 channel->key_len / 8, channel->key);
3284 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3285 SILC_STATUS_OK, 0, ident, 13,
3286 2, channel->channel_name,
3287 strlen(channel->channel_name),
3288 3, chidp->data, chidp->len,
3289 4, clidp->data, clidp->len,
3292 7, keyp ? keyp->data : NULL,
3293 keyp ? keyp->len : 0,
3294 8, channel->ban_list,
3296 strlen(channel->ban_list) : 0,
3297 9, channel->invite_list,
3298 channel->invite_list ?
3299 strlen(channel->invite_list) : 0,
3302 strlen(channel->topic) : 0,
3303 11, silc_hmac_get_name(channel->hmac),
3304 strlen(silc_hmac_get_name(channel->
3307 13, user_list->data, user_list->len,
3308 14, mode_list->data,
3311 /* Send command reply */
3312 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3313 reply->data, reply->len, FALSE);
3315 /* Send JOIN notify to locally connected clients on the channel. If
3316 we are normal server then router will send or have sent JOIN notify
3317 already. However since we've added the client already to our channel
3318 we'll ignore it (in packet_receive.c) so we must send it here. If
3319 we are router then this will send it to local clients and local
3321 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3322 SILC_NOTIFY_TYPE_JOIN, 2,
3323 clidp->data, clidp->len,
3324 chidp->data, chidp->len);
3326 if (!cmd->pending) {
3327 /* Send JOIN notify packet to our primary router */
3328 if (!server->standalone)
3329 silc_server_send_notify_join(server, server->router->connection,
3330 server->server_type == SILC_ROUTER ?
3331 TRUE : FALSE, channel, client->id);
3334 /* Distribute the channel key to all backup routers. */
3335 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3336 keyp->data, keyp->len, FALSE, TRUE);
3339 /* If client became founder by providing correct founder auth data
3340 notify the mode change to the channel. */
3342 SILC_PUT32_MSB(chl->mode, mode);
3343 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3344 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3345 clidp->data, clidp->len,
3346 mode, 4, clidp->data, clidp->len);
3348 /* Set CUMODE notify type to network */
3349 if (!server->standalone)
3350 silc_server_send_notify_cumode(server, server->router->connection,
3351 server->server_type == SILC_ROUTER ?
3352 TRUE : FALSE, channel,
3353 chl->mode, client->id, SILC_ID_CLIENT,
3357 silc_buffer_free(reply);
3358 silc_buffer_free(clidp);
3359 silc_buffer_free(chidp);
3360 silc_buffer_free(keyp);
3361 silc_buffer_free(user_list);
3362 silc_buffer_free(mode_list);
3365 silc_free(passphrase);
3368 /* Server side of command JOIN. Joins client into requested channel. If
3369 the channel does not exist it will be created. */
3371 SILC_SERVER_CMD_FUNC(join)
3373 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3374 SilcServer server = cmd->server;
3375 unsigned char *auth;
3376 SilcUInt32 tmp_len, auth_len;
3377 char *tmp, *channel_name = NULL, *cipher, *hmac;
3378 SilcChannelEntry channel;
3379 SilcUInt32 umode = 0;
3380 bool created = FALSE, create_key = TRUE;
3381 SilcClientID *client_id;
3383 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3385 /* Get channel name */
3386 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3388 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3389 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3395 channel_name[255] = '\0';
3397 if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
3398 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3399 SILC_STATUS_ERR_BAD_CHANNEL);
3403 /* Get Client ID of the client who is joining to the channel */
3404 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3406 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3407 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3410 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3412 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3413 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3417 /* Get cipher, hmac name and auth payload */
3418 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3419 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3420 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3422 /* See if the channel exists */
3423 channel = silc_idlist_find_channel_by_name(server->local_list,
3424 channel_name, NULL);
3426 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3427 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3428 client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
3430 if (!channel || channel->disabled) {
3431 /* Channel not found */
3433 /* If we are standalone server we don't have a router, we just create
3434 the channel by ourselves. */
3435 if (server->standalone) {
3436 channel = silc_server_create_new_channel(server, server->id, cipher,
3437 hmac, channel_name, TRUE);
3439 silc_server_command_send_status_reply(
3440 cmd, SILC_COMMAND_JOIN,
3441 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3445 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3451 /* The channel does not exist on our server. If we are normal server
3452 we will send JOIN command to our router which will handle the
3453 joining procedure (either creates the channel if it doesn't exist
3454 or joins the client to it). */
3455 if (server->server_type != SILC_ROUTER) {
3457 SilcUInt16 old_ident;
3459 /* If this is pending command callback then we've resolved
3460 it and it didn't work, return since we've notified the
3461 client already in the command reply callback. */
3465 old_ident = silc_command_get_ident(cmd->payload);
3466 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3467 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3469 /* Send JOIN command to our router */
3470 silc_server_packet_send(server, (SilcSocketConnection)
3471 server->router->connection,
3472 SILC_PACKET_COMMAND, cmd->packet->flags,
3473 tmpbuf->data, tmpbuf->len, TRUE);
3475 /* Reprocess this packet after received reply from router */
3476 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3477 silc_command_get_ident(cmd->payload),
3478 silc_server_command_join,
3479 silc_server_command_dup(cmd));
3480 cmd->pending = TRUE;
3481 silc_command_set_ident(cmd->payload, old_ident);
3482 silc_buffer_free(tmpbuf);
3486 /* We are router and the channel does not seem exist so we will check
3487 our global list as well for the channel. */
3488 channel = silc_idlist_find_channel_by_name(server->global_list,
3489 channel_name, NULL);
3491 /* Channel really does not exist, create it */
3492 channel = silc_server_create_new_channel(server, server->id, cipher,
3493 hmac, channel_name, TRUE);
3495 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3496 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3500 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3508 /* Channel not found */
3510 /* If the command came from router and we are normal server then
3511 something went wrong with the joining as the channel was not found.
3512 We can't do anything else but ignore this. */
3513 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3514 server->server_type != SILC_ROUTER)
3517 /* We are router and the channel does not seem exist so we will check
3518 our global list as well for the channel. */
3519 channel = silc_idlist_find_channel_by_name(server->global_list,
3520 channel_name, NULL);
3522 /* Channel really does not exist, create it */
3523 channel = silc_server_create_new_channel(server, server->id, cipher,
3524 hmac, channel_name, TRUE);
3526 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3527 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3531 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3538 /* Check whether the channel was created by our router */
3539 if (cmd->pending && context2) {
3540 SilcServerCommandReplyContext reply = context2;
3542 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3543 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3544 SILC_GET32_MSB(created, tmp);
3545 if (silc_argument_get_arg_type(reply->args, 7, NULL))
3546 create_key = FALSE; /* Router returned the key already */
3549 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
3550 !silc_hash_table_count(channel->user_list))
3554 /* If the channel does not have global users and is also empty the client
3555 will be the channel founder and operator. */
3556 if (!channel->global_users && !silc_hash_table_count(channel->user_list))
3557 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3559 /* Join to the channel */
3560 silc_server_command_join_channel(server, cmd, channel, client_id,
3561 created, create_key, umode,
3564 silc_free(client_id);
3567 silc_server_command_free(cmd);
3570 /* Server side of command MOTD. Sends server's current "message of the
3571 day" to the client. */
3573 SILC_SERVER_CMD_FUNC(motd)
3575 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3576 SilcServer server = cmd->server;
3577 SilcBuffer packet, idp;
3578 char *motd, *dest_server;
3579 SilcUInt32 motd_len;
3580 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3582 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3584 /* Get server name */
3585 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3587 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3588 SILC_STATUS_ERR_NO_SUCH_SERVER);
3592 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3595 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3597 if (server->config && server->config->server_info &&
3598 server->config->server_info->motd_file) {
3600 motd = silc_file_readfile(server->config->server_info->motd_file, &motd_len);
3605 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3612 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3618 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3619 packet->data, packet->len, FALSE);
3620 silc_buffer_free(packet);
3621 silc_buffer_free(idp);
3623 SilcServerEntry entry;
3625 /* Check whether we have this server cached */
3626 entry = silc_idlist_find_server_by_name(server->global_list,
3627 dest_server, TRUE, NULL);
3629 entry = silc_idlist_find_server_by_name(server->local_list,
3630 dest_server, TRUE, NULL);
3633 if (server->server_type != SILC_SERVER && !cmd->pending &&
3634 entry && !entry->motd) {
3635 /* Send to the server */
3637 SilcUInt16 old_ident;
3639 old_ident = silc_command_get_ident(cmd->payload);
3640 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3641 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3643 silc_server_packet_send(server, entry->connection,
3644 SILC_PACKET_COMMAND, cmd->packet->flags,
3645 tmpbuf->data, tmpbuf->len, TRUE);
3647 /* Reprocess this packet after received reply from router */
3648 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3649 silc_command_get_ident(cmd->payload),
3650 silc_server_command_motd,
3651 silc_server_command_dup(cmd));
3652 cmd->pending = TRUE;
3653 silc_command_set_ident(cmd->payload, old_ident);
3654 silc_buffer_free(tmpbuf);
3658 if (!entry && !cmd->pending && !server->standalone) {
3659 /* Send to the primary router */
3661 SilcUInt16 old_ident;
3663 old_ident = silc_command_get_ident(cmd->payload);
3664 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3665 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3667 silc_server_packet_send(server, server->router->connection,
3668 SILC_PACKET_COMMAND, cmd->packet->flags,
3669 tmpbuf->data, tmpbuf->len, TRUE);
3671 /* Reprocess this packet after received reply from router */
3672 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3673 silc_command_get_ident(cmd->payload),
3674 silc_server_command_motd,
3675 silc_server_command_dup(cmd));
3676 cmd->pending = TRUE;
3677 silc_command_set_ident(cmd->payload, old_ident);
3678 silc_buffer_free(tmpbuf);
3683 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3684 SILC_STATUS_ERR_NO_SUCH_SERVER);
3688 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3689 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3690 SILC_STATUS_OK, 0, ident, 2,
3694 strlen(entry->motd) : 0);
3695 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3696 packet->data, packet->len, FALSE);
3697 silc_buffer_free(packet);
3698 silc_buffer_free(idp);
3702 silc_server_command_free(cmd);
3705 /* Server side of command UMODE. Client can use this command to set/unset
3706 user mode. Client actually cannot set itself to be as server/router
3707 operator so this can be used only to unset the modes. */
3709 SILC_SERVER_CMD_FUNC(umode)
3711 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3712 SilcServer server = cmd->server;
3713 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3715 unsigned char *tmp_mask, m[4];
3716 SilcUInt32 mask = 0;
3717 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3718 bool set_mask = FALSE;
3720 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3723 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2);
3725 /* Get the client's mode mask */
3726 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3728 SILC_GET32_MSB(mask, tmp_mask);
3733 /* Check that mode changing is allowed. */
3734 if (!silc_server_check_umode_rights(server, client, mask)) {
3735 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3736 SILC_STATUS_ERR_PERM_DENIED);
3740 /* Anonymous mode cannot be set by client */
3741 if (mask & SILC_UMODE_ANONYMOUS) {
3742 if (!(client->mode & SILC_UMODE_ANONYMOUS)) {
3743 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3744 SILC_STATUS_ERR_PERM_DENIED);
3748 if (client->mode & SILC_UMODE_ANONYMOUS) {
3749 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3750 SILC_STATUS_ERR_PERM_DENIED);
3755 /* Change the mode */
3756 client->mode = mask;
3758 /* Send UMODE change to primary router */
3759 if (!server->standalone)
3760 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3761 client->id, client->mode);
3764 /* Send command reply to sender */
3765 SILC_PUT32_MSB(client->mode, m);
3766 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3767 SILC_STATUS_OK, 0, ident, 1,
3769 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3770 packet->data, packet->len, FALSE);
3771 silc_buffer_free(packet);
3774 silc_server_command_free(cmd);
3777 /* Server side command of CMODE. Changes channel mode */
3779 SILC_SERVER_CMD_FUNC(cmode)
3781 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3782 SilcServer server = cmd->server;
3783 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3784 SilcIDListData idata = (SilcIDListData)client;
3785 SilcChannelID *channel_id = NULL;
3786 SilcChannelEntry channel;
3787 SilcChannelClientEntry chl;
3788 SilcBuffer packet, cidp;
3789 unsigned char *tmp, *tmp_id, *tmp_mask;
3790 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3791 SilcUInt32 mode_mask = 0, tmp_len, tmp_len2;
3792 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3793 bool set_mask = FALSE;
3795 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 7);
3797 /* Get Channel ID */
3798 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3800 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3801 SILC_STATUS_ERR_NO_CHANNEL_ID);
3804 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
3806 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3807 SILC_STATUS_ERR_NO_CHANNEL_ID);
3811 /* Get the channel mode mask */
3812 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3814 SILC_GET32_MSB(mode_mask, tmp_mask);
3818 /* Get channel entry */
3819 channel = silc_idlist_find_channel_by_id(server->local_list,
3822 channel = silc_idlist_find_channel_by_id(server->global_list,
3825 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3826 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3831 /* Check whether this client is on the channel */
3832 if (!silc_server_client_on_channel(client, channel, &chl)) {
3833 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3834 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3838 /* Check that client has rights to change any requested channel modes */
3839 if (set_mask && !silc_server_check_cmode_rights(server, channel, chl,
3841 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3843 SILC_STATUS_ERR_NO_CHANNEL_PRIV :
3844 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV));
3848 /* If mode mask was not sent as argument then merely return the current
3849 mode mask to the sender. */
3852 SILC_PUT32_MSB(channel->mode, m);
3853 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3854 SILC_STATUS_OK, 0, ident, 2,
3855 2, tmp_id, tmp_len2,
3857 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3858 packet->data, packet->len, FALSE);
3859 silc_buffer_free(packet);
3864 * Check the modes. Modes that requires nothing special operation are
3868 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3869 /* Channel uses private keys to protect traffic. Client(s) has set the
3870 key locally they want to use, server does not know that key. */
3871 /* Nothing interesting to do here */
3873 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3874 /* The mode is removed and we need to generate and distribute
3875 new channel key. Clients are not using private channel keys
3876 anymore after this. */
3878 /* Re-generate channel key */
3879 if (!silc_server_create_channel_key(server, channel, 0))
3882 /* Send the channel key. This sends it to our local clients and if
3883 we are normal server to our router as well. */
3884 silc_server_send_channel_key(server, NULL, channel,
3885 server->server_type == SILC_ROUTER ?
3886 FALSE : !server->standalone);
3888 cipher = channel->channel_key->cipher->name;
3889 hmac = (char *)silc_hmac_get_name(channel->hmac);
3893 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3894 /* User limit is set on channel */
3895 SilcUInt32 user_limit;
3897 /* Get user limit */
3898 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3900 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3901 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3902 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3906 SILC_GET32_MSB(user_limit, tmp);
3907 channel->user_limit = user_limit;
3910 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3911 /* User limit mode is unset. Remove user limit */
3912 channel->user_limit = 0;
3915 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3916 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3917 /* Passphrase has been set to channel */
3919 /* Get the passphrase */
3920 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3922 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3923 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3927 /* Save the passphrase */
3928 passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
3931 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3932 /* Passphrase mode is unset. remove the passphrase */
3933 silc_free(channel->passphrase);
3934 channel->passphrase = NULL;
3938 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3939 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3940 /* Cipher to use protect the traffic */
3941 SilcCipher newkey, oldkey;
3944 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3946 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3947 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3951 /* Delete old cipher and allocate the new one */
3952 if (!silc_cipher_alloc(cipher, &newkey)) {
3953 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3954 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3958 oldkey = channel->channel_key;
3959 channel->channel_key = newkey;
3961 /* Re-generate channel key */
3962 if (!silc_server_create_channel_key(server, channel, 0)) {
3963 /* We don't have new key, revert to old one */
3964 channel->channel_key = oldkey;
3968 /* Remove old channel key for good */
3969 silc_cipher_free(oldkey);
3971 /* Send the channel key. This sends it to our local clients and if
3972 we are normal server to our router as well. */
3973 silc_server_send_channel_key(server, NULL, channel,
3974 server->server_type == SILC_ROUTER ?
3975 FALSE : !server->standalone);
3978 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3979 /* Cipher mode is unset. Remove the cipher and revert back to
3981 SilcCipher newkey, oldkey;
3982 cipher = channel->cipher;
3984 /* Delete old cipher and allocate default one */
3985 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
3986 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3987 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3991 oldkey = channel->channel_key;
3992 channel->channel_key = newkey;
3994 /* Re-generate channel key */
3995 if (!silc_server_create_channel_key(server, channel, 0)) {
3996 /* We don't have new key, revert to old one */
3997 channel->channel_key = oldkey;
4001 /* Remove old channel key for good */
4002 silc_cipher_free(oldkey);
4004 /* Send the channel key. This sends it to our local clients and if
4005 we are normal server to our router as well. */
4006 silc_server_send_channel_key(server, NULL, channel,
4007 server->server_type == SILC_ROUTER ?
4008 FALSE : !server->standalone);
4012 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
4013 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
4014 /* HMAC to use protect the traffic */
4015 unsigned char hash[32];
4019 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4021 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4022 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4026 /* Delete old hmac and allocate the new one */
4027 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4028 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4029 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4033 silc_hmac_free(channel->hmac);
4034 channel->hmac = newhmac;
4036 /* Set the HMAC key out of current channel key. The client must do
4038 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4039 channel->key_len / 8, hash);
4040 silc_hmac_set_key(channel->hmac, hash,
4041 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4042 memset(hash, 0, sizeof(hash));
4045 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4046 /* Hmac mode is unset. Remove the hmac and revert back to
4049 unsigned char hash[32];
4050 hmac = channel->hmac_name;
4052 /* Delete old hmac and allocate default one */
4053 silc_hmac_free(channel->hmac);
4054 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4055 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4056 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4060 silc_hmac_free(channel->hmac);
4061 channel->hmac = newhmac;
4063 /* Set the HMAC key out of current channel key. The client must do
4065 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4066 channel->key_len / 8,
4068 silc_hmac_set_key(channel->hmac, hash,
4069 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4070 memset(hash, 0, sizeof(hash));
4074 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4075 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4076 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4077 /* Set the founder authentication */
4078 SilcAuthPayload auth;
4080 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4082 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4083 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4087 auth = silc_auth_payload_parse(tmp, tmp_len);
4089 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4090 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4094 /* Save the public key */
4095 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
4096 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
4099 channel->founder_method = silc_auth_get_method(auth);
4101 if (channel->founder_method == SILC_AUTH_PASSWORD) {
4102 tmp = silc_auth_get_data(auth, &tmp_len);
4103 channel->founder_passwd = silc_memdup(tmp, tmp_len);
4104 channel->founder_passwd_len = tmp_len;
4106 /* Verify the payload before setting the mode */
4107 if (!silc_auth_verify(auth, channel->founder_method,
4108 channel->founder_key, 0, idata->hash,
4109 client->id, SILC_ID_CLIENT)) {
4110 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4111 SILC_STATUS_ERR_AUTH_FAILED);
4116 silc_auth_payload_free(auth);
4120 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4121 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4122 if (channel->founder_key)
4123 silc_pkcs_public_key_free(channel->founder_key);
4124 if (channel->founder_passwd) {
4125 silc_free(channel->founder_passwd);
4126 channel->founder_passwd = NULL;
4132 /* Finally, set the mode */
4133 channel->mode = mode_mask;
4135 /* Send CMODE_CHANGE notify. */
4136 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4137 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4138 SILC_NOTIFY_TYPE_CMODE_CHANGE, 5,
4139 cidp->data, cidp->len,
4141 cipher, cipher ? strlen(cipher) : 0,
4142 hmac, hmac ? strlen(hmac) : 0,
4143 passphrase, passphrase ?
4144 strlen(passphrase) : 0);
4146 /* Set CMODE notify type to network */
4147 if (!server->standalone)
4148 silc_server_send_notify_cmode(server, server->router->connection,
4149 server->server_type == SILC_ROUTER ?
4150 TRUE : FALSE, channel,
4151 mode_mask, client->id, SILC_ID_CLIENT,
4152 cipher, hmac, passphrase);
4154 /* Send command reply to sender */
4155 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4156 SILC_STATUS_OK, 0, ident, 2,
4157 2, tmp_id, tmp_len2,
4159 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4160 packet->data, packet->len, FALSE);
4162 silc_buffer_free(packet);
4163 silc_buffer_free(cidp);
4166 silc_free(channel_id);
4167 silc_server_command_free(cmd);
4170 /* Server side of CUMODE command. Changes client's mode on a channel. */
4172 SILC_SERVER_CMD_FUNC(cumode)
4174 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4175 SilcServer server = cmd->server;
4176 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4177 SilcIDListData idata = (SilcIDListData)client;
4178 SilcChannelID *channel_id;
4179 SilcClientID *client_id;
4180 SilcChannelEntry channel;
4181 SilcClientEntry target_client;
4182 SilcChannelClientEntry chl;
4183 SilcBuffer packet, idp;
4184 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4185 SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4187 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4189 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4191 /* Get Channel ID */
4192 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4194 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4195 SILC_STATUS_ERR_NO_CHANNEL_ID);
4198 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
4200 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4201 SILC_STATUS_ERR_NO_CHANNEL_ID);
4205 /* Get channel entry */
4206 channel = silc_idlist_find_channel_by_id(server->local_list,
4209 channel = silc_idlist_find_channel_by_id(server->global_list,
4212 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4213 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4218 /* Check whether sender is on the channel */
4219 if (!silc_server_client_on_channel(client, channel, &chl)) {
4220 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4221 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4224 sender_mask = chl->mode;
4226 /* Get the target client's channel mode mask */
4227 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4229 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4230 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4233 SILC_GET32_MSB(target_mask, tmp_mask);
4235 /* Get target Client ID */
4236 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4238 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4239 SILC_STATUS_ERR_NO_CLIENT_ID);
4242 client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
4244 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4245 SILC_STATUS_ERR_NO_CLIENT_ID);
4249 /* Get target client's entry */
4250 target_client = silc_idlist_find_client_by_id(server->local_list,
4251 client_id, TRUE, NULL);
4252 if (!target_client) {
4253 target_client = silc_idlist_find_client_by_id(server->global_list,
4254 client_id, TRUE, NULL);
4257 if (target_client != client &&
4258 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4259 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4260 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4261 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4265 /* Check whether target client is on the channel */
4266 if (target_client != client) {
4267 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4268 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4269 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4278 /* If the target client is founder, no one else can change their mode
4280 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4281 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4282 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4286 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4287 if (target_client != client) {
4288 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4289 SILC_STATUS_ERR_NOT_YOU);
4293 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4294 /* The client tries to claim the founder rights. */
4295 unsigned char *tmp_auth;
4296 SilcUInt32 tmp_auth_len, auth_len;
4299 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4300 !channel->founder_key || !idata->public_key ||
4301 !silc_pkcs_public_key_compare(channel->founder_key,
4302 idata->public_key)) {
4303 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4304 SILC_STATUS_ERR_NOT_YOU);
4308 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4310 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4311 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4315 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4316 (void *)channel->founder_passwd : (void *)channel->founder_key);
4317 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4318 channel->founder_passwd_len : 0);
4320 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4321 channel->founder_method, auth, auth_len,
4322 idata->hash, client->id, SILC_ID_CLIENT)) {
4323 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4324 SILC_STATUS_ERR_AUTH_FAILED);
4328 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4332 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4333 if (target_client == client) {
4334 /* Remove channel founder rights from itself */
4335 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4338 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4339 SILC_STATUS_ERR_NOT_YOU);
4345 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4346 /* Promote to operator */
4347 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4348 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4349 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4350 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4351 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4355 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4359 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4360 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4361 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4362 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4363 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4367 /* Demote to normal user */
4368 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4373 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4374 if (target_client != client) {
4375 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4376 SILC_STATUS_ERR_NOT_YOU);
4380 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
4381 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4385 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4386 if (target_client != client) {
4387 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4388 SILC_STATUS_ERR_NOT_YOU);
4392 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4398 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4399 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4401 /* Send notify to channel, notify only if mode was actually changed. */
4403 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4404 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4405 idp->data, idp->len,
4409 /* Set CUMODE notify type to network */
4410 if (!server->standalone)
4411 silc_server_send_notify_cumode(server, server->router->connection,
4412 server->server_type == SILC_ROUTER ?
4413 TRUE : FALSE, channel,
4414 target_mask, client->id,
4419 /* Send command reply to sender */
4420 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4421 SILC_STATUS_OK, 0, ident, 3,
4423 3, tmp_ch_id, tmp_ch_len,
4424 4, tmp_id, tmp_len);
4425 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4426 packet->data, packet->len, FALSE);
4428 silc_buffer_free(packet);
4429 silc_free(channel_id);
4430 silc_free(client_id);
4431 silc_buffer_free(idp);
4434 silc_server_command_free(cmd);
4437 /* Server side of KICK command. Kicks client out of channel. */
4439 SILC_SERVER_CMD_FUNC(kick)
4441 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4442 SilcServer server = cmd->server;
4443 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4444 SilcClientEntry target_client;
4445 SilcChannelID *channel_id;
4446 SilcClientID *client_id;
4447 SilcChannelEntry channel;
4448 SilcChannelClientEntry chl;
4450 SilcUInt32 tmp_len, target_idp_len;
4451 unsigned char *tmp, *comment, *target_idp;
4453 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4455 /* Get Channel ID */
4456 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4458 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4459 SILC_STATUS_ERR_NO_CHANNEL_ID);
4462 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4464 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4465 SILC_STATUS_ERR_NO_CHANNEL_ID);
4469 /* Get channel entry */
4470 channel = silc_idlist_find_channel_by_id(server->local_list,
4473 channel = silc_idlist_find_channel_by_id(server->local_list,
4476 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4477 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4482 /* Check whether sender is on the channel */
4483 if (!silc_server_client_on_channel(client, channel, &chl)) {
4484 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4485 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4489 /* Check that the kicker is channel operator or channel founder */
4490 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4491 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4492 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4496 /* Get target Client ID */
4497 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4499 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4500 SILC_STATUS_ERR_NO_CLIENT_ID);
4503 client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
4505 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4506 SILC_STATUS_ERR_NO_CLIENT_ID);
4510 /* Get target client's entry */
4511 target_client = silc_idlist_find_client_by_id(server->local_list,
4512 client_id, TRUE, NULL);
4513 if (!target_client) {
4514 target_client = silc_idlist_find_client_by_id(server->global_list,
4515 client_id, TRUE, NULL);
4518 /* Check whether target client is on the channel */
4519 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4520 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4521 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4525 /* Check that the target client is not channel founder. Channel founder
4526 cannot be kicked from the channel. */
4527 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4528 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4529 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4535 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4539 /* Send command reply to sender */
4540 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4543 /* Send KICKED notify to local clients on the channel */
4544 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4545 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4546 SILC_NOTIFY_TYPE_KICKED, 3,
4547 target_idp, target_idp_len,
4548 comment, comment ? strlen(comment) : 0,
4549 idp->data, idp->len);
4550 silc_buffer_free(idp);
4552 /* Remove the client from the channel. If the channel does not exist
4553 after removing the client then the client kicked itself off the channel
4554 and we don't have to send anything after that. */
4555 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4556 target_client, FALSE))
4559 /* Send KICKED notify to primary route */
4560 if (!server->standalone)
4561 silc_server_send_notify_kicked(server, server->router->connection,
4562 server->server_type == SILC_ROUTER ?
4563 TRUE : FALSE, channel,
4564 target_client->id, client->id, comment);
4566 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4567 /* Re-generate channel key */
4568 if (!silc_server_create_channel_key(server, channel, 0))
4571 /* Send the channel key to the channel. The key of course is not sent
4572 to the client who was kicked off the channel. */
4573 silc_server_send_channel_key(server, target_client->connection, channel,
4574 server->server_type == SILC_ROUTER ?
4575 FALSE : !server->standalone);
4579 silc_server_command_free(cmd);
4582 /* Server side of OPER command. Client uses this comand to obtain server
4583 operator privileges to this server/router. */
4585 SILC_SERVER_CMD_FUNC(oper)
4587 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4588 SilcServer server = cmd->server;
4589 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4590 unsigned char *username, *auth;
4592 SilcServerConfigAdmin *admin;
4593 SilcIDListData idata = (SilcIDListData)client;
4594 bool result = FALSE;
4595 SilcPublicKey cached_key;
4597 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4599 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4602 /* Get the username */
4603 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4605 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4606 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4610 /* Get the admin configuration */
4611 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4612 username, client->nickname);
4614 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4615 username, client->nickname);
4617 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4618 SILC_STATUS_ERR_AUTH_FAILED);
4623 /* Get the authentication payload */
4624 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4626 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4627 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4631 /* Verify the authentication data. If both passphrase and public key
4632 is set then try both of them. */
4633 if (admin->passphrase)
4634 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4635 admin->passphrase, admin->passphrase_len,
4636 idata->hash, client->id, SILC_ID_CLIENT);
4637 if (!result && admin->publickeys) {
4638 cached_key = silc_server_get_public_key(server, admin->publickeys);
4641 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4642 cached_key, 0, idata->hash,
4643 client->id, SILC_ID_CLIENT);
4646 /* Authentication failed */
4647 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4648 SILC_STATUS_ERR_AUTH_FAILED);
4652 /* Client is now server operator */
4653 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4655 /* Update statistics */
4656 if (client->connection)
4657 server->stat.my_server_ops++;
4658 if (server->server_type == SILC_ROUTER)
4659 server->stat.server_ops++;
4661 /* Send UMODE change to primary router */
4662 if (!server->standalone)
4663 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4664 client->id, client->mode);
4666 /* Send reply to the sender */
4667 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4671 silc_server_command_free(cmd);
4674 SILC_TASK_CALLBACK(silc_server_command_detach_cb)
4676 QuitInternal q = (QuitInternal)context;
4677 SilcClientEntry client = (SilcClientEntry)q->sock->user_data;
4679 /* If there is pending outgoing data for the client then purge it
4680 to the network before closing connection. */
4681 silc_server_packet_queue_purge(q->server, q->sock);
4683 /* Close the connection on our side */
4684 client->router = NULL;
4685 client->connection = NULL;
4686 q->sock->user_data = NULL;
4687 silc_server_close_connection(q->server, q->sock);
4692 SILC_TASK_CALLBACK(silc_server_command_detach_timeout)
4694 QuitInternal q = (QuitInternal)context;
4695 SilcClientEntry client = (SilcClientEntry)q->sock;
4697 SILC_LOG_DEBUG(("Start"));
4699 if (client->mode & SILC_UMODE_DETACHED)
4700 silc_server_free_client_data(q->server, NULL, client, TRUE,
4705 /* Server side of DETACH command. Detached the client from the network
4706 by closing the connection but preserving the session. */
4708 SILC_SERVER_CMD_FUNC(detach)
4710 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4711 SilcServer server = cmd->server;
4712 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4715 if (server->config->detach_disabled) {
4716 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
4717 SILC_STATUS_ERR_UNKNOWN_COMMAND);
4721 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4724 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
4726 /* Send the user mode notify to notify that client is detached */
4727 client->mode |= SILC_UMODE_DETACHED;
4728 client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
4729 if (!server->standalone)
4730 silc_server_send_notify_umode(server, server->router->connection,
4731 server->server_type == SILC_SERVER ?
4732 FALSE : TRUE, client->id, client->mode);
4734 q = silc_calloc(1, sizeof(*q));
4736 q->sock = cmd->sock;
4737 silc_schedule_task_add(server->schedule, 0, silc_server_command_detach_cb,
4738 q, 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
4740 if (server->config->detach_timeout) {
4741 q = silc_calloc(1, sizeof(*q));
4743 q->sock = (void *)client;
4744 silc_schedule_task_add(server->schedule, 0,
4745 silc_server_command_detach_timeout,
4746 q, server->config->detach_timeout * 60,
4747 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
4750 /* Send reply to the sender */
4751 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
4755 silc_server_command_free(cmd);
4758 /* Server side of SILCOPER command. Client uses this comand to obtain router
4759 operator privileges to this router. */
4761 SILC_SERVER_CMD_FUNC(silcoper)
4763 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4764 SilcServer server = cmd->server;
4765 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4766 unsigned char *username, *auth;
4768 SilcServerConfigAdmin *admin;
4769 SilcIDListData idata = (SilcIDListData)client;
4770 bool result = FALSE;
4771 SilcPublicKey cached_key;
4773 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4775 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4778 if (server->server_type != SILC_ROUTER) {
4779 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4780 SILC_STATUS_ERR_AUTH_FAILED);
4784 /* Get the username */
4785 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4787 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4788 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4792 /* Get the admin configuration */
4793 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4794 username, client->nickname);
4796 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4797 username, client->nickname);
4799 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4800 SILC_STATUS_ERR_AUTH_FAILED);
4805 /* Get the authentication payload */
4806 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4808 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4809 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4813 /* Verify the authentication data. If both passphrase and public key
4814 is set then try both of them. */
4815 if (admin->passphrase)
4816 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4817 admin->passphrase, admin->passphrase_len,
4818 idata->hash, client->id, SILC_ID_CLIENT);
4819 if (!result && admin->publickeys) {
4820 cached_key = silc_server_get_public_key(server, admin->publickeys);
4823 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4824 cached_key, 0, idata->hash,
4825 client->id, SILC_ID_CLIENT);
4828 /* Authentication failed */
4829 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4830 SILC_STATUS_ERR_AUTH_FAILED);
4834 /* Client is now router operator */
4835 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4837 /* Update statistics */
4838 if (client->connection)
4839 server->stat.my_router_ops++;
4840 if (server->server_type == SILC_ROUTER)
4841 server->stat.router_ops++;
4843 /* Send UMODE change to primary router */
4844 if (!server->standalone)
4845 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4846 client->id, client->mode);
4848 /* Send reply to the sender */
4849 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4853 silc_server_command_free(cmd);
4856 /* Server side of command BAN. This is used to manage the ban list of the
4857 channel. To add clients and remove clients from the ban list. */
4859 SILC_SERVER_CMD_FUNC(ban)
4861 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4862 SilcServer server = cmd->server;
4863 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4865 SilcChannelEntry channel;
4866 SilcChannelClientEntry chl;
4867 SilcChannelID *channel_id = NULL;
4868 unsigned char *id, *add, *del;
4869 SilcUInt32 id_len, tmp_len;
4870 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4872 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4875 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4877 /* Get Channel ID */
4878 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4880 channel_id = silc_id_payload_parse_id(id, id_len, NULL);
4882 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4883 SILC_STATUS_ERR_NO_CHANNEL_ID);
4888 /* Get channel entry. The server must know about the channel since the
4889 client is expected to be on the channel. */
4890 channel = silc_idlist_find_channel_by_id(server->local_list,
4893 channel = silc_idlist_find_channel_by_id(server->global_list,
4896 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4897 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4902 /* Check whether this client is on the channel */
4903 if (!silc_server_client_on_channel(client, channel, &chl)) {
4904 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4905 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4909 /* The client must be at least channel operator. */
4910 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4911 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4912 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4916 /* Get the new ban and add it to the ban list */
4917 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4919 if (!channel->ban_list)
4920 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4922 channel->ban_list = silc_realloc(channel->ban_list,
4923 sizeof(*channel->ban_list) *
4925 strlen(channel->ban_list) + 2));
4926 if (add[tmp_len - 1] == ',')
4927 add[tmp_len - 1] = '\0';
4929 strncat(channel->ban_list, add, tmp_len);
4930 strncat(channel->ban_list, ",", 1);
4933 /* Get the ban to be removed and remove it from the list */
4934 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4935 if (del && channel->ban_list) {
4936 char *start, *end, *n;
4938 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4939 silc_free(channel->ban_list);
4940 channel->ban_list = NULL;
4942 start = strstr(channel->ban_list, del);
4943 if (start && strlen(start) >= tmp_len) {
4944 end = start + tmp_len;
4945 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4946 strncat(n, channel->ban_list, start - channel->ban_list);
4947 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4949 silc_free(channel->ban_list);
4950 channel->ban_list = n;
4955 /* Send the BAN notify type to our primary router. */
4956 if (!server->standalone && (add || del))
4957 silc_server_send_notify_ban(server, server->router->connection,
4958 server->server_type == SILC_ROUTER ?
4959 TRUE : FALSE, channel, add, del);
4961 /* Send the reply back to the client */
4963 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4964 SILC_STATUS_OK, 0, ident, 2,
4966 3, channel->ban_list,
4968 strlen(channel->ban_list) -1 : 0);
4969 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4970 packet->data, packet->len, FALSE);
4972 silc_buffer_free(packet);
4975 silc_free(channel_id);
4976 silc_server_command_free(cmd);
4979 /* Server side command of LEAVE. Removes client from a channel. */
4981 SILC_SERVER_CMD_FUNC(leave)
4983 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4984 SilcServer server = cmd->server;
4985 SilcSocketConnection sock = cmd->sock;
4986 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4987 SilcChannelID *id = NULL;
4988 SilcChannelEntry channel;
4992 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4994 /* Get Channel ID */
4995 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4997 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4998 SILC_STATUS_ERR_NO_CHANNEL_ID);
5001 id = silc_id_payload_parse_id(tmp, len, NULL);
5003 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5004 SILC_STATUS_ERR_NO_CHANNEL_ID);
5008 /* Get channel entry */
5009 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5011 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5013 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5014 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5019 /* Check whether this client is on the channel */
5020 if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
5021 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5022 SILC_STATUS_ERR_NOT_ON_CHANNEL);
5026 /* Notify routers that they should remove this client from their list
5027 of clients on the channel. Send LEAVE notify type. */
5028 if (!server->standalone)
5029 silc_server_send_notify_leave(server, server->router->connection,
5030 server->server_type == SILC_ROUTER ?
5031 TRUE : FALSE, channel, id_entry->id);
5033 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
5034 SILC_STATUS_OK, 2, tmp, len);
5036 /* Remove client from channel */
5037 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5039 /* If the channel does not exist anymore we won't send anything */
5042 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5043 /* Re-generate channel key */
5044 if (!silc_server_create_channel_key(server, channel, 0))
5047 /* Send the channel key */
5048 silc_server_send_channel_key(server, NULL, channel,
5049 server->server_type == SILC_ROUTER ?
5050 FALSE : !server->standalone);
5055 silc_server_command_free(cmd);
5058 /* Server side of command USERS. Resolves clients and their USERS currently
5059 joined on the requested channel. The list of Client ID's and their modes
5060 on the channel is sent back. */
5062 SILC_SERVER_CMD_FUNC(users)
5064 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5065 SilcServer server = cmd->server;
5066 SilcChannelEntry channel;
5067 SilcChannelID *id = NULL;
5068 SilcBuffer packet, idp;
5069 unsigned char *channel_id;
5070 SilcUInt32 channel_id_len;
5071 SilcBuffer client_id_list;
5072 SilcBuffer client_mode_list;
5073 unsigned char lc[4];
5074 SilcUInt32 list_count = 0;
5075 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5078 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5080 /* Get Channel ID */
5081 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5083 /* Get channel name */
5084 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5086 if (!channel_id && !channel_name) {
5087 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5088 SILC_STATUS_ERR_NO_CHANNEL_ID);
5093 id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
5095 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5096 SILC_STATUS_ERR_NO_CHANNEL_ID);
5101 /* If we are server and we don't know about this channel we will send
5102 the command to our router. If we know about the channel then we also
5103 have the list of users already. */
5105 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5107 channel = silc_idlist_find_channel_by_name(server->local_list,
5108 channel_name, NULL);
5110 if (!channel || channel->disabled || !channel->users_resolved) {
5111 if (server->server_type != SILC_ROUTER && !server->standalone &&
5115 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5116 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5118 /* Send USERS command */
5119 silc_server_packet_send(server, server->router->connection,
5120 SILC_PACKET_COMMAND, cmd->packet->flags,
5121 tmpbuf->data, tmpbuf->len, TRUE);
5123 /* Reprocess this packet after received reply */
5124 silc_server_command_pending(server, SILC_COMMAND_USERS,
5125 silc_command_get_ident(cmd->payload),
5126 silc_server_command_users,
5127 silc_server_command_dup(cmd));
5128 cmd->pending = TRUE;
5129 silc_command_set_ident(cmd->payload, ident);
5130 silc_buffer_free(tmpbuf);
5135 /* Check the global list as well. */
5137 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5139 channel = silc_idlist_find_channel_by_name(server->global_list,
5140 channel_name, NULL);
5142 /* Channel really does not exist */
5143 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5144 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5149 /* If the channel is private or secret do not send anything, unless the
5150 user requesting this command is on the channel or is server */
5151 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5152 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5153 && !silc_server_client_on_channel(cmd->sock->user_data, channel,
5155 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5156 SILC_STATUS_ERR_NOT_ON_CHANNEL);
5161 /* Get the users list */
5162 silc_server_get_users_on_channel(server, channel, &client_id_list,
5163 &client_mode_list, &list_count);
5166 SILC_PUT32_MSB(list_count, lc);
5169 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5170 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5171 SILC_STATUS_OK, 0, ident, 4,
5172 2, idp->data, idp->len,
5174 4, client_id_list->data,
5175 client_id_list->len,
5176 5, client_mode_list->data,
5177 client_mode_list->len);
5178 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5179 packet->data, packet->len, FALSE);
5181 silc_buffer_free(idp);
5182 silc_buffer_free(packet);
5183 silc_buffer_free(client_id_list);
5184 silc_buffer_free(client_mode_list);
5188 silc_server_command_free(cmd);
5191 /* Server side of command GETKEY. This fetches the client's public key
5192 from the server where to the client is connected. */
5194 SILC_SERVER_CMD_FUNC(getkey)
5196 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5197 SilcServer server = cmd->server;
5199 SilcClientEntry client;
5200 SilcServerEntry server_entry;
5201 SilcClientID *client_id = NULL;
5202 SilcServerID *server_id = NULL;
5203 SilcIDPayload idp = NULL;
5204 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5205 unsigned char *tmp, *pkdata;
5206 SilcUInt32 tmp_len, pklen;
5207 SilcBuffer pk = NULL;
5209 SilcPublicKey public_key;
5211 SILC_LOG_DEBUG(("Start"));
5213 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5215 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5216 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5219 idp = silc_id_payload_parse(tmp, tmp_len);
5221 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5222 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5226 id_type = silc_id_payload_get_type(idp);
5227 if (id_type == SILC_ID_CLIENT) {
5228 client_id = silc_id_payload_get_id(idp);
5230 /* If the client is not found from local list there is no chance it
5231 would be locally connected client so send the command further. */
5232 client = silc_idlist_find_client_by_id(server->local_list,
5233 client_id, TRUE, NULL);
5235 client = silc_idlist_find_client_by_id(server->global_list,
5236 client_id, TRUE, NULL);
5238 if ((!client && !cmd->pending && !server->standalone) ||
5239 (client && !client->connection && !cmd->pending &&
5240 !(client->mode & SILC_UMODE_DETACHED)) ||
5241 (client && !client->data.public_key && !cmd->pending)) {
5243 SilcUInt16 old_ident;
5244 SilcSocketConnection dest_sock;
5246 dest_sock = silc_server_get_client_route(server, NULL, 0,
5247 client_id, NULL, NULL);
5251 old_ident = silc_command_get_ident(cmd->payload);
5252 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5253 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5255 silc_server_packet_send(server, dest_sock,
5256 SILC_PACKET_COMMAND, cmd->packet->flags,
5257 tmpbuf->data, tmpbuf->len, TRUE);
5259 /* Reprocess this packet after received reply from router */
5260 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5261 silc_command_get_ident(cmd->payload),
5262 silc_server_command_getkey,
5263 silc_server_command_dup(cmd));
5264 cmd->pending = TRUE;
5265 silc_command_set_ident(cmd->payload, old_ident);
5266 silc_buffer_free(tmpbuf);
5271 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5272 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5276 /* The client is locally connected, just get the public key and
5277 send it back. If they key does not exist then do not send it,
5278 send just OK reply */
5279 public_key = client->data.public_key;
5284 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5285 pk = silc_buffer_alloc(4 + tmp_len);
5286 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5287 silc_buffer_format(pk,
5288 SILC_STR_UI_SHORT(tmp_len),
5289 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5290 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5296 } else if (id_type == SILC_ID_SERVER) {
5297 server_id = silc_id_payload_get_id(idp);
5299 /* If the server is not found from local list there is no chance it
5300 would be locally connected server so send the command further. */
5301 server_entry = silc_idlist_find_server_by_id(server->local_list,
5302 server_id, TRUE, NULL);
5304 server_entry = silc_idlist_find_server_by_id(server->global_list,
5305 server_id, TRUE, NULL);
5307 if (server_entry != server->id_entry &&
5308 ((!server_entry && !cmd->pending && !server->standalone) ||
5309 (server_entry && !server_entry->connection && !cmd->pending &&
5310 !server->standalone) ||
5311 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5312 !server->standalone))) {
5314 SilcUInt16 old_ident;
5316 old_ident = silc_command_get_ident(cmd->payload);
5317 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5318 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5320 silc_server_packet_send(server, server->router->connection,
5321 SILC_PACKET_COMMAND, cmd->packet->flags,
5322 tmpbuf->data, tmpbuf->len, TRUE);
5324 /* Reprocess this packet after received reply from router */
5325 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5326 silc_command_get_ident(cmd->payload),
5327 silc_server_command_getkey,
5328 silc_server_command_dup(cmd));
5329 cmd->pending = TRUE;
5330 silc_command_set_ident(cmd->payload, old_ident);
5331 silc_buffer_free(tmpbuf);
5335 if (!server_entry) {
5336 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5337 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5341 /* If they key does not exist then do not send it, send just OK reply */
5342 public_key = (!server_entry->data.public_key ?
5343 (server_entry == server->id_entry ? server->public_key :
5344 NULL) : server_entry->data.public_key);
5349 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5350 pk = silc_buffer_alloc(4 + tmp_len);
5351 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5352 silc_buffer_format(pk,
5353 SILC_STR_UI_SHORT(tmp_len),
5354 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5355 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5365 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5366 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5367 SILC_STATUS_OK, 0, ident,
5371 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5372 packet->data, packet->len, FALSE);
5373 silc_buffer_free(packet);
5376 silc_buffer_free(pk);
5380 silc_id_payload_free(idp);
5381 silc_free(client_id);
5382 silc_free(server_id);
5383 silc_server_command_free(cmd);
5387 /* Private range commands, specific to this implementation */
5389 /* Server side command of CONNECT. Connects us to the specified remote
5390 server or router. */
5392 SILC_SERVER_CMD_FUNC(connect)
5394 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5395 SilcServer server = cmd->server;
5396 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5397 unsigned char *tmp, *host;
5399 SilcUInt32 port = SILC_PORT;
5401 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
5403 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5406 /* Check whether client has the permissions. */
5407 if (client->mode == SILC_UMODE_NONE) {
5408 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5409 SILC_STATUS_ERR_NO_SERVER_PRIV);
5413 if (server->server_type == SILC_ROUTER &&
5414 client->mode & SILC_UMODE_SERVER_OPERATOR) {
5415 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5416 SILC_STATUS_ERR_NO_ROUTER_PRIV);
5420 /* Get the remote server */
5421 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5423 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5424 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5429 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5431 SILC_GET32_MSB(port, tmp);
5433 /* Create the connection. It is done with timeout and is async. */
5434 silc_server_create_connection(server, host, port);
5436 /* Send reply to the sender */
5437 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5441 silc_server_command_free(cmd);
5444 /* Server side command of CLOSE. Closes connection to a specified server. */
5446 SILC_SERVER_CMD_FUNC(close)
5448 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5449 SilcServer server = cmd->server;
5450 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5451 SilcServerEntry server_entry;
5452 SilcSocketConnection sock;
5455 unsigned char *name;
5456 SilcUInt32 port = SILC_PORT;
5458 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
5460 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5463 /* Check whether client has the permissions. */
5464 if (client->mode == SILC_UMODE_NONE) {
5465 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5466 SILC_STATUS_ERR_NO_SERVER_PRIV);
5470 /* Get the remote server */
5471 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5473 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5474 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5479 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5481 SILC_GET32_MSB(port, tmp);
5483 server_entry = silc_idlist_find_server_by_conn(server->local_list,
5484 name, port, FALSE, NULL);
5486 server_entry = silc_idlist_find_server_by_conn(server->global_list,
5487 name, port, FALSE, NULL);
5488 if (!server_entry) {
5489 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5490 SILC_STATUS_ERR_NO_SERVER_ID);
5494 /* Send reply to the sender */
5495 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5498 /* Close the connection to the server */
5499 sock = (SilcSocketConnection)server_entry->connection;
5501 /* If we shutdown primary router connection manually then don't trigger
5502 any reconnect or backup router connections, by setting the router
5504 if (server->router == server_entry) {
5505 server->id_entry->router = NULL;
5506 server->router = NULL;
5507 server->standalone = TRUE;
5509 silc_server_free_sock_user_data(server, sock, NULL);
5510 silc_server_close_connection(server, sock);
5513 silc_server_command_free(cmd);
5516 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
5517 active connections. */
5519 SILC_SERVER_CMD_FUNC(shutdown)
5521 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5522 SilcServer server = cmd->server;
5523 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5525 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
5527 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5530 /* Check whether client has the permission. */
5531 if (client->mode == SILC_UMODE_NONE) {
5532 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5533 SILC_STATUS_ERR_NO_SERVER_PRIV);
5537 /* Send reply to the sender */
5538 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5541 /* Then, gracefully, or not, bring the server down. */
5542 silc_server_stop(server);
5546 silc_server_command_free(cmd);