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(watch, WATCH, SILC_CF_LAG | SILC_CF_REG),
71 SILC_SERVER_CMD(silcoper, SILCOPER,
72 SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
73 SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
74 SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
75 SILC_SERVER_CMD(getkey, GETKEY, SILC_CF_LAG | SILC_CF_REG),
77 SILC_SERVER_CMD(connect, PRIV_CONNECT,
78 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
79 SILC_SERVER_CMD(close, PRIV_CLOSE,
80 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
81 SILC_SERVER_CMD(shutdown, PRIV_SHUTDOWN, SILC_CF_LAG | SILC_CF_REG |
87 /* Performs several checks to the command. It first checks whether this
88 command was called as pending command callback. If it was then it checks
89 whether error occurred in the command reply where the pending command
92 It also checks that the requested command includes correct amount
94 #define SILC_SERVER_COMMAND_CHECK(command, context, min, max) \
98 SILC_LOG_DEBUG(("Start")); \
100 if (silc_server_command_pending_error_check(cmd, context2, command)) { \
101 silc_server_command_free(cmd); \
105 _argc = silc_argument_get_arg_num(cmd->args); \
107 silc_server_command_send_status_reply(cmd, command, \
108 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
109 silc_server_command_free(cmd); \
113 silc_server_command_send_status_reply(cmd, command, \
114 SILC_STATUS_ERR_TOO_MANY_PARAMS); \
115 silc_server_command_free(cmd); \
120 /* Returns TRUE if the connection is registered. Unregistered connections
121 usually cannot send commands hence the check. */
123 static int silc_server_is_registered(SilcServer server,
124 SilcSocketConnection sock,
125 SilcServerCommandContext cmd,
128 SilcIDListData idata = (SilcIDListData)sock->user_data;
133 if (idata->status & SILC_IDLIST_STATUS_REGISTERED)
136 silc_server_command_send_status_reply(cmd, command,
137 SILC_STATUS_ERR_NOT_REGISTERED);
141 /* Internal context to hold data when executed command with timeout. */
143 SilcServerCommandContext ctx;
144 SilcServerCommand *cmd;
145 } *SilcServerCommandTimeout;
147 /* Timeout callback to process commands with timeout for client. Client's
148 commands are always executed with timeout. */
150 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
152 SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
153 SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data;
156 silc_server_command_free(timeout->ctx);
160 /* Update access time */
161 client->last_command = time(NULL);
163 if (!(timeout->cmd->flags & SILC_CF_REG))
164 timeout->cmd->cb(timeout->ctx, NULL);
165 else if (silc_server_is_registered(timeout->ctx->server,
169 timeout->cmd->cb(timeout->ctx, NULL);
171 silc_server_command_free(timeout->ctx);
176 /* Processes received command packet. */
178 void silc_server_command_process(SilcServer server,
179 SilcSocketConnection sock,
180 SilcPacketContext *packet)
182 SilcServerCommandContext ctx;
183 SilcServerCommand *cmd;
186 /* Allocate command context. This must be free'd by the
187 command routine receiving it. */
188 ctx = silc_server_command_alloc();
189 ctx->server = server;
190 ctx->sock = silc_socket_dup(sock);
191 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
193 /* Parse the command payload in the packet */
194 ctx->payload = silc_command_payload_parse(packet->buffer->data,
195 packet->buffer->len);
197 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
198 silc_buffer_free(packet->buffer);
199 silc_packet_context_free(packet);
200 silc_socket_free(ctx->sock);
204 ctx->args = silc_command_get_args(ctx->payload);
206 /* Get the command */
207 command = silc_command_get(ctx->payload);
208 for (cmd = silc_command_list; cmd->cb; cmd++)
209 if (cmd->cmd == command)
212 if (!cmd || !cmd->cb) {
213 silc_server_command_send_status_reply(ctx, command,
214 SILC_STATUS_ERR_UNKNOWN_COMMAND);
215 silc_server_command_free(ctx);
219 /* Execute client's commands always with timeout. Normally they are
220 executed with zero (0) timeout but if client is sending command more
221 frequently than once in 2 seconds, then the timeout may be 0 to 2
223 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
224 SilcClientEntry client = (SilcClientEntry)sock->user_data;
225 SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
231 if (client->last_command && (time(NULL) - client->last_command) < 2) {
232 client->fast_command++;
235 if (client->fast_command - 2 <= 0)
236 client->fast_command = 0;
238 client->fast_command -= 2;
242 if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
243 (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
244 silc_schedule_task_add(server->schedule, sock->sock,
245 silc_server_command_process_timeout, timeout,
246 (client->fast_command < 3 ? 0 :
247 2 - (time(NULL) - client->last_command)),
248 (client->fast_command < 3 ? 200000 : 0),
249 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
251 silc_schedule_task_add(server->schedule, sock->sock,
252 silc_server_command_process_timeout, timeout,
253 0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
257 /* Execute for server */
259 if (!(cmd->flags & SILC_CF_REG))
261 else if (silc_server_is_registered(server, sock, ctx, cmd->cmd))
264 silc_server_command_free(ctx);
267 /* Allocate Command Context */
269 SilcServerCommandContext silc_server_command_alloc()
271 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
276 /* Free's the command context allocated before executing the command */
278 void silc_server_command_free(SilcServerCommandContext ctx)
281 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
283 if (ctx->users < 1) {
285 silc_command_payload_free(ctx->payload);
287 silc_packet_context_free(ctx->packet);
289 silc_socket_free(ctx->sock); /* Decrease reference counter */
294 /* Duplicate Command Context by adding reference counter. The context won't
295 be free'd untill it hits zero. */
297 SilcServerCommandContext
298 silc_server_command_dup(SilcServerCommandContext ctx)
301 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
306 /* Add new pending command to be executed when reply to a command has been
307 received. The `reply_cmd' is the command that will call the `callback'
308 with `context' when reply has been received. It can be SILC_COMMAND_NONE
309 to match any command with the `ident'. If `ident' is non-zero
310 the `callback' will be executed when received reply with command
311 identifier `ident'. If there already exists pending command for the
312 specified command, ident, callback and context this function has no
315 bool silc_server_command_pending(SilcServer server,
316 SilcCommand reply_cmd,
318 SilcCommandCb callback,
321 SilcServerCommandPending *reply;
323 /* Check whether identical pending already exists for same command,
324 ident, callback and callback context. If it does then it would be
325 error to register it again. */
326 silc_dlist_start(server->pending_commands);
327 while ((reply = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
328 if (reply->reply_cmd == reply_cmd && reply->ident == ident &&
329 reply->callback == callback && reply->context == context)
333 reply = silc_calloc(1, sizeof(*reply));
334 reply->reply_cmd = reply_cmd;
335 reply->ident = ident;
336 reply->context = context;
337 reply->callback = callback;
338 silc_dlist_add(server->pending_commands, reply);
343 /* Deletes pending command by reply command type. */
345 void silc_server_command_pending_del(SilcServer server,
346 SilcCommand reply_cmd,
349 SilcServerCommandPending *r;
351 silc_dlist_start(server->pending_commands);
352 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
353 if (r->reply_cmd == reply_cmd && r->ident == ident) {
354 silc_dlist_del(server->pending_commands, r);
360 /* Checks for pending commands and marks callbacks to be called from
361 the command reply function. Returns TRUE if there were pending command. */
363 SilcServerCommandPendingCallbacks
364 silc_server_command_pending_check(SilcServer server,
365 SilcServerCommandReplyContext ctx,
368 SilcUInt32 *callbacks_count)
370 SilcServerCommandPending *r;
371 SilcServerCommandPendingCallbacks callbacks = NULL;
374 silc_dlist_start(server->pending_commands);
375 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
376 if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE)
377 && r->ident == ident) {
378 callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
379 callbacks[i].context = r->context;
380 callbacks[i].callback = r->callback;
386 *callbacks_count = i;
390 /* Sends simple status message as command reply packet */
393 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
399 SILC_LOG_DEBUG(("Sending command status %d", status));
402 silc_command_reply_payload_encode_va(command, status, 0,
403 silc_command_get_ident(cmd->payload),
405 silc_server_packet_send(cmd->server, cmd->sock,
406 SILC_PACKET_COMMAND_REPLY, 0,
407 buffer->data, buffer->len, FALSE);
408 silc_buffer_free(buffer);
411 /* Sends command status reply with one extra argument. The argument
412 type must be sent as argument. */
415 silc_server_command_send_status_data(SilcServerCommandContext cmd,
419 const unsigned char *arg,
424 SILC_LOG_DEBUG(("Sending command status %d", status));
427 silc_command_reply_payload_encode_va(command, status, 0,
428 silc_command_get_ident(cmd->payload),
429 1, arg_type, arg, arg_len);
430 silc_server_packet_send(cmd->server, cmd->sock,
431 SILC_PACKET_COMMAND_REPLY, 0,
432 buffer->data, buffer->len, FALSE);
433 silc_buffer_free(buffer);
436 /* This function can be called to check whether in the command reply
437 an error occurred. This function has no effect if this is called
438 when the command function was not called as pending command callback.
439 This returns TRUE if error had occurred. */
442 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
443 SilcServerCommandReplyContext cmdr,
446 if (!cmd->pending || !cmdr)
449 if (!silc_command_get_status(cmdr->payload, NULL, NULL)) {
452 /* Send the same command reply payload */
453 silc_command_set_ident(cmdr->payload,
454 silc_command_get_ident(cmd->payload));
455 buffer = silc_command_payload_encode_payload(cmdr->payload);
456 silc_server_packet_send(cmd->server, cmd->sock,
457 SILC_PACKET_COMMAND_REPLY, 0,
458 buffer->data, buffer->len, FALSE);
459 silc_buffer_free(buffer);
466 /******************************************************************************
470 ******************************************************************************/
473 silc_server_command_whois_parse(SilcServerCommandContext cmd,
474 SilcClientID ***client_id,
475 SilcUInt32 *client_id_count,
483 SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
486 /* If client ID is in the command it must be used instead of nickname */
487 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
489 /* No ID, get the nickname@server string and parse it. */
490 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
492 silc_parse_userfqdn(tmp, nickname, server_name);
494 silc_server_command_send_status_reply(cmd, command,
495 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
499 /* Command includes ID, we must use that. Also check whether the command
500 has more than one ID set - take them all. */
502 *client_id = silc_calloc(1, sizeof(**client_id));
503 (*client_id)[0] = silc_id_payload_parse_id(tmp, len, NULL);
504 if ((*client_id)[0] == NULL) {
505 silc_free(*client_id);
506 silc_server_command_send_status_reply(cmd, command,
507 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
510 *client_id_count = 1;
512 /* Take all ID's from the command packet */
514 for (k = 1, i = 1; i < argc; i++) {
515 tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
517 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
518 (*client_id_count + 1));
519 (*client_id)[k] = silc_id_payload_parse_id(tmp, len, NULL);
520 if ((*client_id)[k] == NULL) {
521 /* Cleanup all and fail */
522 for (i = 0; i < *client_id_count; i++)
523 silc_free((*client_id)[i]);
524 silc_free(*client_id);
525 silc_server_command_send_status_reply(
527 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
530 (*client_id_count)++;
537 /* Get the max count of reply messages allowed */
538 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
540 SILC_GET32_MSB(*count, tmp);
548 /* Resolve context used by both WHOIS and IDENTIFY commands */
550 SilcServerEntry router;
552 unsigned char **res_argv;
553 SilcUInt32 *res_argv_lens;
554 SilcUInt32 *res_argv_types;
556 } *SilcServerResolveContext;
559 silc_server_command_whois_check(SilcServerCommandContext cmd,
560 SilcClientEntry *clients,
561 SilcUInt32 clients_count)
563 SilcServer server = cmd->server;
564 SilcClientEntry entry;
565 SilcServerResolveContext resolve = NULL, r = NULL;
566 SilcUInt32 resolve_count = 0;
570 SILC_LOG_DEBUG(("Start"));
572 for (i = 0; i < clients_count; i++) {
577 if ((entry->nickname && entry->username && entry->userinfo) ||
578 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
582 /* If we are normal server, and we've not resolved this client from
583 router and it is global client, we'll check whether it is on some
584 channel. If not then we cannot be sure about its validity, and
585 we'll resolve it from router. */
586 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
587 entry->connection || silc_hash_table_count(entry->channels))
591 /* We need to resolve this entry since it is not complete */
593 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
594 /* The entry is being resolved (and we are not the resolver) so attach
595 to the command reply and we're done with this one. */
596 silc_server_command_pending(server, SILC_COMMAND_NONE,
597 entry->resolve_cmd_ident,
598 silc_server_command_whois,
599 silc_server_command_dup(cmd));
602 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
603 /* We've resolved this and it still is not ready. We'll return
604 and are that this will be handled again after it is resolved. */
605 for (i = 0; i < resolve_count; i++) {
606 for (k = 0; k < r->res_argc; k++)
607 silc_free(r->res_argv[k]);
608 silc_free(r->res_argv);
609 silc_free(r->res_argv_lens);
610 silc_free(r->res_argv_types);
615 /* We'll resolve this client */
619 for (k = 0; k < resolve_count; k++) {
620 if (resolve[k].router == entry->router) {
627 resolve = silc_realloc(resolve, sizeof(*resolve) *
628 (resolve_count + 1));
629 r = &resolve[resolve_count];
630 memset(r, 0, sizeof(*r));
631 r->router = entry->router;
632 r->ident = ++server->cmd_ident;
636 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
638 r->res_argv_lens = silc_realloc(r->res_argv_lens,
639 sizeof(*r->res_argv_lens) *
641 r->res_argv_types = silc_realloc(r->res_argv_types,
642 sizeof(*r->res_argv_types) *
644 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
645 r->res_argv[r->res_argc] = silc_calloc(idp->len,
646 sizeof(**r->res_argv));
647 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
648 r->res_argv_lens[r->res_argc] = idp->len;
649 r->res_argv_types[r->res_argc] = r->res_argc + 3;
651 silc_buffer_free(idp);
653 entry->resolve_cmd_ident = r->ident;
654 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
655 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
660 /* Do the resolving */
661 for (i = 0; i < resolve_count; i++) {
666 /* Send WHOIS request. We send WHOIS since we're doing the requesting
667 now anyway so make it a good one. */
668 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
669 r->res_argc, r->res_argv,
673 silc_server_packet_send(server, r->router->connection,
674 SILC_PACKET_COMMAND, cmd->packet->flags,
675 res_cmd->data, res_cmd->len, FALSE);
677 /* Reprocess this packet after received reply */
678 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
680 silc_server_command_whois,
681 silc_server_command_dup(cmd));
684 silc_buffer_free(res_cmd);
685 for (k = 0; k < r->res_argc; k++)
686 silc_free(r->res_argv[k]);
687 silc_free(r->res_argv);
688 silc_free(r->res_argv_lens);
689 silc_free(r->res_argv_types);
698 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
699 SilcClientEntry *clients,
700 SilcUInt32 clients_count,
702 const char *nickname,
703 SilcClientID **client_ids)
705 SilcServer server = cmd->server;
707 int i, k, len, valid_count;
708 SilcBuffer packet, idp, channels, umode_list = NULL;
709 SilcClientEntry entry;
711 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
712 char nh[256], uh[256];
713 unsigned char idle[4], mode[4];
714 unsigned char *fingerprint;
715 SilcSocketConnection hsock;
717 /* Process only valid clients and ignore those that are not registered. */
719 for (i = 0; i < clients_count; i++) {
720 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
727 /* No valid clients found, send error reply */
729 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
730 SILC_STATUS_ERR_NO_SUCH_NICK,
731 3, nickname, strlen(nickname));
732 } else if (client_ids && client_ids[0]) {
733 SilcBuffer idp = silc_id_payload_encode(client_ids[0], SILC_ID_CLIENT);
734 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
735 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
736 2, idp->data, idp->len);
737 silc_buffer_free(idp);
742 /* Start processing found clients. */
744 status = SILC_STATUS_LIST_START;
746 status = SILC_STATUS_OK;
748 for (i = 0, k = 0; i < clients_count; i++) {
754 status = SILC_STATUS_LIST_ITEM;
755 if (valid_count > 1 && k == valid_count - 1)
756 status = SILC_STATUS_LIST_END;
757 if (count && k - 1 == count)
758 status = SILC_STATUS_LIST_END;
760 /* Send WHOIS reply */
761 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
762 tmp = silc_argument_get_first_arg(cmd->args, NULL);
764 memset(uh, 0, sizeof(uh));
765 memset(nh, 0, sizeof(nh));
766 memset(idle, 0, sizeof(idle));
768 strncat(nh, entry->nickname, strlen(entry->nickname));
769 if (!strchr(entry->nickname, '@')) {
771 if (entry->servername) {
772 strncat(nh, entry->servername, strlen(entry->servername));
774 len = entry->router ? strlen(entry->router->server_name) :
775 strlen(server->server_name);
776 strncat(nh, entry->router ? entry->router->server_name :
777 server->server_name, len);
781 strncat(uh, entry->username, strlen(entry->username));
782 if (!strchr(entry->username, '@') && entry->connection) {
784 hsock = (SilcSocketConnection)entry->connection;
785 len = strlen(hsock->hostname);
786 strncat(uh, hsock->hostname, len);
789 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
790 channels = silc_server_get_client_channel_list(server, entry, FALSE,
793 channels = silc_server_get_client_channel_list(server, entry, TRUE,
796 if (entry->data.fingerprint[0] != 0 && entry->data.fingerprint[1] != 0)
797 fingerprint = entry->data.fingerprint;
801 SILC_PUT32_MSB(entry->mode, mode);
803 if (entry->connection) {
804 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
808 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
810 2, idp->data, idp->len,
814 strlen(entry->userinfo),
815 6, channels ? channels->data : NULL,
816 channels ? channels->len : 0,
820 fingerprint ? 20 : 0,
821 10, umode_list ? umode_list->data :
822 NULL, umode_list ? umode_list->len :
825 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
826 0, packet->data, packet->len, FALSE);
828 silc_buffer_free(packet);
829 silc_buffer_free(idp);
831 silc_buffer_free(channels);
833 silc_buffer_free(umode_list);
842 silc_server_command_whois_send_router(SilcServerCommandContext cmd)
844 SilcServer server = cmd->server;
846 SilcUInt16 old_ident;
848 old_ident = silc_command_get_ident(cmd->payload);
849 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
850 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
852 /* Send WHOIS command to our router */
853 silc_server_packet_send(server, (SilcSocketConnection)
854 server->router->connection,
855 SILC_PACKET_COMMAND, cmd->packet->flags,
856 tmpbuf->data, tmpbuf->len, TRUE);
858 /* Reprocess this packet after received reply from router */
859 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
860 silc_command_get_ident(cmd->payload),
861 silc_server_command_whois,
862 silc_server_command_dup(cmd));
864 silc_command_set_ident(cmd->payload, old_ident);
865 silc_buffer_free(tmpbuf);
869 silc_server_command_whois_process(SilcServerCommandContext cmd)
871 SilcServer server = cmd->server;
872 char *nick = NULL, *server_name = NULL;
874 SilcClientEntry *clients = NULL, entry;
875 SilcClientID **client_id = NULL;
876 SilcUInt32 client_id_count = 0, clients_count = 0;
878 bool check_global = FALSE;
880 /* Parse the whois request */
881 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
882 &nick, &server_name, &count,
886 /* Send the WHOIS request to the router only if it included nickname.
887 Since nicknames can be expanded into many clients we need to send it
888 to router. If the WHOIS included only client ID's we will check them
889 first locally since we just might have them. */
890 if (nick && !client_id_count && cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
891 server->server_type == SILC_SERVER && !cmd->pending &&
892 !server->standalone) {
893 silc_server_command_whois_send_router(cmd);
898 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
900 else if (server->server_type != SILC_SERVER)
903 /* Get all clients matching that ID or nickname from local list */
904 if (client_id_count) {
905 /* Check all Client ID's received in the command packet */
906 for (i = 0; i < client_id_count; i++) {
907 entry = silc_idlist_find_client_by_id(server->local_list,
908 client_id[i], TRUE, NULL);
909 if (!entry && check_global)
910 entry = silc_idlist_find_client_by_id(server->global_list,
911 client_id[i], TRUE, NULL);
913 clients = silc_realloc(clients, sizeof(*clients) *
914 (clients_count + 1));
915 clients[clients_count++] = entry;
917 /* If we are normal server and did not send the request first to router
918 do it now, since we do not have the Client ID information. */
919 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
920 server->server_type == SILC_SERVER && !cmd->pending &&
921 !server->standalone) {
922 silc_server_command_whois_send_router(cmd);
929 /* Find by nickname */
930 if (!silc_idlist_get_clients_by_hash(server->local_list,
931 nick, server->md5hash,
932 &clients, &clients_count))
933 silc_idlist_get_clients_by_nickname(server->local_list,
935 &clients, &clients_count);
937 if (!silc_idlist_get_clients_by_hash(server->global_list,
938 nick, server->md5hash,
939 &clients, &clients_count))
940 silc_idlist_get_clients_by_nickname(server->global_list,
942 &clients, &clients_count);
947 /* If we are normal server and did not send the request first to router
948 do it now, since we do not have the information. */
949 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
950 server->server_type == SILC_SERVER && !cmd->pending &&
951 !server->standalone) {
952 silc_server_command_whois_send_router(cmd);
957 /* Such client(s) really does not exist in the SILC network. */
958 if (!client_id_count) {
959 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
960 SILC_STATUS_ERR_NO_SUCH_NICK,
961 3, nick, strlen(nick));
963 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
964 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
965 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
966 2, idp->data, idp->len);
967 silc_buffer_free(idp);
972 /* Router always finds the client entry if it exists in the SILC network.
973 However, it might be incomplete entry and does not include all the
974 mandatory fields that WHOIS command reply requires. Check for these and
975 make query from the server who owns the client if some fields are
977 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
982 /* Send the command reply */
983 silc_server_command_whois_send_reply(cmd, clients, clients_count,
984 count, nick, client_id);
987 if (client_id_count) {
988 for (i = 0; i < client_id_count; i++)
989 silc_free(client_id[i]);
990 silc_free(client_id);
994 silc_free(server_name);
999 /* Server side of command WHOIS. Processes user's query and sends found
1000 results as command replies back to the client. */
1002 SILC_SERVER_CMD_FUNC(whois)
1004 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1007 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 3328);
1009 ret = silc_server_command_whois_process(cmd);
1010 silc_server_command_free(cmd);
1013 /******************************************************************************
1017 ******************************************************************************/
1020 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
1028 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1030 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
1031 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1035 /* Get the nickname@server string and parse it. */
1036 silc_parse_userfqdn(tmp, nickname, server_name);
1038 /* Get the max count of reply messages allowed */
1039 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1041 SILC_GET32_MSB(*count, tmp);
1050 silc_server_command_whowas_check(SilcServerCommandContext cmd,
1051 SilcClientEntry *clients,
1052 SilcUInt32 clients_count)
1054 SilcServer server = cmd->server;
1056 SilcClientEntry entry;
1058 for (i = 0; i < clients_count; i++) {
1061 if (!entry->nickname || !entry->username) {
1063 SilcUInt16 old_ident;
1068 old_ident = silc_command_get_ident(cmd->payload);
1069 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1070 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1072 /* Send WHOWAS command */
1073 silc_server_packet_send(server, entry->router->connection,
1074 SILC_PACKET_COMMAND, cmd->packet->flags,
1075 tmpbuf->data, tmpbuf->len, TRUE);
1077 /* Reprocess this packet after received reply */
1078 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1079 silc_command_get_ident(cmd->payload),
1080 silc_server_command_whowas,
1081 silc_server_command_dup(cmd));
1082 cmd->pending = TRUE;
1083 silc_command_set_ident(cmd->payload, old_ident);
1085 silc_buffer_free(tmpbuf);
1094 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1095 SilcClientEntry *clients,
1096 SilcUInt32 clients_count)
1098 SilcServer server = cmd->server;
1100 int i, k, count = 0, len;
1101 SilcBuffer packet, idp;
1102 SilcClientEntry entry = NULL;
1104 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1105 char nh[256], uh[256];
1108 status = SILC_STATUS_OK;
1110 /* Process only entries that are not registered anymore. */
1112 for (i = 0; i < clients_count; i++) {
1113 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1120 /* No valid entries found at all, just send error */
1123 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1125 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1126 SILC_STATUS_ERR_NO_SUCH_NICK,
1127 3, tmp, strlen(tmp));
1131 if (valid_count > 1)
1132 status = SILC_STATUS_LIST_START;
1134 for (i = 0, k = 0; i < clients_count; i++) {
1140 status = SILC_STATUS_LIST_ITEM;
1141 if (valid_count > 1 && k == valid_count - 1)
1142 status = SILC_STATUS_LIST_END;
1143 if (count && k - 1 == count)
1144 status = SILC_STATUS_LIST_END;
1145 if (count && k - 1 > count)
1148 /* Send WHOWAS reply */
1149 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1150 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1151 memset(uh, 0, sizeof(uh));
1152 memset(nh, 0, sizeof(nh));
1154 strncat(nh, entry->nickname, strlen(entry->nickname));
1155 if (!strchr(entry->nickname, '@')) {
1156 strncat(nh, "@", 1);
1157 if (entry->servername) {
1158 strncat(nh, entry->servername, strlen(entry->servername));
1160 len = entry->router ? strlen(entry->router->server_name) :
1161 strlen(server->server_name);
1162 strncat(nh, entry->router ? entry->router->server_name :
1163 server->server_name, len);
1167 strncat(uh, entry->username, strlen(entry->username));
1168 if (!strchr(entry->username, '@')) {
1169 strncat(uh, "@", 1);
1170 strcat(uh, "*private*");
1174 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1175 status, 0, ident, 4,
1176 2, idp->data, idp->len,
1181 strlen(entry->userinfo) : 0);
1182 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1183 0, packet->data, packet->len, FALSE);
1185 silc_buffer_free(packet);
1186 silc_buffer_free(idp);
1193 silc_server_command_whowas_process(SilcServerCommandContext cmd)
1195 SilcServer server = cmd->server;
1196 char *nick = NULL, *server_name = NULL;
1198 SilcClientEntry *clients = NULL;
1199 SilcUInt32 clients_count = 0;
1201 bool check_global = FALSE;
1203 /* Protocol dictates that we must always send the received WHOWAS request
1204 to our router if we are normal server, so let's do it now unless we
1205 are standalone. We will not send any replies to the client until we
1206 have received reply from the router. */
1207 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1208 server->server_type == SILC_SERVER && !cmd->pending &&
1209 !server->standalone) {
1211 SilcUInt16 old_ident;
1213 old_ident = silc_command_get_ident(cmd->payload);
1214 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1215 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1217 /* Send WHOWAS command to our router */
1218 silc_server_packet_send(server, (SilcSocketConnection)
1219 server->router->connection,
1220 SILC_PACKET_COMMAND, cmd->packet->flags,
1221 tmpbuf->data, tmpbuf->len, TRUE);
1223 /* Reprocess this packet after received reply from router */
1224 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1225 silc_command_get_ident(cmd->payload),
1226 silc_server_command_whowas,
1227 silc_server_command_dup(cmd));
1228 cmd->pending = TRUE;
1229 silc_command_set_ident(cmd->payload, old_ident);
1231 silc_buffer_free(tmpbuf);
1236 /* We are ready to process the command request. Let's search for the
1237 requested client and send reply to the requesting client. */
1239 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1240 check_global = TRUE;
1241 else if (server->server_type != SILC_SERVER)
1242 check_global = TRUE;
1244 /* Parse the whowas request */
1245 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1248 /* Get all clients matching that nickname from local list */
1249 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1251 &clients, &clients_count))
1252 silc_idlist_get_clients_by_hash(server->local_list,
1253 nick, server->md5hash,
1254 &clients, &clients_count);
1256 /* Check global list as well */
1258 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1260 &clients, &clients_count))
1261 silc_idlist_get_clients_by_hash(server->global_list,
1262 nick, server->md5hash,
1263 &clients, &clients_count);
1267 /* Such a client really does not exist in the SILC network. */
1268 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1269 SILC_STATUS_ERR_NO_SUCH_NICK,
1270 3, nick, strlen(nick));
1274 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1279 /* Send the command reply to the client */
1280 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1285 silc_free(server_name);
1289 /* Server side of command WHOWAS. */
1291 SILC_SERVER_CMD_FUNC(whowas)
1293 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1296 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1298 ret = silc_server_command_whowas_process(cmd);
1299 silc_server_command_free(cmd);
1302 /******************************************************************************
1306 ******************************************************************************/
1309 silc_server_command_identify_send_router(SilcServerCommandContext cmd)
1311 SilcServer server = cmd->server;
1313 SilcUInt16 old_ident;
1315 old_ident = silc_command_get_ident(cmd->payload);
1316 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1317 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1319 /* Send IDENTIFY command to our router */
1320 silc_server_packet_send(server, (SilcSocketConnection)
1321 server->router->connection,
1322 SILC_PACKET_COMMAND, cmd->packet->flags,
1323 tmpbuf->data, tmpbuf->len, TRUE);
1325 /* Reprocess this packet after received reply from router */
1326 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1327 silc_command_get_ident(cmd->payload),
1328 silc_server_command_identify,
1329 silc_server_command_dup(cmd));
1330 cmd->pending = TRUE;
1331 silc_command_set_ident(cmd->payload, old_ident);
1332 silc_buffer_free(tmpbuf);
1336 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1337 SilcClientEntry **clients,
1338 SilcUInt32 *clients_count,
1339 SilcServerEntry **servers,
1340 SilcUInt32 *servers_count,
1341 SilcChannelEntry **channels,
1342 SilcUInt32 *channels_count,
1345 SilcServer server = cmd->server;
1348 SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
1350 bool check_global = FALSE;
1355 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1356 check_global = TRUE;
1357 else if (server->server_type != SILC_SERVER)
1358 check_global = TRUE;
1360 /* If ID Payload is in the command it must be used instead of names */
1361 tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1363 /* No ID, get the names. */
1365 /* If we are normal server and have not resolved information from
1366 router yet, do so now. */
1367 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1368 server->server_type == SILC_SERVER && !cmd->pending &&
1369 !server->standalone) {
1370 silc_server_command_identify_send_router(cmd);
1374 /* Try to get nickname@server. */
1375 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1378 char *nick_server = NULL;
1380 silc_parse_userfqdn(tmp, &nick, &nick_server);
1382 if (!silc_idlist_get_clients_by_hash(server->local_list,
1383 nick, server->md5hash,
1384 clients, clients_count))
1385 silc_idlist_get_clients_by_nickname(server->local_list,
1387 clients, clients_count);
1389 if (!silc_idlist_get_clients_by_hash(server->global_list,
1390 nick, server->md5hash,
1391 clients, clients_count))
1392 silc_idlist_get_clients_by_nickname(server->global_list,
1394 clients, clients_count);
1398 silc_free(nick_server);
1401 /* the nickname does not exist, send error reply */
1402 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1403 SILC_STATUS_ERR_NO_SUCH_NICK,
1404 3, tmp, strlen(tmp));
1409 /* Try to get server name */
1410 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1412 entry = silc_idlist_find_server_by_name(server->local_list,
1414 if (!entry && check_global)
1415 entry = silc_idlist_find_server_by_name(server->global_list,
1418 *servers = silc_realloc(*servers, sizeof(**servers) *
1419 (*servers_count + 1));
1420 (*servers)[(*servers_count)++] = entry;
1424 /* the server does not exist, send error reply */
1425 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1426 SILC_STATUS_ERR_NO_SUCH_SERVER,
1427 3, tmp, strlen(tmp));
1432 /* Try to get channel name */
1433 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1435 entry = silc_idlist_find_channel_by_name(server->local_list,
1437 if (!entry && check_global)
1438 entry = silc_idlist_find_channel_by_name(server->global_list,
1441 *channels = silc_realloc(*channels, sizeof(**channels) *
1442 (*channels_count + 1));
1443 (*channels)[(*channels_count)++] = entry;
1447 /* The channel does not exist, send error reply */
1448 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1449 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1450 3, tmp, strlen(tmp));
1455 if (!(*clients) && !(*servers) && !(*channels)) {
1456 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1457 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1461 /* Command includes ID, we must use that. Also check whether the command
1462 has more than one ID set - take them all. */
1464 /* Take all ID's from the command packet */
1465 for (i = 0; i < argc; i++) {
1468 tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
1472 idp = silc_id_payload_parse(tmp, len);
1474 silc_free(*clients);
1475 silc_free(*servers);
1476 silc_free(*channels);
1477 silc_server_command_send_status_reply(
1478 cmd, SILC_COMMAND_IDENTIFY,
1479 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1483 id = silc_id_payload_get_id(idp);
1485 switch (silc_id_payload_get_type(idp)) {
1487 case SILC_ID_CLIENT:
1488 entry = (void *)silc_idlist_find_client_by_id(server->local_list,
1490 if (!entry && check_global)
1491 entry = (void *)silc_idlist_find_client_by_id(server->global_list,
1494 *clients = silc_realloc(*clients, sizeof(**clients) *
1495 (*clients_count + 1));
1496 (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
1498 /* If we are normal server and have not resolved information from
1499 router yet, do so now. */
1500 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1501 server->server_type == SILC_SERVER && !cmd->pending &&
1502 !server->standalone) {
1503 silc_server_command_identify_send_router(cmd);
1504 silc_free(*clients);
1505 silc_free(*servers);
1506 silc_free(*channels);
1509 silc_server_command_send_status_data(
1510 cmd, SILC_COMMAND_IDENTIFY,
1511 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1519 case SILC_ID_SERVER:
1520 entry = (void *)silc_idlist_find_server_by_id(server->local_list,
1522 if (!entry && check_global)
1523 entry = (void *)silc_idlist_find_server_by_id(server->global_list,
1526 *servers = silc_realloc(*servers, sizeof(**servers) *
1527 (*servers_count + 1));
1528 (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
1530 /* If we are normal server and have not resolved information from
1531 router yet, do so now. */
1532 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1533 server->server_type == SILC_SERVER && !cmd->pending &&
1534 !server->standalone) {
1535 silc_server_command_identify_send_router(cmd);
1536 silc_free(*clients);
1537 silc_free(*servers);
1538 silc_free(*channels);
1541 silc_server_command_send_status_data(
1542 cmd, SILC_COMMAND_IDENTIFY,
1543 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
1550 case SILC_ID_CHANNEL:
1551 entry = (void *)silc_idlist_find_channel_by_id(server->local_list,
1553 if (!entry && check_global)
1554 entry = (void *)silc_idlist_find_channel_by_id(server->global_list,
1557 *channels = silc_realloc(*channels, sizeof(**channels) *
1558 (*channels_count + 1));
1559 (*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
1561 /* If we are normal server and have not resolved information from
1562 router yet, do so now. */
1563 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1564 server->server_type == SILC_SERVER && !cmd->pending &&
1565 !server->standalone) {
1566 silc_server_command_identify_send_router(cmd);
1567 silc_free(*clients);
1568 silc_free(*servers);
1569 silc_free(*channels);
1572 silc_server_command_send_status_data(
1573 cmd, SILC_COMMAND_IDENTIFY,
1574 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
1587 silc_free(*clients);
1588 silc_free(*servers);
1589 silc_free(*channels);
1593 /* Get the max count of reply messages allowed */
1594 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1596 SILC_GET32_MSB(*count, tmp);
1604 /* Checks that all mandatory fields in client entry are present. If not
1605 then send WHOIS request to the server who owns the client. We use
1606 WHOIS because we want to get as much information as possible at once. */
1609 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1610 SilcClientEntry *clients,
1611 SilcUInt32 clients_count)
1613 SilcServer server = cmd->server;
1614 SilcClientEntry entry;
1615 SilcServerResolveContext resolve = NULL, r = NULL;
1616 SilcUInt32 resolve_count = 0;
1620 for (i = 0; i < clients_count; i++) {
1625 if (entry->nickname ||
1626 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1630 /* If we are normal server, and we've not resolved this client from
1631 router and it is global client, we'll check whether it is on some
1632 channel. If not then we cannot be sure about its validity, and
1633 we'll resolve it from router. */
1634 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
1635 entry->connection || silc_hash_table_count(entry->channels))
1639 /* We need to resolve this entry since it is not complete */
1641 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1642 /* The entry is being resolved (and we are not the resolver) so attach
1643 to the command reply and we're done with this one. */
1644 silc_server_command_pending(server, SILC_COMMAND_NONE,
1645 entry->resolve_cmd_ident,
1646 silc_server_command_identify,
1647 silc_server_command_dup(cmd));
1650 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1651 /* We've resolved this and it still is not ready. We'll return
1652 and are that this will be handled again after it is resolved. */
1653 for (i = 0; i < resolve_count; i++) {
1654 for (k = 0; k < r->res_argc; k++)
1655 silc_free(r->res_argv[k]);
1656 silc_free(r->res_argv);
1657 silc_free(r->res_argv_lens);
1658 silc_free(r->res_argv_types);
1663 /* We'll resolve this client */
1667 for (k = 0; k < resolve_count; k++) {
1668 if (resolve[k].router == entry->router) {
1675 resolve = silc_realloc(resolve, sizeof(*resolve) *
1676 (resolve_count + 1));
1677 r = &resolve[resolve_count];
1678 memset(r, 0, sizeof(*r));
1679 r->router = entry->router;
1680 r->ident = ++server->cmd_ident;
1684 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1686 r->res_argv_lens = silc_realloc(r->res_argv_lens,
1687 sizeof(*r->res_argv_lens) *
1689 r->res_argv_types = silc_realloc(r->res_argv_types,
1690 sizeof(*r->res_argv_types) *
1692 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1693 r->res_argv[r->res_argc] = silc_calloc(idp->len,
1694 sizeof(**r->res_argv));
1695 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1696 r->res_argv_lens[r->res_argc] = idp->len;
1697 r->res_argv_types[r->res_argc] = r->res_argc + 3;
1699 silc_buffer_free(idp);
1701 entry->resolve_cmd_ident = r->ident;
1702 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1703 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1708 /* Do the resolving */
1709 for (i = 0; i < resolve_count; i++) {
1714 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1715 now anyway so make it a good one. */
1716 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1717 r->res_argc, r->res_argv,
1721 silc_server_packet_send(server, r->router->connection,
1722 SILC_PACKET_COMMAND, cmd->packet->flags,
1723 res_cmd->data, res_cmd->len, FALSE);
1725 /* Reprocess this packet after received reply */
1726 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1728 silc_server_command_identify,
1729 silc_server_command_dup(cmd));
1730 cmd->pending = TRUE;
1732 silc_buffer_free(res_cmd);
1733 for (k = 0; k < r->res_argc; k++)
1734 silc_free(r->res_argv[k]);
1735 silc_free(r->res_argv);
1736 silc_free(r->res_argv_lens);
1737 silc_free(r->res_argv_types);
1746 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1747 SilcClientEntry *clients,
1748 SilcUInt32 clients_count,
1749 SilcServerEntry *servers,
1750 SilcUInt32 servers_count,
1751 SilcChannelEntry *channels,
1752 SilcUInt32 channels_count,
1755 SilcServer server = cmd->server;
1756 int i, k, len, valid_count;
1757 SilcBuffer packet, idp;
1759 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1760 char nh[256], uh[256];
1761 SilcSocketConnection hsock;
1763 status = SILC_STATUS_OK;
1766 SilcClientEntry entry;
1768 /* Process only valid entries. */
1770 for (i = 0; i < clients_count; i++) {
1771 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1778 /* No valid entries found at all, just send error */
1781 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1783 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1784 SILC_STATUS_ERR_NO_SUCH_NICK,
1785 3, tmp, strlen(tmp));
1787 tmp = silc_argument_get_arg_type(cmd->args, 5, (SilcUInt32 *)&len);
1788 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1789 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1795 /* Process all valid client entries and send command replies */
1797 if (valid_count > 1)
1798 status = SILC_STATUS_LIST_START;
1800 for (i = 0, k = 0; i < clients_count; i++) {
1806 status = SILC_STATUS_LIST_ITEM;
1807 if (valid_count > 1 && k == valid_count - 1
1808 && !servers_count && !channels_count)
1809 status = SILC_STATUS_LIST_END;
1810 if (count && k - 1 == count)
1811 status = SILC_STATUS_LIST_END;
1812 if (count && k - 1 > count)
1815 /* Send IDENTIFY reply */
1817 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1818 memset(uh, 0, sizeof(uh));
1819 memset(nh, 0, sizeof(nh));
1820 strncat(nh, entry->nickname, strlen(entry->nickname));
1821 if (!strchr(entry->nickname, '@')) {
1822 strncat(nh, "@", 1);
1823 if (entry->servername) {
1824 strncat(nh, entry->servername, strlen(entry->servername));
1826 len = entry->router ? strlen(entry->router->server_name) :
1827 strlen(server->server_name);
1828 strncat(nh, entry->router ? entry->router->server_name :
1829 server->server_name, len);
1833 if (!entry->username) {
1834 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1835 status, 0, ident, 2,
1836 2, idp->data, idp->len,
1839 strncat(uh, entry->username, strlen(entry->username));
1840 if (!strchr(entry->username, '@') && entry->connection) {
1841 strncat(uh, "@", 1);
1842 hsock = (SilcSocketConnection)entry->connection;
1843 len = strlen(hsock->hostname);
1844 strncat(uh, hsock->hostname, len);
1847 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1848 status, 0, ident, 3,
1849 2, idp->data, idp->len,
1854 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1855 0, packet->data, packet->len, FALSE);
1857 silc_buffer_free(packet);
1858 silc_buffer_free(idp);
1865 SilcServerEntry entry;
1867 if (status == SILC_STATUS_OK && servers_count > 1)
1868 status = SILC_STATUS_LIST_START;
1870 for (i = 0, k = 0; i < servers_count; i++) {
1874 status = SILC_STATUS_LIST_ITEM;
1875 if (servers_count > 1 && k == servers_count - 1 && !channels_count)
1876 status = SILC_STATUS_LIST_END;
1877 if (count && k - 1 == count)
1878 status = SILC_STATUS_LIST_END;
1879 if (count && k - 1 > count)
1882 /* Send IDENTIFY reply */
1883 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1885 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1886 status, 0, ident, 2,
1887 2, idp->data, idp->len,
1888 3, entry->server_name,
1889 entry->server_name ?
1890 strlen(entry->server_name) : 0);
1891 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1892 0, packet->data, packet->len, FALSE);
1894 silc_buffer_free(packet);
1895 silc_buffer_free(idp);
1902 SilcChannelEntry entry;
1904 if (status == SILC_STATUS_OK && channels_count > 1)
1905 status = SILC_STATUS_LIST_START;
1907 for (i = 0, k = 0; i < channels_count; i++) {
1908 entry = channels[i];
1911 status = SILC_STATUS_LIST_ITEM;
1912 if (channels_count > 1 && k == channels_count - 1)
1913 status = SILC_STATUS_LIST_END;
1914 if (count && k - 1 == count)
1915 status = SILC_STATUS_LIST_END;
1916 if (count && k - 1 > count)
1919 /* Send IDENTIFY reply */
1920 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1922 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1923 status, 0, ident, 2,
1924 2, idp->data, idp->len,
1925 3, entry->channel_name,
1926 entry->channel_name ?
1927 strlen(entry->channel_name): 0);
1928 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1929 0, packet->data, packet->len, FALSE);
1931 silc_buffer_free(packet);
1932 silc_buffer_free(idp);
1940 silc_server_command_identify_process(SilcServerCommandContext cmd)
1942 SilcUInt32 count = 0;
1944 SilcClientEntry *clients = NULL;
1945 SilcServerEntry *servers = NULL;
1946 SilcChannelEntry *channels = NULL;
1947 SilcUInt32 clients_count = 0, servers_count = 0, channels_count = 0;
1949 /* Parse the IDENTIFY request */
1950 ret = silc_server_command_identify_parse(cmd,
1951 &clients, &clients_count,
1952 &servers, &servers_count,
1953 &channels, &channels_count,
1959 /* Check that all mandatory fields are present and request those data
1960 from the server who owns the client if necessary. */
1961 if (clients && !silc_server_command_identify_check_client(cmd, clients,
1967 /* Send the command reply to the client */
1968 silc_server_command_identify_send_reply(cmd,
1969 clients, clients_count,
1970 servers, servers_count,
1971 channels, channels_count,
1977 silc_free(channels);
1981 SILC_SERVER_CMD_FUNC(identify)
1983 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1986 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1988 ret = silc_server_command_identify_process(cmd);
1989 silc_server_command_free(cmd);
1992 /* Server side of command NICK. Sets nickname for user. Setting
1993 nickname causes generation of a new client ID for the client. The
1994 new client ID is sent to the client after changing the nickname. */
1996 SILC_SERVER_CMD_FUNC(nick)
1998 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1999 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2000 SilcServer server = cmd->server;
2001 SilcBuffer packet, nidp, oidp = NULL;
2002 SilcClientID *new_id;
2003 SilcUInt32 nick_len;
2005 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2008 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2011 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
2013 /* Check nickname */
2014 nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
2017 if (silc_server_name_bad_chars(nick, nick_len) == TRUE) {
2018 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2019 SILC_STATUS_ERR_BAD_NICKNAME);
2023 /* Check for same nickname */
2024 if (!strcmp(client->nickname, nick)) {
2025 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2029 /* Create new Client ID */
2030 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
2032 cmd->server->md5hash, nick,
2036 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2037 SILC_STATUS_ERR_BAD_NICKNAME);
2040 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2043 /* Send notify about nickname change to our router. We send the new
2044 ID and ask to replace it with the old one. If we are router the
2045 packet is broadcasted. Send NICK_CHANGE notify. */
2046 if (!server->standalone)
2047 silc_server_send_notify_nick_change(server, server->router->connection,
2048 server->server_type == SILC_SERVER ?
2049 FALSE : TRUE, client->id,
2052 /* Check if anyone is watching the old nickname */
2053 if (server->server_type == SILC_ROUTER)
2054 silc_server_check_watcher_list(server, client, nick,
2055 SILC_NOTIFY_TYPE_NICK_CHANGE);
2057 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2059 /* Remove old cache entry */
2060 silc_idcache_del_by_context(server->local_list->clients, client);
2062 silc_free(client->id);
2063 client->id = new_id;
2065 silc_free(client->nickname);
2066 client->nickname = strdup(nick);
2068 /* Update client cache */
2069 silc_idcache_add(server->local_list->clients, client->nickname,
2070 client->id, (void *)client, 0, NULL);
2072 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2074 /* Send NICK_CHANGE notify to the client's channels */
2075 silc_server_send_notify_on_channels(server, NULL, client,
2076 SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
2077 oidp->data, oidp->len,
2078 nidp->data, nidp->len,
2080 strlen(client->nickname));
2082 /* Check if anyone is watching the new nickname */
2083 if (server->server_type == SILC_ROUTER)
2084 silc_server_check_watcher_list(server, client, NULL,
2085 SILC_NOTIFY_TYPE_NICK_CHANGE);
2088 /* Send the new Client ID as reply command back to client */
2089 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
2090 SILC_STATUS_OK, 0, ident, 2,
2091 2, nidp->data, nidp->len,
2092 3, nick, strlen(nick));
2093 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2094 0, packet->data, packet->len, FALSE);
2096 silc_buffer_free(packet);
2097 silc_buffer_free(nidp);
2099 silc_buffer_free(oidp);
2102 silc_server_command_free(cmd);
2105 /* Sends the LIST command reply */
2108 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2109 SilcChannelEntry *lch,
2110 SilcUInt32 lch_count,
2111 SilcChannelEntry *gch,
2112 SilcUInt32 gch_count)
2115 SilcBuffer packet, idp;
2116 SilcChannelEntry entry;
2118 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2120 unsigned char usercount[4];
2122 int valid_lcount = 0, valid_rcount = 0;
2124 for (i = 0; i < lch_count; i++) {
2125 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2130 for (i = 0; i < gch_count; i++) {
2131 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2137 status = SILC_STATUS_OK;
2138 if ((lch_count + gch_count) > 1)
2139 status = SILC_STATUS_LIST_START;
2142 for (i = 0, k = 0; i < lch_count; i++) {
2148 status = SILC_STATUS_LIST_ITEM;
2149 if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
2150 status = SILC_STATUS_LIST_END;
2152 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2154 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2155 topic = "*private*";
2156 memset(usercount, 0, sizeof(usercount));
2158 topic = entry->topic;
2159 users = silc_hash_table_count(entry->user_list);
2160 SILC_PUT32_MSB(users, usercount);
2163 /* Send the reply */
2165 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2166 status, 0, ident, 4,
2167 2, idp->data, idp->len,
2168 3, entry->channel_name,
2169 strlen(entry->channel_name),
2170 4, topic, topic ? strlen(topic) : 0,
2172 silc_server_packet_send(cmd->server, cmd->sock,
2173 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2174 packet->len, FALSE);
2175 silc_buffer_free(packet);
2176 silc_buffer_free(idp);
2181 for (i = 0, k = 0; i < gch_count; i++) {
2187 status = SILC_STATUS_LIST_ITEM;
2188 if (valid_rcount > 1 && k == valid_rcount - 1)
2189 status = SILC_STATUS_LIST_END;
2191 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2193 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2194 topic = "*private*";
2195 memset(usercount, 0, sizeof(usercount));
2197 topic = entry->topic;
2198 users = entry->user_count;
2199 SILC_PUT32_MSB(users, usercount);
2202 /* Send the reply */
2204 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2205 status, 0, ident, 4,
2206 2, idp->data, idp->len,
2207 3, entry->channel_name,
2208 strlen(entry->channel_name),
2209 4, topic, topic ? strlen(topic) : 0,
2211 silc_server_packet_send(cmd->server, cmd->sock,
2212 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2213 packet->len, FALSE);
2214 silc_buffer_free(packet);
2215 silc_buffer_free(idp);
2220 /* Server side of LIST command. This lists the channel of the requested
2221 server. Secret channels are not listed. */
2223 SILC_SERVER_CMD_FUNC(list)
2225 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2226 SilcServer server = cmd->server;
2227 SilcChannelID *channel_id = NULL;
2230 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2231 SilcUInt32 lch_count = 0, gch_count = 0;
2233 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2235 /* If we are normal server, send the command to router, since we
2236 want to know all channels in the network. */
2237 if (!cmd->pending && server->server_type == SILC_SERVER &&
2238 !server->standalone) {
2240 SilcUInt16 old_ident;
2242 old_ident = silc_command_get_ident(cmd->payload);
2243 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2244 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2245 silc_server_packet_send(server, server->router->connection,
2246 SILC_PACKET_COMMAND, cmd->packet->flags,
2247 tmpbuf->data, tmpbuf->len, TRUE);
2249 /* Reprocess this packet after received reply from router */
2250 silc_server_command_pending(server, SILC_COMMAND_LIST,
2251 silc_command_get_ident(cmd->payload),
2252 silc_server_command_list,
2253 silc_server_command_dup(cmd));
2254 cmd->pending = TRUE;
2255 silc_command_set_ident(cmd->payload, old_ident);
2256 silc_buffer_free(tmpbuf);
2260 /* Get Channel ID */
2261 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2263 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2265 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2266 SILC_STATUS_ERR_NO_CHANNEL_ID);
2271 /* Get the channels from local list */
2272 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2275 /* Get the channels from global list */
2276 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2279 /* Send the reply */
2280 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2281 gchannels, gch_count);
2283 silc_free(lchannels);
2284 silc_free(gchannels);
2287 silc_server_command_free(cmd);
2290 /* Server side of TOPIC command. Sets topic for channel and/or returns
2291 current topic to client. */
2293 SILC_SERVER_CMD_FUNC(topic)
2295 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2296 SilcServer server = cmd->server;
2297 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2298 SilcChannelID *channel_id;
2299 SilcChannelEntry channel;
2300 SilcChannelClientEntry chl;
2301 SilcBuffer packet, idp;
2303 SilcUInt32 argc, tmp_len;
2304 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2306 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2308 argc = silc_argument_get_arg_num(cmd->args);
2310 /* Get Channel ID */
2311 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2313 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2314 SILC_STATUS_ERR_NO_CHANNEL_ID);
2317 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2319 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2320 SILC_STATUS_ERR_NO_CHANNEL_ID);
2324 /* Check whether the channel exists */
2325 channel = silc_idlist_find_channel_by_id(server->local_list,
2328 channel = silc_idlist_find_channel_by_id(server->global_list,
2331 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2332 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2339 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2341 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2342 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2346 if (strlen(tmp) > 256) {
2347 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2348 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2352 /* See whether the client is on channel and has rights to change topic */
2353 if (!silc_server_client_on_channel(client, channel, &chl)) {
2354 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2355 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2359 if (channel->mode & SILC_CHANNEL_MODE_TOPIC &&
2360 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
2361 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
2362 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2363 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2367 /* Set the topic for channel */
2368 silc_free(channel->topic);
2369 channel->topic = strdup(tmp);
2371 /* Send TOPIC_SET notify type to the network */
2372 if (!server->standalone)
2373 silc_server_send_notify_topic_set(server, server->router->connection,
2374 server->server_type == SILC_ROUTER ?
2375 TRUE : FALSE, channel,
2376 client->id, SILC_ID_CLIENT,
2379 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2381 /* Send notify about topic change to all clients on the channel */
2382 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2383 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2384 idp->data, idp->len,
2385 channel->topic, strlen(channel->topic));
2386 silc_buffer_free(idp);
2389 /* Send the topic to client as reply packet */
2390 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2391 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2392 SILC_STATUS_OK, 0, ident, 2,
2393 2, idp->data, idp->len,
2396 strlen(channel->topic) : 0);
2397 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2398 0, packet->data, packet->len, FALSE);
2400 silc_buffer_free(packet);
2401 silc_buffer_free(idp);
2402 silc_free(channel_id);
2405 silc_server_command_free(cmd);
2408 /* Server side of INVITE command. Invites some client to join some channel.
2409 This command is also used to manage the invite list of the channel. */
2411 SILC_SERVER_CMD_FUNC(invite)
2413 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2414 SilcServer server = cmd->server;
2415 SilcSocketConnection sock = cmd->sock, dest_sock;
2416 SilcChannelClientEntry chl;
2417 SilcClientEntry sender, dest;
2418 SilcClientID *dest_id = NULL;
2419 SilcChannelEntry channel;
2420 SilcChannelID *channel_id = NULL;
2421 SilcIDListData idata;
2422 SilcBuffer idp, idp2, packet;
2423 unsigned char *tmp, *add, *del;
2425 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2427 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2429 /* Get Channel ID */
2430 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2432 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2433 SILC_STATUS_ERR_NO_CHANNEL_ID);
2436 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
2438 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2439 SILC_STATUS_ERR_NO_CHANNEL_ID);
2443 /* Get the channel entry */
2444 channel = silc_idlist_find_channel_by_id(server->local_list,
2447 channel = silc_idlist_find_channel_by_id(server->global_list,
2450 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2451 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2456 /* Check whether the sender of this command is on the channel. */
2457 sender = (SilcClientEntry)sock->user_data;
2458 if (!silc_server_client_on_channel(sender, channel, &chl)) {
2459 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2460 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2464 /* Check whether the channel is invite-only channel. If yes then the
2465 sender of this command must be at least channel operator. */
2466 if (channel->mode & SILC_CHANNEL_MODE_INVITE &&
2467 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
2468 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
2469 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2470 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2474 /* Get destination client ID */
2475 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2480 dest_id = silc_id_payload_parse_id(tmp, len, NULL);
2482 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2483 SILC_STATUS_ERR_NO_CLIENT_ID);
2487 /* Get the client entry */
2488 dest = silc_server_get_client_resolve(server, dest_id, FALSE, &resolve);
2490 if (server->server_type != SILC_SERVER || !resolve) {
2491 silc_server_command_send_status_reply(
2492 cmd, SILC_COMMAND_INVITE,
2493 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2497 /* The client info is being resolved. Reprocess this packet after
2498 receiving the reply to the query. */
2499 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2501 silc_server_command_invite,
2502 silc_server_command_dup(cmd));
2503 cmd->pending = TRUE;
2504 silc_free(channel_id);
2509 /* Check whether the requested client is already on the channel. */
2510 if (silc_server_client_on_channel(dest, channel, NULL)) {
2511 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2512 SILC_STATUS_ERR_USER_ON_CHANNEL);
2516 /* Get route to the client */
2517 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id,
2520 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2521 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2525 memset(invite, 0, sizeof(invite));
2526 strncat(invite, dest->nickname, strlen(dest->nickname));
2527 strncat(invite, "!", 1);
2528 strncat(invite, dest->username, strlen(dest->username));
2529 if (!strchr(dest->username, '@')) {
2530 strncat(invite, "@", 1);
2531 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2534 len = strlen(invite);
2535 if (!channel->invite_list)
2536 channel->invite_list = silc_calloc(len + 2,
2537 sizeof(*channel->invite_list));
2539 channel->invite_list = silc_realloc(channel->invite_list,
2540 sizeof(*channel->invite_list) *
2542 strlen(channel->invite_list) + 2));
2543 strncat(channel->invite_list, invite, len);
2544 strncat(channel->invite_list, ",", 1);
2546 if (!(dest->mode & SILC_UMODE_BLOCK_INVITE)) {
2547 /* Send notify to the client that is invited to the channel */
2548 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2549 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2550 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2552 SILC_NOTIFY_TYPE_INVITE, 3,
2553 idp->data, idp->len,
2554 channel->channel_name,
2555 strlen(channel->channel_name),
2556 idp2->data, idp2->len);
2557 silc_buffer_free(idp);
2558 silc_buffer_free(idp2);
2562 /* Add the client to the invite list of the channel */
2563 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2565 if (!channel->invite_list)
2566 channel->invite_list = silc_calloc(len + 2,
2567 sizeof(*channel->invite_list));
2569 channel->invite_list = silc_realloc(channel->invite_list,
2570 sizeof(*channel->invite_list) *
2572 strlen(channel->invite_list) + 2));
2573 if (add[len - 1] == ',')
2574 add[len - 1] = '\0';
2576 strncat(channel->invite_list, add, len);
2577 strncat(channel->invite_list, ",", 1);
2580 /* Get the invite to be removed and remove it from the list */
2581 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2582 if (del && channel->invite_list) {
2583 char *start, *end, *n;
2585 if (!strncmp(channel->invite_list, del,
2586 strlen(channel->invite_list) - 1)) {
2587 silc_free(channel->invite_list);
2588 channel->invite_list = NULL;
2590 start = strstr(channel->invite_list, del);
2591 if (start && strlen(start) >= len) {
2593 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2594 strncat(n, channel->invite_list, start - channel->invite_list);
2595 strncat(n, end + 1, ((channel->invite_list +
2596 strlen(channel->invite_list)) - end) - 1);
2597 silc_free(channel->invite_list);
2598 channel->invite_list = n;
2603 /* Send notify to the primary router */
2604 if (!server->standalone)
2605 silc_server_send_notify_invite(server, server->router->connection,
2606 server->server_type == SILC_ROUTER ?
2607 TRUE : FALSE, channel,
2608 sender->id, add, del);
2610 /* Send command reply */
2611 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2615 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2616 SILC_STATUS_OK, 0, ident, 2,
2618 3, channel->invite_list,
2619 channel->invite_list ?
2620 strlen(channel->invite_list) : 0);
2623 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2624 SILC_STATUS_OK, 0, ident, 1,
2626 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2627 packet->data, packet->len, FALSE);
2628 silc_buffer_free(packet);
2632 silc_free(channel_id);
2633 silc_server_command_free(cmd);
2638 SilcSocketConnection sock;
2642 /* Quits connection to client. This gets called if client won't
2643 close the connection even when it has issued QUIT command. */
2645 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2647 QuitInternal q = (QuitInternal)context;
2649 /* Free all client specific data, such as client entry and entires
2650 on channels this client may be on. */
2651 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2653 q->sock->user_data = NULL;
2655 /* Close the connection on our side */
2656 silc_server_close_connection(q->server, q->sock);
2658 silc_free(q->signoff);
2662 /* Quits SILC session. This is the normal way to disconnect client. */
2664 SILC_SERVER_CMD_FUNC(quit)
2666 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2667 SilcServer server = cmd->server;
2668 SilcSocketConnection sock = cmd->sock;
2670 unsigned char *tmp = NULL;
2673 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2675 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2679 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2683 q = silc_calloc(1, sizeof(*q));
2686 q->signoff = tmp ? strdup(tmp) : NULL;
2688 /* We quit the connection with little timeout */
2689 silc_schedule_task_add(server->schedule, sock->sock,
2690 silc_server_command_quit_cb, (void *)q,
2691 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2694 silc_server_command_free(cmd);
2697 /* Server side of command KILL. This command is used by router operator
2698 to remove an client from the SILC Network temporarily. */
2700 SILC_SERVER_CMD_FUNC(kill)
2702 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2703 SilcServer server = cmd->server;
2704 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2705 SilcClientEntry remote_client;
2706 SilcClientID *client_id;
2707 unsigned char *tmp, *comment;
2708 SilcUInt32 tmp_len, tmp_len2;
2711 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2713 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2716 /* KILL command works only on router */
2717 if (server->server_type != SILC_ROUTER) {
2718 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2719 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2723 /* Check whether client has the permissions. */
2724 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2725 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2726 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2730 /* Get the client ID */
2731 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2733 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2734 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2737 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2739 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2740 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2744 /* Get the client entry */
2745 remote_client = silc_idlist_find_client_by_id(server->local_list,
2746 client_id, TRUE, NULL);
2748 if (!remote_client) {
2749 remote_client = silc_idlist_find_client_by_id(server->global_list,
2750 client_id, TRUE, NULL);
2752 if (!remote_client) {
2753 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2754 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2760 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2764 /* Send reply to the sender */
2765 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2768 /* Check if anyone is watching this nickname */
2769 if (server->server_type == SILC_ROUTER)
2770 silc_server_check_watcher_list(server, client, NULL,
2771 SILC_NOTIFY_TYPE_KILLED);
2773 /* Now do the killing */
2774 silc_server_kill_client(server, remote_client, comment, client->id,
2778 silc_server_command_free(cmd);
2781 /* Server side of command INFO. This sends information about us to
2782 the client. If client requested specific server we will send the
2783 command to that server. */
2785 SILC_SERVER_CMD_FUNC(info)
2787 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2788 SilcServer server = cmd->server;
2789 SilcBuffer packet, idp;
2792 char *dest_server, *server_info = NULL, *server_name;
2793 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2794 SilcServerEntry entry = NULL;
2795 SilcServerID *server_id = NULL;
2797 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2799 /* Get server name */
2800 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2803 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2805 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2807 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2808 SILC_STATUS_ERR_NO_SERVER_ID);
2814 /* Check whether we have this server cached */
2815 entry = silc_idlist_find_server_by_id(server->local_list,
2816 server_id, TRUE, NULL);
2818 entry = silc_idlist_find_server_by_id(server->global_list,
2819 server_id, TRUE, NULL);
2820 if (!entry && server->server_type != SILC_SERVER) {
2821 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2822 SILC_STATUS_ERR_NO_SUCH_SERVER);
2828 /* Some buggy servers has sent request to router about themselves. */
2829 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2832 if ((!dest_server && !server_id && !entry) || (entry &&
2833 entry == server->id_entry) ||
2834 (dest_server && !cmd->pending &&
2835 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2836 /* Send our reply */
2837 char info_string[256];
2839 memset(info_string, 0, sizeof(info_string));
2840 snprintf(info_string, sizeof(info_string),
2841 "location: %s server: %s admin: %s <%s>",
2842 server->config->server_info->location,
2843 server->config->server_info->server_type,
2844 server->config->server_info->admin,
2845 server->config->server_info->email);
2847 server_info = info_string;
2848 entry = server->id_entry;
2850 /* Check whether we have this server cached */
2851 if (!entry && dest_server) {
2852 entry = silc_idlist_find_server_by_name(server->global_list,
2853 dest_server, TRUE, NULL);
2855 entry = silc_idlist_find_server_by_name(server->local_list,
2856 dest_server, TRUE, NULL);
2860 if (!cmd->pending &&
2861 server->server_type != SILC_SERVER && entry && !entry->server_info) {
2862 /* Send to the server */
2864 SilcUInt16 old_ident;
2866 old_ident = silc_command_get_ident(cmd->payload);
2867 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2868 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2870 silc_server_packet_send(server, entry->connection,
2871 SILC_PACKET_COMMAND, cmd->packet->flags,
2872 tmpbuf->data, tmpbuf->len, TRUE);
2874 /* Reprocess this packet after received reply from router */
2875 silc_server_command_pending(server, SILC_COMMAND_INFO,
2876 silc_command_get_ident(cmd->payload),
2877 silc_server_command_info,
2878 silc_server_command_dup(cmd));
2879 cmd->pending = TRUE;
2880 silc_command_set_ident(cmd->payload, old_ident);
2881 silc_buffer_free(tmpbuf);
2885 if (!entry && !cmd->pending && !server->standalone) {
2886 /* Send to the primary router */
2888 SilcUInt16 old_ident;
2890 old_ident = silc_command_get_ident(cmd->payload);
2891 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2892 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2894 silc_server_packet_send(server, server->router->connection,
2895 SILC_PACKET_COMMAND, cmd->packet->flags,
2896 tmpbuf->data, tmpbuf->len, TRUE);
2898 /* Reprocess this packet after received reply from router */
2899 silc_server_command_pending(server, SILC_COMMAND_INFO,
2900 silc_command_get_ident(cmd->payload),
2901 silc_server_command_info,
2902 silc_server_command_dup(cmd));
2903 cmd->pending = TRUE;
2904 silc_command_set_ident(cmd->payload, old_ident);
2905 silc_buffer_free(tmpbuf);
2910 silc_free(server_id);
2913 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2914 SILC_STATUS_ERR_NO_SUCH_SERVER);
2918 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2920 server_info = entry->server_info;
2921 server_name = entry->server_name;
2923 /* Send the reply */
2924 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2925 SILC_STATUS_OK, 0, ident, 3,
2926 2, idp->data, idp->len,
2928 strlen(server_name),
2931 strlen(server_info) : 0);
2932 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2933 packet->data, packet->len, FALSE);
2935 silc_buffer_free(packet);
2936 silc_buffer_free(idp);
2939 silc_server_command_free(cmd);
2942 /* Server side of command PING. This just replies to the ping. */
2944 SILC_SERVER_CMD_FUNC(ping)
2946 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2947 SilcServer server = cmd->server;
2952 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
2955 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2957 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2958 SILC_STATUS_ERR_NO_SERVER_ID);
2961 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2965 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2966 /* Send our reply */
2967 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2970 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2971 SILC_STATUS_ERR_NO_SUCH_SERVER);
2978 silc_server_command_free(cmd);
2981 /* Server side of command STATS. */
2983 SILC_SERVER_CMD_FUNC(stats)
2985 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2986 SilcServer server = cmd->server;
2987 SilcServerID *server_id;
2990 SilcBuffer packet, stats;
2991 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2994 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1);
2997 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2999 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3000 SILC_STATUS_ERR_NO_SERVER_ID);
3003 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3007 /* The ID must be ours */
3008 if (!SILC_ID_SERVER_COMPARE(server->id, server_id)) {
3009 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3010 SILC_STATUS_ERR_NO_SUCH_SERVER);
3011 silc_free(server_id);
3014 silc_free(server_id);
3016 /* If we are router then just send everything we got. If we are normal
3017 server then we'll send this to our router to get all the latest
3018 statistical information. */
3019 if (!cmd->pending && server->server_type != SILC_ROUTER &&
3020 !server->standalone) {
3021 /* Send request to our router */
3022 SilcBuffer idp = silc_id_payload_encode(server->router->id,
3024 packet = silc_command_payload_encode_va(SILC_COMMAND_STATS,
3025 ++server->cmd_ident, 1,
3026 1, idp->data, idp->len);
3027 silc_server_packet_send(server, server->router->connection,
3028 SILC_PACKET_COMMAND, 0, packet->data,
3029 packet->len, FALSE);
3031 /* Reprocess this packet after received reply from router */
3032 silc_server_command_pending(server, SILC_COMMAND_STATS,
3034 silc_server_command_stats,
3035 silc_server_command_dup(cmd));
3036 cmd->pending = TRUE;
3037 silc_buffer_free(packet);
3038 silc_buffer_free(idp);
3042 /* Send our reply to sender */
3043 uptime = time(NULL) - server->starttime;
3045 stats = silc_buffer_alloc_size(60);
3046 silc_buffer_format(stats,
3047 SILC_STR_UI_INT(server->starttime),
3048 SILC_STR_UI_INT(uptime),
3049 SILC_STR_UI_INT(server->stat.my_clients),
3050 SILC_STR_UI_INT(server->stat.my_channels),
3051 SILC_STR_UI_INT(server->stat.my_server_ops),
3052 SILC_STR_UI_INT(server->stat.my_router_ops),
3053 SILC_STR_UI_INT(server->stat.cell_clients),
3054 SILC_STR_UI_INT(server->stat.cell_channels),
3055 SILC_STR_UI_INT(server->stat.cell_servers),
3056 SILC_STR_UI_INT(server->stat.clients),
3057 SILC_STR_UI_INT(server->stat.channels),
3058 SILC_STR_UI_INT(server->stat.servers),
3059 SILC_STR_UI_INT(server->stat.routers),
3060 SILC_STR_UI_INT(server->stat.server_ops),
3061 SILC_STR_UI_INT(server->stat.router_ops),
3064 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_STATS,
3065 SILC_STATUS_OK, 0, ident, 2,
3067 3, stats->data, stats->len);
3068 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
3069 0, packet->data, packet->len, FALSE);
3070 silc_buffer_free(packet);
3071 silc_buffer_free(stats);
3074 silc_server_command_free(cmd);
3077 /* Internal routine to join channel. The channel sent to this function
3078 has been either created or resolved from ID lists. This joins the sent
3079 client to the channel. */
3081 static void silc_server_command_join_channel(SilcServer server,
3082 SilcServerCommandContext cmd,
3083 SilcChannelEntry channel,
3084 SilcClientID *client_id,
3088 const unsigned char *auth,
3089 SilcUInt32 auth_len)
3091 SilcSocketConnection sock = cmd->sock;
3093 SilcUInt32 tmp_len, user_count;
3094 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
3095 SilcClientEntry client;
3096 SilcChannelClientEntry chl;
3097 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
3098 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3099 char check[512], check2[512];
3100 bool founder = FALSE;
3103 SILC_LOG_DEBUG(("Start"));
3108 /* Get the client entry */
3109 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3110 client = (SilcClientEntry)sock->user_data;
3112 client = silc_server_get_client_resolve(server, client_id, FALSE,
3119 silc_server_command_send_status_reply(
3120 cmd, SILC_COMMAND_JOIN,
3121 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3125 /* The client info is being resolved. Reprocess this packet after
3126 receiving the reply to the query. */
3127 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
3129 silc_server_command_join,
3130 silc_server_command_dup(cmd));
3131 cmd->pending = TRUE;
3135 cmd->pending = FALSE;
3139 * Check founder auth payload if provided. If client can gain founder
3140 * privileges it can override various conditions on joining the channel,
3141 * and can have directly the founder mode set on the channel.
3143 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3144 SilcIDListData idata = (SilcIDListData)client;
3146 if (channel->founder_key && idata->public_key &&
3147 silc_pkcs_public_key_compare(channel->founder_key,
3148 idata->public_key)) {
3149 void *auth_data = (channel->founder_method == SILC_AUTH_PASSWORD ?
3150 (void *)channel->founder_passwd :
3151 (void *)channel->founder_key);
3152 SilcUInt32 auth_data_len =
3153 (channel->founder_method == SILC_AUTH_PASSWORD ?
3154 channel->founder_passwd_len : 0);
3156 /* Check whether the client is to become founder */
3157 if (silc_auth_verify_data(auth, auth_len, channel->founder_method,
3158 auth_data, auth_data_len,
3159 idata->hash, client->id, SILC_ID_CLIENT)) {
3160 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3167 * Check channel modes
3171 memset(check, 0, sizeof(check));
3172 memset(check2, 0, sizeof(check2));
3173 strncat(check, client->nickname, strlen(client->nickname));
3174 strncat(check, "!", 1);
3175 strncat(check, client->username, strlen(client->username));
3176 if (!strchr(client->username, '@')) {
3177 strncat(check, "@", 1);
3178 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3181 strncat(check2, client->nickname, strlen(client->nickname));
3182 if (!strchr(client->nickname, '@')) {
3183 strncat(check2, "@", 1);
3184 strncat(check2, server->server_name, strlen(server->server_name));
3186 strncat(check2, "!", 1);
3187 strncat(check2, client->username, strlen(client->username));
3188 if (!strchr(client->username, '@')) {
3189 strncat(check2, "@", 1);
3190 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3193 /* Check invite list if channel is invite-only channel */
3194 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3195 if (!channel->invite_list ||
3196 (!silc_string_match(channel->invite_list, check) &&
3197 !silc_string_match(channel->invite_list, check2))) {
3198 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3199 SILC_STATUS_ERR_NOT_INVITED);
3204 /* Check ban list if it exists. If the client's nickname, server,
3205 username and/or hostname is in the ban list the access to the
3206 channel is denied. */
3207 if (channel->ban_list) {
3208 if (silc_string_match(channel->ban_list, check) ||
3209 silc_string_match(channel->ban_list, check2)) {
3210 silc_server_command_send_status_reply(
3211 cmd, SILC_COMMAND_JOIN,
3212 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
3217 /* Check user count limit if set. */
3218 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3219 if (silc_hash_table_count(channel->user_list) + 1 >
3220 channel->user_limit) {
3221 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3222 SILC_STATUS_ERR_CHANNEL_IS_FULL);
3228 /* Check the channel passphrase if set. */
3229 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3230 /* Get passphrase */
3231 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3233 passphrase = silc_memdup(tmp, tmp_len);
3235 if (!passphrase || !channel->passphrase ||
3236 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3237 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3238 SILC_STATUS_ERR_BAD_PASSWORD);
3244 * Client is allowed to join to the channel. Make it happen.
3247 /* Check whether the client already is on the channel */
3248 if (silc_server_client_on_channel(client, channel, NULL)) {
3249 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3250 SILC_STATUS_ERR_USER_ON_CHANNEL);
3254 /* Generate new channel key as protocol dictates */
3256 if (!silc_server_create_channel_key(server, channel, 0))
3259 /* Send the channel key. This is broadcasted to the channel but is not
3260 sent to the client who is joining to the channel. */
3261 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3262 silc_server_send_channel_key(server, NULL, channel,
3263 server->server_type == SILC_ROUTER ?
3264 FALSE : !server->standalone);
3267 /* Join the client to the channel by adding it to channel's user list.
3268 Add also the channel to client entry's channels list for fast cross-
3270 chl = silc_calloc(1, sizeof(*chl));
3272 chl->client = client;
3273 chl->channel = channel;
3274 silc_hash_table_add(channel->user_list, client, chl);
3275 silc_hash_table_add(client->channels, channel, chl);
3276 channel->user_count++;
3278 /* Get users on the channel */
3279 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3282 /* Encode Client ID Payload of the original client who wants to join */
3283 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3285 /* Encode command reply packet */
3286 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3287 SILC_PUT32_MSB(channel->mode, mode);
3288 SILC_PUT32_MSB(created, tmp2);
3289 SILC_PUT32_MSB(user_count, tmp3);
3291 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3292 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3293 keyp = silc_channel_key_payload_encode(silc_id_get_len(channel->id,
3296 strlen(channel->channel_key->
3298 channel->channel_key->cipher->name,
3299 channel->key_len / 8, channel->key);
3304 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3305 SILC_STATUS_OK, 0, ident, 13,
3306 2, channel->channel_name,
3307 strlen(channel->channel_name),
3308 3, chidp->data, chidp->len,
3309 4, clidp->data, clidp->len,
3312 7, keyp ? keyp->data : NULL,
3313 keyp ? keyp->len : 0,
3314 8, channel->ban_list,
3316 strlen(channel->ban_list) : 0,
3317 9, channel->invite_list,
3318 channel->invite_list ?
3319 strlen(channel->invite_list) : 0,
3322 strlen(channel->topic) : 0,
3323 11, silc_hmac_get_name(channel->hmac),
3324 strlen(silc_hmac_get_name(channel->
3327 13, user_list->data, user_list->len,
3328 14, mode_list->data,
3331 /* Send command reply */
3332 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3333 reply->data, reply->len, FALSE);
3335 /* Send JOIN notify to locally connected clients on the channel. If
3336 we are normal server then router will send or have sent JOIN notify
3337 already. However since we've added the client already to our channel
3338 we'll ignore it (in packet_receive.c) so we must send it here. If
3339 we are router then this will send it to local clients and local
3341 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3342 SILC_NOTIFY_TYPE_JOIN, 2,
3343 clidp->data, clidp->len,
3344 chidp->data, chidp->len);
3346 if (!cmd->pending) {
3347 /* Send JOIN notify packet to our primary router */
3348 if (!server->standalone)
3349 silc_server_send_notify_join(server, server->router->connection,
3350 server->server_type == SILC_ROUTER ?
3351 TRUE : FALSE, channel, client->id);
3354 /* Distribute the channel key to all backup routers. */
3355 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3356 keyp->data, keyp->len, FALSE, TRUE);
3359 /* If client became founder by providing correct founder auth data
3360 notify the mode change to the channel. */
3362 SILC_PUT32_MSB(chl->mode, mode);
3363 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3364 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3365 clidp->data, clidp->len,
3366 mode, 4, clidp->data, clidp->len);
3368 /* Set CUMODE notify type to network */
3369 if (!server->standalone)
3370 silc_server_send_notify_cumode(server, server->router->connection,
3371 server->server_type == SILC_ROUTER ?
3372 TRUE : FALSE, channel,
3373 chl->mode, client->id, SILC_ID_CLIENT,
3377 silc_buffer_free(reply);
3378 silc_buffer_free(clidp);
3379 silc_buffer_free(chidp);
3380 silc_buffer_free(keyp);
3381 silc_buffer_free(user_list);
3382 silc_buffer_free(mode_list);
3385 silc_free(passphrase);
3388 /* Server side of command JOIN. Joins client into requested channel. If
3389 the channel does not exist it will be created. */
3391 SILC_SERVER_CMD_FUNC(join)
3393 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3394 SilcServer server = cmd->server;
3395 unsigned char *auth;
3396 SilcUInt32 tmp_len, auth_len;
3397 char *tmp, *channel_name = NULL, *cipher, *hmac;
3398 SilcChannelEntry channel;
3399 SilcUInt32 umode = 0;
3400 bool created = FALSE, create_key = TRUE;
3401 SilcClientID *client_id;
3403 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3405 /* Get channel name */
3406 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3408 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3409 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3415 channel_name[255] = '\0';
3417 if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
3418 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3419 SILC_STATUS_ERR_BAD_CHANNEL);
3423 /* Get Client ID of the client who is joining to the channel */
3424 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3426 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3427 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3430 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3432 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3433 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3437 /* Get cipher, hmac name and auth payload */
3438 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3439 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3440 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3442 /* See if the channel exists */
3443 channel = silc_idlist_find_channel_by_name(server->local_list,
3444 channel_name, NULL);
3446 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3447 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3448 client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
3450 if (!channel || channel->disabled) {
3451 /* Channel not found */
3453 /* If we are standalone server we don't have a router, we just create
3454 the channel by ourselves. */
3455 if (server->standalone) {
3456 channel = silc_server_create_new_channel(server, server->id, cipher,
3457 hmac, channel_name, TRUE);
3459 silc_server_command_send_status_reply(
3460 cmd, SILC_COMMAND_JOIN,
3461 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3465 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3471 /* The channel does not exist on our server. If we are normal server
3472 we will send JOIN command to our router which will handle the
3473 joining procedure (either creates the channel if it doesn't exist
3474 or joins the client to it). */
3475 if (server->server_type != SILC_ROUTER) {
3477 SilcUInt16 old_ident;
3479 /* If this is pending command callback then we've resolved
3480 it and it didn't work, return since we've notified the
3481 client already in the command reply callback. */
3485 old_ident = silc_command_get_ident(cmd->payload);
3486 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3487 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3489 /* Send JOIN command to our router */
3490 silc_server_packet_send(server, (SilcSocketConnection)
3491 server->router->connection,
3492 SILC_PACKET_COMMAND, cmd->packet->flags,
3493 tmpbuf->data, tmpbuf->len, TRUE);
3495 /* Reprocess this packet after received reply from router */
3496 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3497 silc_command_get_ident(cmd->payload),
3498 silc_server_command_join,
3499 silc_server_command_dup(cmd));
3500 cmd->pending = TRUE;
3501 silc_command_set_ident(cmd->payload, old_ident);
3502 silc_buffer_free(tmpbuf);
3506 /* We are router and the channel does not seem exist so we will check
3507 our global list as well for the channel. */
3508 channel = silc_idlist_find_channel_by_name(server->global_list,
3509 channel_name, NULL);
3511 /* Channel really does not exist, create it */
3512 channel = silc_server_create_new_channel(server, server->id, cipher,
3513 hmac, channel_name, TRUE);
3515 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3516 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3520 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3528 /* Channel not found */
3530 /* If the command came from router and we are normal server then
3531 something went wrong with the joining as the channel was not found.
3532 We can't do anything else but ignore this. */
3533 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3534 server->server_type != SILC_ROUTER)
3537 /* We are router and the channel does not seem exist so we will check
3538 our global list as well for the channel. */
3539 channel = silc_idlist_find_channel_by_name(server->global_list,
3540 channel_name, NULL);
3542 /* Channel really does not exist, create it */
3543 channel = silc_server_create_new_channel(server, server->id, cipher,
3544 hmac, channel_name, TRUE);
3546 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3547 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3551 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3558 /* Check whether the channel was created by our router */
3559 if (cmd->pending && context2) {
3560 SilcServerCommandReplyContext reply = context2;
3562 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3563 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3564 SILC_GET32_MSB(created, tmp);
3565 if (silc_argument_get_arg_type(reply->args, 7, NULL))
3566 create_key = FALSE; /* Router returned the key already */
3569 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
3570 !silc_hash_table_count(channel->user_list))
3574 /* If the channel does not have global users and is also empty the client
3575 will be the channel founder and operator. */
3576 if (!channel->global_users && !silc_hash_table_count(channel->user_list))
3577 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3579 /* Join to the channel */
3580 silc_server_command_join_channel(server, cmd, channel, client_id,
3581 created, create_key, umode,
3584 silc_free(client_id);
3587 silc_server_command_free(cmd);
3590 /* Server side of command MOTD. Sends server's current "message of the
3591 day" to the client. */
3593 SILC_SERVER_CMD_FUNC(motd)
3595 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3596 SilcServer server = cmd->server;
3597 SilcBuffer packet, idp;
3598 char *motd, *dest_server;
3599 SilcUInt32 motd_len;
3600 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3602 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3604 /* Get server name */
3605 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3607 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3608 SILC_STATUS_ERR_NO_SUCH_SERVER);
3612 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3615 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3617 if (server->config && server->config->server_info &&
3618 server->config->server_info->motd_file) {
3620 motd = silc_file_readfile(server->config->server_info->motd_file, &motd_len);
3625 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3632 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3638 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3639 packet->data, packet->len, FALSE);
3640 silc_buffer_free(packet);
3641 silc_buffer_free(idp);
3643 SilcServerEntry entry;
3645 /* Check whether we have this server cached */
3646 entry = silc_idlist_find_server_by_name(server->global_list,
3647 dest_server, TRUE, NULL);
3649 entry = silc_idlist_find_server_by_name(server->local_list,
3650 dest_server, TRUE, NULL);
3653 if (server->server_type != SILC_SERVER && !cmd->pending &&
3654 entry && !entry->motd) {
3655 /* Send to the server */
3657 SilcUInt16 old_ident;
3659 old_ident = silc_command_get_ident(cmd->payload);
3660 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3661 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3663 silc_server_packet_send(server, entry->connection,
3664 SILC_PACKET_COMMAND, cmd->packet->flags,
3665 tmpbuf->data, tmpbuf->len, TRUE);
3667 /* Reprocess this packet after received reply from router */
3668 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3669 silc_command_get_ident(cmd->payload),
3670 silc_server_command_motd,
3671 silc_server_command_dup(cmd));
3672 cmd->pending = TRUE;
3673 silc_command_set_ident(cmd->payload, old_ident);
3674 silc_buffer_free(tmpbuf);
3678 if (!entry && !cmd->pending && !server->standalone) {
3679 /* Send to the primary router */
3681 SilcUInt16 old_ident;
3683 old_ident = silc_command_get_ident(cmd->payload);
3684 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3685 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3687 silc_server_packet_send(server, server->router->connection,
3688 SILC_PACKET_COMMAND, cmd->packet->flags,
3689 tmpbuf->data, tmpbuf->len, TRUE);
3691 /* Reprocess this packet after received reply from router */
3692 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3693 silc_command_get_ident(cmd->payload),
3694 silc_server_command_motd,
3695 silc_server_command_dup(cmd));
3696 cmd->pending = TRUE;
3697 silc_command_set_ident(cmd->payload, old_ident);
3698 silc_buffer_free(tmpbuf);
3703 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3704 SILC_STATUS_ERR_NO_SUCH_SERVER);
3708 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3709 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3710 SILC_STATUS_OK, 0, ident, 2,
3714 strlen(entry->motd) : 0);
3715 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3716 packet->data, packet->len, FALSE);
3717 silc_buffer_free(packet);
3718 silc_buffer_free(idp);
3722 silc_server_command_free(cmd);
3725 /* Server side of command UMODE. Client can use this command to set/unset
3726 user mode. Client actually cannot set itself to be as server/router
3727 operator so this can be used only to unset the modes. */
3729 SILC_SERVER_CMD_FUNC(umode)
3731 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3732 SilcServer server = cmd->server;
3733 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3735 unsigned char *tmp_mask, m[4];
3736 SilcUInt32 mask = 0;
3737 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3738 bool set_mask = FALSE;
3740 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3743 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2);
3745 /* Get the client's mode mask */
3746 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3748 SILC_GET32_MSB(mask, tmp_mask);
3753 /* Check that mode changing is allowed. */
3754 if (!silc_server_check_umode_rights(server, client, mask)) {
3755 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3756 SILC_STATUS_ERR_PERM_DENIED);
3760 /* Anonymous mode cannot be set by client */
3761 if (mask & SILC_UMODE_ANONYMOUS) {
3762 if (!(client->mode & SILC_UMODE_ANONYMOUS)) {
3763 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3764 SILC_STATUS_ERR_PERM_DENIED);
3768 if (client->mode & SILC_UMODE_ANONYMOUS) {
3769 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3770 SILC_STATUS_ERR_PERM_DENIED);
3775 /* Change the mode */
3776 client->mode = mask;
3778 /* Send UMODE change to primary router */
3779 if (!server->standalone)
3780 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3781 client->id, client->mode);
3783 /* Check if anyone is watching this nickname */
3784 if (server->server_type == SILC_ROUTER)
3785 silc_server_check_watcher_list(server, client, NULL,
3786 SILC_NOTIFY_TYPE_UMODE_CHANGE);
3789 /* Send command reply to sender */
3790 SILC_PUT32_MSB(client->mode, m);
3791 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3792 SILC_STATUS_OK, 0, ident, 1,
3794 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3795 packet->data, packet->len, FALSE);
3796 silc_buffer_free(packet);
3799 silc_server_command_free(cmd);
3802 /* Server side command of CMODE. Changes channel mode */
3804 SILC_SERVER_CMD_FUNC(cmode)
3806 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3807 SilcServer server = cmd->server;
3808 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3809 SilcIDListData idata = (SilcIDListData)client;
3810 SilcChannelID *channel_id = NULL;
3811 SilcChannelEntry channel;
3812 SilcChannelClientEntry chl;
3813 SilcBuffer packet, cidp;
3814 unsigned char *tmp, *tmp_id, *tmp_mask;
3815 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3816 SilcUInt32 mode_mask = 0, tmp_len, tmp_len2;
3817 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3818 bool set_mask = FALSE;
3820 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 7);
3822 /* Get Channel ID */
3823 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3825 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3826 SILC_STATUS_ERR_NO_CHANNEL_ID);
3829 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
3831 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3832 SILC_STATUS_ERR_NO_CHANNEL_ID);
3836 /* Get the channel mode mask */
3837 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3839 SILC_GET32_MSB(mode_mask, tmp_mask);
3843 /* Get channel entry */
3844 channel = silc_idlist_find_channel_by_id(server->local_list,
3847 channel = silc_idlist_find_channel_by_id(server->global_list,
3850 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3851 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3856 /* Check whether this client is on the channel */
3857 if (!silc_server_client_on_channel(client, channel, &chl)) {
3858 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3859 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3863 /* Check that client has rights to change any requested channel modes */
3864 if (set_mask && !silc_server_check_cmode_rights(server, channel, chl,
3866 silc_server_command_send_status_reply(
3867 cmd, SILC_COMMAND_CMODE,
3868 (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) ?
3869 SILC_STATUS_ERR_NO_CHANNEL_PRIV :
3870 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV));
3874 /* If mode mask was not sent as argument then merely return the current
3875 mode mask to the sender. */
3878 SILC_PUT32_MSB(channel->mode, m);
3879 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3880 SILC_STATUS_OK, 0, ident, 2,
3881 2, tmp_id, tmp_len2,
3883 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3884 packet->data, packet->len, FALSE);
3885 silc_buffer_free(packet);
3890 * Check the modes. Modes that requires nothing special operation are
3894 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3895 /* Channel uses private keys to protect traffic. Client(s) has set the
3896 key locally they want to use, server does not know that key. */
3897 /* Nothing interesting to do here */
3899 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3900 /* The mode is removed and we need to generate and distribute
3901 new channel key. Clients are not using private channel keys
3902 anymore after this. */
3904 /* Re-generate channel key */
3905 if (!silc_server_create_channel_key(server, channel, 0))
3908 /* Send the channel key. This sends it to our local clients and if
3909 we are normal server to our router as well. */
3910 silc_server_send_channel_key(server, NULL, channel,
3911 server->server_type == SILC_ROUTER ?
3912 FALSE : !server->standalone);
3914 cipher = channel->channel_key->cipher->name;
3915 hmac = (char *)silc_hmac_get_name(channel->hmac);
3919 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3920 /* User limit is set on channel */
3921 SilcUInt32 user_limit;
3923 /* Get user limit */
3924 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3926 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3927 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3928 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3932 SILC_GET32_MSB(user_limit, tmp);
3933 channel->user_limit = user_limit;
3936 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3937 /* User limit mode is unset. Remove user limit */
3938 channel->user_limit = 0;
3941 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3942 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3943 /* Passphrase has been set to channel */
3945 /* Get the passphrase */
3946 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3948 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3949 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3953 /* Save the passphrase */
3954 passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
3957 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3958 /* Passphrase mode is unset. remove the passphrase */
3959 silc_free(channel->passphrase);
3960 channel->passphrase = NULL;
3964 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3965 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3966 /* Cipher to use protect the traffic */
3967 SilcCipher newkey, oldkey;
3970 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3972 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3973 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3977 /* Delete old cipher and allocate the new one */
3978 if (!silc_cipher_alloc(cipher, &newkey)) {
3979 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3980 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3984 oldkey = channel->channel_key;
3985 channel->channel_key = newkey;
3987 /* Re-generate channel key */
3988 if (!silc_server_create_channel_key(server, channel, 0)) {
3989 /* We don't have new key, revert to old one */
3990 channel->channel_key = oldkey;
3994 /* Remove old channel key for good */
3995 silc_cipher_free(oldkey);
3997 /* Send the channel key. This sends it to our local clients and if
3998 we are normal server to our router as well. */
3999 silc_server_send_channel_key(server, NULL, channel,
4000 server->server_type == SILC_ROUTER ?
4001 FALSE : !server->standalone);
4004 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
4005 /* Cipher mode is unset. Remove the cipher and revert back to
4007 SilcCipher newkey, oldkey;
4008 cipher = channel->cipher;
4010 /* Delete old cipher and allocate default one */
4011 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
4012 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4013 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4017 oldkey = channel->channel_key;
4018 channel->channel_key = newkey;
4020 /* Re-generate channel key */
4021 if (!silc_server_create_channel_key(server, channel, 0)) {
4022 /* We don't have new key, revert to old one */
4023 channel->channel_key = oldkey;
4027 /* Remove old channel key for good */
4028 silc_cipher_free(oldkey);
4030 /* Send the channel key. This sends it to our local clients and if
4031 we are normal server to our router as well. */
4032 silc_server_send_channel_key(server, NULL, channel,
4033 server->server_type == SILC_ROUTER ?
4034 FALSE : !server->standalone);
4038 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
4039 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
4040 /* HMAC to use protect the traffic */
4041 unsigned char hash[32];
4045 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4047 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4048 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4052 /* Delete old hmac and allocate the new one */
4053 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4054 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4055 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4059 silc_hmac_free(channel->hmac);
4060 channel->hmac = newhmac;
4062 /* Set the HMAC key out of current channel key. The client must do
4064 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4065 channel->key_len / 8, hash);
4066 silc_hmac_set_key(channel->hmac, hash,
4067 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4068 memset(hash, 0, sizeof(hash));
4071 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4072 /* Hmac mode is unset. Remove the hmac and revert back to
4075 unsigned char hash[32];
4076 hmac = channel->hmac_name;
4078 /* Delete old hmac and allocate default one */
4079 silc_hmac_free(channel->hmac);
4080 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4081 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4082 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4086 silc_hmac_free(channel->hmac);
4087 channel->hmac = newhmac;
4089 /* Set the HMAC key out of current channel key. The client must do
4091 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4092 channel->key_len / 8,
4094 silc_hmac_set_key(channel->hmac, hash,
4095 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4096 memset(hash, 0, sizeof(hash));
4100 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4101 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4102 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4103 /* Set the founder authentication */
4104 SilcAuthPayload auth;
4106 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4108 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4109 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4113 auth = silc_auth_payload_parse(tmp, tmp_len);
4115 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4116 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4120 /* Save the public key */
4121 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
4122 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
4125 channel->founder_method = silc_auth_get_method(auth);
4127 if (channel->founder_method == SILC_AUTH_PASSWORD) {
4128 tmp = silc_auth_get_data(auth, &tmp_len);
4129 channel->founder_passwd = silc_memdup(tmp, tmp_len);
4130 channel->founder_passwd_len = tmp_len;
4132 /* Verify the payload before setting the mode */
4133 if (!silc_auth_verify(auth, channel->founder_method,
4134 channel->founder_key, 0, idata->hash,
4135 client->id, SILC_ID_CLIENT)) {
4136 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4137 SILC_STATUS_ERR_AUTH_FAILED);
4142 silc_auth_payload_free(auth);
4146 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4147 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4148 if (channel->founder_key)
4149 silc_pkcs_public_key_free(channel->founder_key);
4150 if (channel->founder_passwd) {
4151 silc_free(channel->founder_passwd);
4152 channel->founder_passwd = NULL;
4158 /* Finally, set the mode */
4159 channel->mode = mode_mask;
4161 /* Send CMODE_CHANGE notify. */
4162 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4163 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4164 SILC_NOTIFY_TYPE_CMODE_CHANGE, 5,
4165 cidp->data, cidp->len,
4167 cipher, cipher ? strlen(cipher) : 0,
4168 hmac, hmac ? strlen(hmac) : 0,
4169 passphrase, passphrase ?
4170 strlen(passphrase) : 0);
4172 /* Set CMODE notify type to network */
4173 if (!server->standalone)
4174 silc_server_send_notify_cmode(server, server->router->connection,
4175 server->server_type == SILC_ROUTER ?
4176 TRUE : FALSE, channel,
4177 mode_mask, client->id, SILC_ID_CLIENT,
4178 cipher, hmac, passphrase);
4180 /* Send command reply to sender */
4181 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4182 SILC_STATUS_OK, 0, ident, 2,
4183 2, tmp_id, tmp_len2,
4185 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4186 packet->data, packet->len, FALSE);
4188 silc_buffer_free(packet);
4189 silc_buffer_free(cidp);
4192 silc_free(channel_id);
4193 silc_server_command_free(cmd);
4196 /* Server side of CUMODE command. Changes client's mode on a channel. */
4198 SILC_SERVER_CMD_FUNC(cumode)
4200 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4201 SilcServer server = cmd->server;
4202 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4203 SilcIDListData idata = (SilcIDListData)client;
4204 SilcChannelID *channel_id;
4205 SilcClientID *client_id;
4206 SilcChannelEntry channel;
4207 SilcClientEntry target_client;
4208 SilcChannelClientEntry chl;
4209 SilcBuffer packet, idp;
4210 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4211 SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4213 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4215 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4217 /* Get Channel ID */
4218 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4220 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4221 SILC_STATUS_ERR_NO_CHANNEL_ID);
4224 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
4226 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4227 SILC_STATUS_ERR_NO_CHANNEL_ID);
4231 /* Get channel entry */
4232 channel = silc_idlist_find_channel_by_id(server->local_list,
4235 channel = silc_idlist_find_channel_by_id(server->global_list,
4238 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4239 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4244 /* Check whether sender is on the channel */
4245 if (!silc_server_client_on_channel(client, channel, &chl)) {
4246 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4247 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4250 sender_mask = chl->mode;
4252 /* Get the target client's channel mode mask */
4253 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4255 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4256 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4259 SILC_GET32_MSB(target_mask, tmp_mask);
4261 /* Get target Client ID */
4262 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4264 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4265 SILC_STATUS_ERR_NO_CLIENT_ID);
4268 client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
4270 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4271 SILC_STATUS_ERR_NO_CLIENT_ID);
4275 /* Get target client's entry */
4276 target_client = silc_idlist_find_client_by_id(server->local_list,
4277 client_id, TRUE, NULL);
4278 if (!target_client) {
4279 target_client = silc_idlist_find_client_by_id(server->global_list,
4280 client_id, TRUE, NULL);
4283 if (target_client != client &&
4284 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4285 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4286 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4287 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4291 /* Check whether target client is on the channel */
4292 if (target_client != client) {
4293 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4294 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4295 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4304 /* If the target client is founder, no one else can change their mode
4306 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4307 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4308 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4312 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4313 if (target_client != client) {
4314 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4315 SILC_STATUS_ERR_NOT_YOU);
4319 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4320 /* The client tries to claim the founder rights. */
4321 unsigned char *tmp_auth;
4322 SilcUInt32 tmp_auth_len, auth_len;
4325 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4326 !channel->founder_key || !idata->public_key ||
4327 !silc_pkcs_public_key_compare(channel->founder_key,
4328 idata->public_key)) {
4329 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4330 SILC_STATUS_ERR_NOT_YOU);
4334 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4336 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4337 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4341 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4342 (void *)channel->founder_passwd : (void *)channel->founder_key);
4343 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4344 channel->founder_passwd_len : 0);
4346 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4347 channel->founder_method, auth, auth_len,
4348 idata->hash, client->id, SILC_ID_CLIENT)) {
4349 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4350 SILC_STATUS_ERR_AUTH_FAILED);
4354 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4358 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4359 if (target_client == client) {
4360 /* Remove channel founder rights from itself */
4361 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4364 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4365 SILC_STATUS_ERR_NOT_YOU);
4371 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4372 /* Promote to operator */
4373 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4374 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4375 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4376 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4377 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4381 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4385 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4386 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4387 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4388 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4389 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4393 /* Demote to normal user */
4394 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4399 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4400 if (target_client != client) {
4401 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4402 SILC_STATUS_ERR_NOT_YOU);
4406 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
4407 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4411 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4412 if (target_client != client) {
4413 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4414 SILC_STATUS_ERR_NOT_YOU);
4418 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4423 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4424 if (target_client != client) {
4425 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4426 SILC_STATUS_ERR_NOT_YOU);
4430 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)) {
4431 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4435 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4436 if (target_client != client) {
4437 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4438 SILC_STATUS_ERR_NOT_YOU);
4442 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4447 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4448 if (target_client != client) {
4449 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4450 SILC_STATUS_ERR_NOT_YOU);
4454 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)) {
4455 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4459 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4460 if (target_client != client) {
4461 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4462 SILC_STATUS_ERR_NOT_YOU);
4466 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4471 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4472 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4474 /* Send notify to channel, notify only if mode was actually changed. */
4476 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4477 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4478 idp->data, idp->len,
4482 /* Set CUMODE notify type to network */
4483 if (!server->standalone)
4484 silc_server_send_notify_cumode(server, server->router->connection,
4485 server->server_type == SILC_ROUTER ?
4486 TRUE : FALSE, channel,
4487 target_mask, client->id,
4492 /* Send command reply to sender */
4493 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4494 SILC_STATUS_OK, 0, ident, 3,
4496 3, tmp_ch_id, tmp_ch_len,
4497 4, tmp_id, tmp_len);
4498 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4499 packet->data, packet->len, FALSE);
4501 silc_buffer_free(packet);
4502 silc_free(channel_id);
4503 silc_free(client_id);
4504 silc_buffer_free(idp);
4507 silc_server_command_free(cmd);
4510 /* Server side of KICK command. Kicks client out of channel. */
4512 SILC_SERVER_CMD_FUNC(kick)
4514 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4515 SilcServer server = cmd->server;
4516 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4517 SilcClientEntry target_client;
4518 SilcChannelID *channel_id;
4519 SilcClientID *client_id;
4520 SilcChannelEntry channel;
4521 SilcChannelClientEntry chl;
4523 SilcUInt32 tmp_len, target_idp_len;
4524 unsigned char *tmp, *comment, *target_idp;
4526 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4528 /* Get Channel ID */
4529 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4531 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4532 SILC_STATUS_ERR_NO_CHANNEL_ID);
4535 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4537 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4538 SILC_STATUS_ERR_NO_CHANNEL_ID);
4542 /* Get channel entry */
4543 channel = silc_idlist_find_channel_by_id(server->local_list,
4546 channel = silc_idlist_find_channel_by_id(server->local_list,
4549 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4550 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4555 /* Check whether sender is on the channel */
4556 if (!silc_server_client_on_channel(client, channel, &chl)) {
4557 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4558 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4562 /* Check that the kicker is channel operator or channel founder */
4563 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
4564 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4565 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4566 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4570 /* Get target Client ID */
4571 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4573 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4574 SILC_STATUS_ERR_NO_CLIENT_ID);
4577 client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
4579 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4580 SILC_STATUS_ERR_NO_CLIENT_ID);
4584 /* Get target client's entry */
4585 target_client = silc_idlist_find_client_by_id(server->local_list,
4586 client_id, TRUE, NULL);
4587 if (!target_client) {
4588 target_client = silc_idlist_find_client_by_id(server->global_list,
4589 client_id, TRUE, NULL);
4592 /* Check whether target client is on the channel */
4593 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4594 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4595 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4599 /* Check that the target client is not channel founder. Channel founder
4600 cannot be kicked from the channel. */
4601 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4602 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4603 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4609 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4613 /* Send command reply to sender */
4614 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4617 /* Send KICKED notify to local clients on the channel */
4618 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4619 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4620 SILC_NOTIFY_TYPE_KICKED, 3,
4621 target_idp, target_idp_len,
4622 comment, comment ? strlen(comment) : 0,
4623 idp->data, idp->len);
4624 silc_buffer_free(idp);
4626 /* Remove the client from the channel. If the channel does not exist
4627 after removing the client then the client kicked itself off the channel
4628 and we don't have to send anything after that. */
4629 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4630 target_client, FALSE))
4633 /* Send KICKED notify to primary route */
4634 if (!server->standalone)
4635 silc_server_send_notify_kicked(server, server->router->connection,
4636 server->server_type == SILC_ROUTER ?
4637 TRUE : FALSE, channel,
4638 target_client->id, client->id, comment);
4640 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4641 /* Re-generate channel key */
4642 if (!silc_server_create_channel_key(server, channel, 0))
4645 /* Send the channel key to the channel. The key of course is not sent
4646 to the client who was kicked off the channel. */
4647 silc_server_send_channel_key(server, target_client->connection, channel,
4648 server->server_type == SILC_ROUTER ?
4649 FALSE : !server->standalone);
4653 silc_server_command_free(cmd);
4656 /* Server side of OPER command. Client uses this comand to obtain server
4657 operator privileges to this server/router. */
4659 SILC_SERVER_CMD_FUNC(oper)
4661 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4662 SilcServer server = cmd->server;
4663 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4664 unsigned char *username, *auth;
4666 SilcServerConfigAdmin *admin;
4667 SilcIDListData idata = (SilcIDListData)client;
4668 bool result = FALSE;
4669 SilcPublicKey cached_key;
4671 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4673 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4676 /* Get the username */
4677 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4679 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4680 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4684 /* Get the admin configuration */
4685 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4686 username, client->nickname);
4688 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4689 username, client->nickname);
4691 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4692 SILC_STATUS_ERR_AUTH_FAILED);
4697 /* Get the authentication payload */
4698 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4700 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4701 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4705 /* Verify the authentication data. If both passphrase and public key
4706 is set then try both of them. */
4707 if (admin->passphrase)
4708 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4709 admin->passphrase, admin->passphrase_len,
4710 idata->hash, client->id, SILC_ID_CLIENT);
4711 if (!result && admin->publickeys) {
4712 cached_key = silc_server_get_public_key(server, admin->publickeys);
4715 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4716 cached_key, 0, idata->hash,
4717 client->id, SILC_ID_CLIENT);
4720 /* Authentication failed */
4721 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4722 SILC_STATUS_ERR_AUTH_FAILED);
4726 /* Client is now server operator */
4727 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4729 /* Update statistics */
4730 if (client->connection)
4731 server->stat.my_server_ops++;
4732 if (server->server_type == SILC_ROUTER)
4733 server->stat.server_ops++;
4735 /* Send UMODE change to primary router */
4736 if (!server->standalone)
4737 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4738 client->id, client->mode);
4740 /* Check if anyone is watching this nickname */
4741 if (server->server_type == SILC_ROUTER)
4742 silc_server_check_watcher_list(server, client, NULL,
4743 SILC_NOTIFY_TYPE_UMODE_CHANGE);
4745 /* Send reply to the sender */
4746 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4750 silc_server_command_free(cmd);
4753 SILC_TASK_CALLBACK(silc_server_command_detach_cb)
4755 QuitInternal q = (QuitInternal)context;
4756 SilcClientEntry client = (SilcClientEntry)q->sock->user_data;
4758 /* If there is pending outgoing data for the client then purge it
4759 to the network before closing connection. */
4760 silc_server_packet_queue_purge(q->server, q->sock);
4762 /* Close the connection on our side */
4763 client->router = NULL;
4764 client->connection = NULL;
4765 q->sock->user_data = NULL;
4766 silc_server_close_connection(q->server, q->sock);
4771 SILC_TASK_CALLBACK(silc_server_command_detach_timeout)
4773 QuitInternal q = (QuitInternal)context;
4774 SilcClientEntry client = (SilcClientEntry)q->sock;
4776 SILC_LOG_DEBUG(("Start"));
4778 if (client->mode & SILC_UMODE_DETACHED)
4779 silc_server_free_client_data(q->server, NULL, client, TRUE,
4784 /* Server side of DETACH command. Detached the client from the network
4785 by closing the connection but preserving the session. */
4787 SILC_SERVER_CMD_FUNC(detach)
4789 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4790 SilcServer server = cmd->server;
4791 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4794 if (server->config->detach_disabled) {
4795 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
4796 SILC_STATUS_ERR_UNKNOWN_COMMAND);
4800 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4803 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
4805 /* Send the user mode notify to notify that client is detached */
4806 client->mode |= SILC_UMODE_DETACHED;
4807 client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
4808 if (!server->standalone)
4809 silc_server_send_notify_umode(server, server->router->connection,
4810 server->server_type == SILC_SERVER ?
4811 FALSE : TRUE, client->id, client->mode);
4813 /* Check if anyone is watching this nickname */
4814 if (server->server_type == SILC_ROUTER)
4815 silc_server_check_watcher_list(server, client, NULL,
4816 SILC_NOTIFY_TYPE_UMODE_CHANGE);
4818 q = silc_calloc(1, sizeof(*q));
4820 q->sock = cmd->sock;
4821 silc_schedule_task_add(server->schedule, 0, silc_server_command_detach_cb,
4822 q, 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
4824 if (server->config->detach_timeout) {
4825 q = silc_calloc(1, sizeof(*q));
4827 q->sock = (void *)client;
4828 silc_schedule_task_add(server->schedule, 0,
4829 silc_server_command_detach_timeout,
4830 q, server->config->detach_timeout * 60,
4831 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
4834 /* Send reply to the sender */
4835 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
4839 silc_server_command_free(cmd);
4842 /* Server side of WATCH command. */
4844 SILC_SERVER_CMD_FUNC(watch)
4846 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4847 SilcServer server = cmd->server;
4848 char *add_nick, *del_nick;
4849 SilcUInt32 add_nick_len, del_nick_len, tmp_len;
4851 unsigned char hash[16], *tmp;
4852 SilcClientEntry client;
4853 SilcClientID *client_id = NULL;
4855 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WATCH, cmd, 1, 3);
4857 if (server->server_type == SILC_SERVER && !server->standalone) {
4858 if (!cmd->pending) {
4859 /* Send the command to router */
4861 SilcUInt16 old_ident;
4863 old_ident = silc_command_get_ident(cmd->payload);
4864 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4865 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4867 silc_server_packet_send(server, server->router->connection,
4868 SILC_PACKET_COMMAND, cmd->packet->flags,
4869 tmpbuf->data, tmpbuf->len, TRUE);
4871 /* Reprocess this packet after received reply from router */
4872 silc_server_command_pending(server, SILC_COMMAND_WATCH,
4873 silc_command_get_ident(cmd->payload),
4874 silc_server_command_watch,
4875 silc_server_command_dup(cmd));
4876 cmd->pending = TRUE;
4877 silc_command_set_ident(cmd->payload, old_ident);
4878 silc_buffer_free(tmpbuf);
4879 } else if (context2) {
4880 /* Received reply from router, just send same data to the client. */
4881 SilcServerCommandReplyContext reply = context2;
4883 silc_command_get_status(reply->payload, &status, NULL);
4884 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, status);
4890 /* We are router and keep the watch list for local cell */
4892 /* Get the client ID */
4893 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4895 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4896 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4899 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4901 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4902 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
4906 /* Get the client entry which must be in local list */
4907 client = silc_idlist_find_client_by_id(server->local_list,
4908 client_id, TRUE, NULL);
4910 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4911 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
4916 add_nick = silc_argument_get_arg_type(cmd->args, 2, &add_nick_len);
4917 del_nick = silc_argument_get_arg_type(cmd->args, 3, &del_nick_len);
4918 if (!add_nick && !del_nick) {
4919 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4920 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4924 if (add_nick && add_nick_len > 128)
4925 add_nick[128] = '\0';
4926 if (del_nick && del_nick_len > 128)
4927 del_nick[128] = '\0';
4929 memset(nick, 0, sizeof(nick));
4931 /* Add new nickname to be watched in our cell */
4933 if (silc_server_name_bad_chars(add_nick, strlen(add_nick)) == TRUE) {
4934 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4935 SILC_STATUS_ERR_BAD_NICKNAME);
4939 /* Hash the nick, we have the hash saved, not nicks because we can
4940 do one to one mapping to the nick from Client ID hash this way. */
4941 silc_to_lower(add_nick, nick, sizeof(nick) - 1);
4942 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
4944 /* Check whether this client is already watching this nickname */
4945 if (silc_hash_table_find_by_context(server->watcher_list, hash,
4947 /* Nickname is alredy being watched for this client */
4948 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4949 SILC_STATUS_ERR_NICKNAME_IN_USE);
4953 /* Get the nickname from the watcher list and use the same key in
4954 new entries as well. If key doesn't exist then create it. */
4955 if (!silc_hash_table_find(server->watcher_list, hash, (void **)&tmp, NULL))
4956 tmp = silc_memdup(hash, CLIENTID_HASH_LEN);
4958 /* Add the client to the watcher list with the specified nickname hash. */
4959 silc_hash_table_add(server->watcher_list, tmp, client);
4962 /* Delete nickname from watch list */
4964 if (silc_server_name_bad_chars(del_nick, strlen(del_nick)) == TRUE) {
4965 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4966 SILC_STATUS_ERR_BAD_NICKNAME);
4970 /* Hash the nick, we have the hash saved, not nicks because we can
4971 do one to one mapping to the nick from Client ID hash this way. */
4972 silc_to_lower(del_nick, nick, sizeof(nick) - 1);
4973 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
4975 /* Check that this client is watching for this nickname */
4976 if (!silc_hash_table_find_by_context(server->watcher_list, hash,
4977 client, (void **)&tmp)) {
4978 /* Nickname is alredy being watched for this client */
4979 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4980 SILC_STATUS_ERR_NO_SUCH_NICK);
4984 /* Delete the nickname from the watcher list. */
4985 silc_hash_table_del_by_context(server->watcher_list, hash, client);
4987 /* Now check whether there still exists entries with this key, if not
4988 then free the key to not leak memory. */
4989 if (!silc_hash_table_find(server->watcher_list, hash, NULL, NULL))
4993 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4997 silc_free(client_id);
4998 silc_server_command_free(cmd);
5001 /* Server side of SILCOPER command. Client uses this comand to obtain router
5002 operator privileges to this router. */
5004 SILC_SERVER_CMD_FUNC(silcoper)
5006 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5007 SilcServer server = cmd->server;
5008 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5009 unsigned char *username, *auth;
5011 SilcServerConfigAdmin *admin;
5012 SilcIDListData idata = (SilcIDListData)client;
5013 bool result = FALSE;
5014 SilcPublicKey cached_key;
5016 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
5018 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5021 if (server->server_type != SILC_ROUTER) {
5022 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5023 SILC_STATUS_ERR_AUTH_FAILED);
5027 /* Get the username */
5028 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5030 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5031 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5035 /* Get the admin configuration */
5036 admin = silc_server_config_find_admin(server, cmd->sock->ip,
5037 username, client->nickname);
5039 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
5040 username, client->nickname);
5042 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5043 SILC_STATUS_ERR_AUTH_FAILED);
5048 /* Get the authentication payload */
5049 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5051 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5052 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5056 /* Verify the authentication data. If both passphrase and public key
5057 is set then try both of them. */
5058 if (admin->passphrase)
5059 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
5060 admin->passphrase, admin->passphrase_len,
5061 idata->hash, client->id, SILC_ID_CLIENT);
5062 if (!result && admin->publickeys) {
5063 cached_key = silc_server_get_public_key(server, admin->publickeys);
5066 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
5067 cached_key, 0, idata->hash,
5068 client->id, SILC_ID_CLIENT);
5071 /* Authentication failed */
5072 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
5073 SILC_STATUS_ERR_AUTH_FAILED);
5077 /* Client is now router operator */
5078 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
5080 /* Update statistics */
5081 if (client->connection)
5082 server->stat.my_router_ops++;
5083 if (server->server_type == SILC_ROUTER)
5084 server->stat.router_ops++;
5086 /* Send UMODE change to primary router */
5087 if (!server->standalone)
5088 silc_server_send_notify_umode(server, server->router->connection, TRUE,
5089 client->id, client->mode);
5091 /* Check if anyone is watching this nickname */
5092 if (server->server_type == SILC_ROUTER)
5093 silc_server_check_watcher_list(server, client, NULL,
5094 SILC_NOTIFY_TYPE_UMODE_CHANGE);
5096 /* Send reply to the sender */
5097 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5101 silc_server_command_free(cmd);
5104 /* Server side of command BAN. This is used to manage the ban list of the
5105 channel. To add clients and remove clients from the ban list. */
5107 SILC_SERVER_CMD_FUNC(ban)
5109 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5110 SilcServer server = cmd->server;
5111 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5113 SilcChannelEntry channel;
5114 SilcChannelClientEntry chl;
5115 SilcChannelID *channel_id = NULL;
5116 unsigned char *id, *add, *del;
5117 SilcUInt32 id_len, tmp_len;
5118 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5120 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5123 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
5125 /* Get Channel ID */
5126 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
5128 channel_id = silc_id_payload_parse_id(id, id_len, NULL);
5130 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5131 SILC_STATUS_ERR_NO_CHANNEL_ID);
5136 /* Get channel entry. The server must know about the channel since the
5137 client is expected to be on the channel. */
5138 channel = silc_idlist_find_channel_by_id(server->local_list,
5141 channel = silc_idlist_find_channel_by_id(server->global_list,
5144 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5145 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5150 /* Check whether this client is on the channel */
5151 if (!silc_server_client_on_channel(client, channel, &chl)) {
5152 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5153 SILC_STATUS_ERR_NOT_ON_CHANNEL);
5157 /* The client must be at least channel operator. */
5158 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
5159 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5160 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
5164 /* Get the new ban and add it to the ban list */
5165 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5167 if (!channel->ban_list)
5168 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
5170 channel->ban_list = silc_realloc(channel->ban_list,
5171 sizeof(*channel->ban_list) *
5173 strlen(channel->ban_list) + 2));
5174 if (add[tmp_len - 1] == ',')
5175 add[tmp_len - 1] = '\0';
5177 strncat(channel->ban_list, add, tmp_len);
5178 strncat(channel->ban_list, ",", 1);
5181 /* Get the ban to be removed and remove it from the list */
5182 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
5183 if (del && channel->ban_list) {
5184 char *start, *end, *n;
5186 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
5187 silc_free(channel->ban_list);
5188 channel->ban_list = NULL;
5190 start = strstr(channel->ban_list, del);
5191 if (start && strlen(start) >= tmp_len) {
5192 end = start + tmp_len;
5193 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
5194 strncat(n, channel->ban_list, start - channel->ban_list);
5195 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
5197 silc_free(channel->ban_list);
5198 channel->ban_list = n;
5203 /* Send the BAN notify type to our primary router. */
5204 if (!server->standalone && (add || del))
5205 silc_server_send_notify_ban(server, server->router->connection,
5206 server->server_type == SILC_ROUTER ?
5207 TRUE : FALSE, channel, add, del);
5209 /* Send the reply back to the client */
5211 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
5212 SILC_STATUS_OK, 0, ident, 2,
5214 3, channel->ban_list,
5216 strlen(channel->ban_list) -1 : 0);
5217 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5218 packet->data, packet->len, FALSE);
5220 silc_buffer_free(packet);
5223 silc_free(channel_id);
5224 silc_server_command_free(cmd);
5227 /* Server side command of LEAVE. Removes client from a channel. */
5229 SILC_SERVER_CMD_FUNC(leave)
5231 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5232 SilcServer server = cmd->server;
5233 SilcSocketConnection sock = cmd->sock;
5234 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
5235 SilcChannelID *id = NULL;
5236 SilcChannelEntry channel;
5240 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
5242 /* Get Channel ID */
5243 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
5245 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5246 SILC_STATUS_ERR_NO_CHANNEL_ID);
5249 id = silc_id_payload_parse_id(tmp, len, NULL);
5251 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5252 SILC_STATUS_ERR_NO_CHANNEL_ID);
5256 /* Get channel entry */
5257 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5259 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5261 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5262 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5267 /* Check whether this client is on the channel */
5268 if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
5269 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5270 SILC_STATUS_ERR_NOT_ON_CHANNEL);
5274 /* Notify routers that they should remove this client from their list
5275 of clients on the channel. Send LEAVE notify type. */
5276 if (!server->standalone)
5277 silc_server_send_notify_leave(server, server->router->connection,
5278 server->server_type == SILC_ROUTER ?
5279 TRUE : FALSE, channel, id_entry->id);
5281 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
5282 SILC_STATUS_OK, 2, tmp, len);
5284 /* Remove client from channel */
5285 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5287 /* If the channel does not exist anymore we won't send anything */
5290 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5291 /* Re-generate channel key */
5292 if (!silc_server_create_channel_key(server, channel, 0))
5295 /* Send the channel key */
5296 silc_server_send_channel_key(server, NULL, channel,
5297 server->server_type == SILC_ROUTER ?
5298 FALSE : !server->standalone);
5303 silc_server_command_free(cmd);
5306 /* Server side of command USERS. Resolves clients and their USERS currently
5307 joined on the requested channel. The list of Client ID's and their modes
5308 on the channel is sent back. */
5310 SILC_SERVER_CMD_FUNC(users)
5312 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5313 SilcServer server = cmd->server;
5314 SilcChannelEntry channel;
5315 SilcChannelID *id = NULL;
5316 SilcBuffer packet, idp;
5317 unsigned char *channel_id;
5318 SilcUInt32 channel_id_len;
5319 SilcBuffer client_id_list;
5320 SilcBuffer client_mode_list;
5321 unsigned char lc[4];
5322 SilcUInt32 list_count = 0;
5323 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5326 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5328 /* Get Channel ID */
5329 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5331 /* Get channel name */
5332 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5334 if (!channel_id && !channel_name) {
5335 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5336 SILC_STATUS_ERR_NO_CHANNEL_ID);
5341 id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
5343 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5344 SILC_STATUS_ERR_NO_CHANNEL_ID);
5349 /* If we are server and we don't know about this channel we will send
5350 the command to our router. If we know about the channel then we also
5351 have the list of users already. */
5353 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5355 channel = silc_idlist_find_channel_by_name(server->local_list,
5356 channel_name, NULL);
5358 if (!channel || channel->disabled || !channel->users_resolved) {
5359 if (server->server_type != SILC_ROUTER && !server->standalone &&
5363 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5364 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5366 /* Send USERS command */
5367 silc_server_packet_send(server, server->router->connection,
5368 SILC_PACKET_COMMAND, cmd->packet->flags,
5369 tmpbuf->data, tmpbuf->len, TRUE);
5371 /* Reprocess this packet after received reply */
5372 silc_server_command_pending(server, SILC_COMMAND_USERS,
5373 silc_command_get_ident(cmd->payload),
5374 silc_server_command_users,
5375 silc_server_command_dup(cmd));
5376 cmd->pending = TRUE;
5377 silc_command_set_ident(cmd->payload, ident);
5378 silc_buffer_free(tmpbuf);
5383 /* Check the global list as well. */
5385 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5387 channel = silc_idlist_find_channel_by_name(server->global_list,
5388 channel_name, NULL);
5390 /* Channel really does not exist */
5391 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5392 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5397 /* If the channel is private or secret do not send anything, unless the
5398 user requesting this command is on the channel or is server */
5399 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5400 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5401 && !silc_server_client_on_channel(cmd->sock->user_data, channel,
5403 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5404 SILC_STATUS_ERR_NOT_ON_CHANNEL);
5409 /* Get the users list */
5410 silc_server_get_users_on_channel(server, channel, &client_id_list,
5411 &client_mode_list, &list_count);
5414 SILC_PUT32_MSB(list_count, lc);
5417 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5418 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5419 SILC_STATUS_OK, 0, ident, 4,
5420 2, idp->data, idp->len,
5422 4, client_id_list->data,
5423 client_id_list->len,
5424 5, client_mode_list->data,
5425 client_mode_list->len);
5426 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5427 packet->data, packet->len, FALSE);
5429 silc_buffer_free(idp);
5430 silc_buffer_free(packet);
5431 silc_buffer_free(client_id_list);
5432 silc_buffer_free(client_mode_list);
5436 silc_server_command_free(cmd);
5439 /* Server side of command GETKEY. This fetches the client's public key
5440 from the server where to the client is connected. */
5442 SILC_SERVER_CMD_FUNC(getkey)
5444 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5445 SilcServer server = cmd->server;
5447 SilcClientEntry client;
5448 SilcServerEntry server_entry;
5449 SilcClientID *client_id = NULL;
5450 SilcServerID *server_id = NULL;
5451 SilcIDPayload idp = NULL;
5452 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5453 unsigned char *tmp, *pkdata;
5454 SilcUInt32 tmp_len, pklen;
5455 SilcBuffer pk = NULL;
5457 SilcPublicKey public_key;
5459 SILC_LOG_DEBUG(("Start"));
5461 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5463 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5464 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5467 idp = silc_id_payload_parse(tmp, tmp_len);
5469 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5470 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5474 id_type = silc_id_payload_get_type(idp);
5475 if (id_type == SILC_ID_CLIENT) {
5476 client_id = silc_id_payload_get_id(idp);
5478 /* If the client is not found from local list there is no chance it
5479 would be locally connected client so send the command further. */
5480 client = silc_idlist_find_client_by_id(server->local_list,
5481 client_id, TRUE, NULL);
5483 client = silc_idlist_find_client_by_id(server->global_list,
5484 client_id, TRUE, NULL);
5486 if ((!client && !cmd->pending && !server->standalone) ||
5487 (client && !client->connection && !cmd->pending &&
5488 !(client->mode & SILC_UMODE_DETACHED)) ||
5489 (client && !client->data.public_key && !cmd->pending)) {
5491 SilcUInt16 old_ident;
5492 SilcSocketConnection dest_sock;
5494 dest_sock = silc_server_get_client_route(server, NULL, 0,
5495 client_id, NULL, NULL);
5499 old_ident = silc_command_get_ident(cmd->payload);
5500 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5501 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5503 silc_server_packet_send(server, dest_sock,
5504 SILC_PACKET_COMMAND, cmd->packet->flags,
5505 tmpbuf->data, tmpbuf->len, TRUE);
5507 /* Reprocess this packet after received reply from router */
5508 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5509 silc_command_get_ident(cmd->payload),
5510 silc_server_command_getkey,
5511 silc_server_command_dup(cmd));
5512 cmd->pending = TRUE;
5513 silc_command_set_ident(cmd->payload, old_ident);
5514 silc_buffer_free(tmpbuf);
5519 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5520 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5524 /* The client is locally connected, just get the public key and
5525 send it back. If they key does not exist then do not send it,
5526 send just OK reply */
5527 public_key = client->data.public_key;
5532 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5533 pk = silc_buffer_alloc(4 + tmp_len);
5534 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5535 silc_buffer_format(pk,
5536 SILC_STR_UI_SHORT(tmp_len),
5537 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5538 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5544 } else if (id_type == SILC_ID_SERVER) {
5545 server_id = silc_id_payload_get_id(idp);
5547 /* If the server is not found from local list there is no chance it
5548 would be locally connected server so send the command further. */
5549 server_entry = silc_idlist_find_server_by_id(server->local_list,
5550 server_id, TRUE, NULL);
5552 server_entry = silc_idlist_find_server_by_id(server->global_list,
5553 server_id, TRUE, NULL);
5555 if (server_entry != server->id_entry &&
5556 ((!server_entry && !cmd->pending && !server->standalone) ||
5557 (server_entry && !server_entry->connection && !cmd->pending &&
5558 !server->standalone) ||
5559 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5560 !server->standalone))) {
5562 SilcUInt16 old_ident;
5564 old_ident = silc_command_get_ident(cmd->payload);
5565 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5566 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5568 silc_server_packet_send(server, server->router->connection,
5569 SILC_PACKET_COMMAND, cmd->packet->flags,
5570 tmpbuf->data, tmpbuf->len, TRUE);
5572 /* Reprocess this packet after received reply from router */
5573 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5574 silc_command_get_ident(cmd->payload),
5575 silc_server_command_getkey,
5576 silc_server_command_dup(cmd));
5577 cmd->pending = TRUE;
5578 silc_command_set_ident(cmd->payload, old_ident);
5579 silc_buffer_free(tmpbuf);
5583 if (!server_entry) {
5584 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5585 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5589 /* If they key does not exist then do not send it, send just OK reply */
5590 public_key = (!server_entry->data.public_key ?
5591 (server_entry == server->id_entry ? server->public_key :
5592 NULL) : server_entry->data.public_key);
5597 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5598 pk = silc_buffer_alloc(4 + tmp_len);
5599 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5600 silc_buffer_format(pk,
5601 SILC_STR_UI_SHORT(tmp_len),
5602 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5603 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5613 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5614 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5615 SILC_STATUS_OK, 0, ident,
5619 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5620 packet->data, packet->len, FALSE);
5621 silc_buffer_free(packet);
5624 silc_buffer_free(pk);
5628 silc_id_payload_free(idp);
5629 silc_free(client_id);
5630 silc_free(server_id);
5631 silc_server_command_free(cmd);
5635 /* Private range commands, specific to this implementation */
5637 /* Server side command of CONNECT. Connects us to the specified remote
5638 server or router. */
5640 SILC_SERVER_CMD_FUNC(connect)
5642 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5643 SilcServer server = cmd->server;
5644 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5645 unsigned char *tmp, *host;
5647 SilcUInt32 port = SILC_PORT;
5649 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
5651 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5654 /* Check whether client has the permissions. */
5655 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5656 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5657 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5658 SILC_STATUS_ERR_NO_SERVER_PRIV);
5662 if (server->server_type == SILC_ROUTER &&
5663 client->mode & SILC_UMODE_SERVER_OPERATOR) {
5664 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5665 SILC_STATUS_ERR_NO_ROUTER_PRIV);
5669 /* Get the remote server */
5670 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5672 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5673 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5678 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5680 SILC_GET32_MSB(port, tmp);
5682 /* Create the connection. It is done with timeout and is async. */
5683 silc_server_create_connection(server, host, port);
5685 /* Send reply to the sender */
5686 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5690 silc_server_command_free(cmd);
5693 /* Server side command of CLOSE. Closes connection to a specified server. */
5695 SILC_SERVER_CMD_FUNC(close)
5697 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5698 SilcServer server = cmd->server;
5699 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5700 SilcServerEntry server_entry;
5701 SilcSocketConnection sock;
5704 unsigned char *name;
5705 SilcUInt32 port = SILC_PORT;
5707 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
5709 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5712 /* Check whether client has the permissions. */
5713 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5714 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5715 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5716 SILC_STATUS_ERR_NO_SERVER_PRIV);
5720 /* Get the remote server */
5721 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5723 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5724 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5729 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5731 SILC_GET32_MSB(port, tmp);
5733 server_entry = silc_idlist_find_server_by_conn(server->local_list,
5734 name, port, FALSE, NULL);
5736 server_entry = silc_idlist_find_server_by_conn(server->global_list,
5737 name, port, FALSE, NULL);
5738 if (!server_entry) {
5739 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5740 SILC_STATUS_ERR_NO_SERVER_ID);
5744 /* Send reply to the sender */
5745 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5748 /* Close the connection to the server */
5749 sock = (SilcSocketConnection)server_entry->connection;
5751 /* If we shutdown primary router connection manually then don't trigger
5752 any reconnect or backup router connections, by setting the router
5754 if (server->router == server_entry) {
5755 server->id_entry->router = NULL;
5756 server->router = NULL;
5757 server->standalone = TRUE;
5759 silc_server_free_sock_user_data(server, sock, NULL);
5760 silc_server_close_connection(server, sock);
5763 silc_server_command_free(cmd);
5766 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
5767 active connections. */
5769 SILC_SERVER_CMD_FUNC(shutdown)
5771 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5772 SilcServer server = cmd->server;
5773 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5775 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
5777 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5780 /* Check whether client has the permission. */
5781 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5782 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5783 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5784 SILC_STATUS_ERR_NO_SERVER_PRIV);
5788 /* Send reply to the sender */
5789 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5792 /* Then, gracefully, or not, bring the server down. */
5793 silc_server_stop(server);
5797 silc_server_command_free(cmd);