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 client->fast_command = ((client->fast_command - 1) <= 0 ? 0 :
236 client->fast_command--);
240 if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
241 (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
242 silc_schedule_task_add(server->schedule, sock->sock,
243 silc_server_command_process_timeout,
245 2 - (time(NULL) - client->last_command), 0,
246 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
248 silc_schedule_task_add(server->schedule, sock->sock,
249 silc_server_command_process_timeout,
250 (void *)timeout, 0, 1,
251 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
255 /* Execute for server */
257 if (!(cmd->flags & SILC_CF_REG))
259 else if (silc_server_is_registered(server, sock, ctx, cmd->cmd))
262 silc_server_command_free(ctx);
265 /* Allocate Command Context */
267 SilcServerCommandContext silc_server_command_alloc()
269 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
274 /* Free's the command context allocated before executing the command */
276 void silc_server_command_free(SilcServerCommandContext ctx)
279 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
281 if (ctx->users < 1) {
283 silc_command_payload_free(ctx->payload);
285 silc_packet_context_free(ctx->packet);
287 silc_socket_free(ctx->sock); /* Decrease reference counter */
292 /* Duplicate Command Context by adding reference counter. The context won't
293 be free'd untill it hits zero. */
295 SilcServerCommandContext
296 silc_server_command_dup(SilcServerCommandContext ctx)
299 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
304 /* Add new pending command to be executed when reply to a command has been
305 received. The `reply_cmd' is the command that will call the `callback'
306 with `context' when reply has been received. It can be SILC_COMMAND_NONE
307 to match any command with the `ident'. If `ident' is non-zero
308 the `callback' will be executed when received reply with command
309 identifier `ident'. If there already exists pending command for the
310 specified command, ident, callback and context this function has no
313 bool silc_server_command_pending(SilcServer server,
314 SilcCommand reply_cmd,
316 SilcCommandCb callback,
319 SilcServerCommandPending *reply;
321 /* Check whether identical pending already exists for same command,
322 ident, callback and callback context. If it does then it would be
323 error to register it again. */
324 silc_dlist_start(server->pending_commands);
325 while ((reply = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
326 if (reply->reply_cmd == reply_cmd && reply->ident == ident &&
327 reply->callback == callback && reply->context == context)
331 reply = silc_calloc(1, sizeof(*reply));
332 reply->reply_cmd = reply_cmd;
333 reply->ident = ident;
334 reply->context = context;
335 reply->callback = callback;
336 silc_dlist_add(server->pending_commands, reply);
341 /* Deletes pending command by reply command type. */
343 void silc_server_command_pending_del(SilcServer server,
344 SilcCommand reply_cmd,
347 SilcServerCommandPending *r;
349 silc_dlist_start(server->pending_commands);
350 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
351 if (r->reply_cmd == reply_cmd && r->ident == ident) {
352 silc_dlist_del(server->pending_commands, r);
358 /* Checks for pending commands and marks callbacks to be called from
359 the command reply function. Returns TRUE if there were pending command. */
361 SilcServerCommandPendingCallbacks
362 silc_server_command_pending_check(SilcServer server,
363 SilcServerCommandReplyContext ctx,
366 SilcUInt32 *callbacks_count)
368 SilcServerCommandPending *r;
369 SilcServerCommandPendingCallbacks callbacks = NULL;
372 silc_dlist_start(server->pending_commands);
373 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
374 if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE)
375 && r->ident == ident) {
376 callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
377 callbacks[i].context = r->context;
378 callbacks[i].callback = r->callback;
384 *callbacks_count = i;
388 /* Sends simple status message as command reply packet */
391 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
397 SILC_LOG_DEBUG(("Sending command status %d", status));
400 silc_command_reply_payload_encode_va(command, status, 0,
401 silc_command_get_ident(cmd->payload),
403 silc_server_packet_send(cmd->server, cmd->sock,
404 SILC_PACKET_COMMAND_REPLY, 0,
405 buffer->data, buffer->len, FALSE);
406 silc_buffer_free(buffer);
409 /* Sends command status reply with one extra argument. The argument
410 type must be sent as argument. */
413 silc_server_command_send_status_data(SilcServerCommandContext cmd,
417 const unsigned char *arg,
422 SILC_LOG_DEBUG(("Sending command status %d", status));
425 silc_command_reply_payload_encode_va(command, status, 0,
426 silc_command_get_ident(cmd->payload),
427 1, arg_type, arg, arg_len);
428 silc_server_packet_send(cmd->server, cmd->sock,
429 SILC_PACKET_COMMAND_REPLY, 0,
430 buffer->data, buffer->len, FALSE);
431 silc_buffer_free(buffer);
434 /* This function can be called to check whether in the command reply
435 an error occurred. This function has no effect if this is called
436 when the command function was not called as pending command callback.
437 This returns TRUE if error had occurred. */
440 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
441 SilcServerCommandReplyContext cmdr,
444 if (!cmd->pending || !cmdr)
447 if (!silc_command_get_status(cmdr->payload, NULL, NULL)) {
450 /* Send the same command reply payload */
451 silc_command_set_ident(cmdr->payload,
452 silc_command_get_ident(cmd->payload));
453 buffer = silc_command_payload_encode_payload(cmdr->payload);
454 silc_server_packet_send(cmd->server, cmd->sock,
455 SILC_PACKET_COMMAND_REPLY, 0,
456 buffer->data, buffer->len, FALSE);
457 silc_buffer_free(buffer);
464 /******************************************************************************
468 ******************************************************************************/
471 silc_server_command_whois_parse(SilcServerCommandContext cmd,
472 SilcClientID ***client_id,
473 SilcUInt32 *client_id_count,
481 SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
484 /* If client ID is in the command it must be used instead of nickname */
485 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
487 /* No ID, get the nickname@server string and parse it. */
488 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
490 silc_parse_userfqdn(tmp, nickname, server_name);
492 silc_server_command_send_status_reply(cmd, command,
493 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
497 /* Command includes ID, we must use that. Also check whether the command
498 has more than one ID set - take them all. */
500 *client_id = silc_calloc(1, sizeof(**client_id));
501 (*client_id)[0] = silc_id_payload_parse_id(tmp, len, NULL);
502 if ((*client_id)[0] == NULL) {
503 silc_free(*client_id);
504 silc_server_command_send_status_reply(cmd, command,
505 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
508 *client_id_count = 1;
510 /* Take all ID's from the command packet */
512 for (k = 1, i = 1; i < argc; i++) {
513 tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
515 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
516 (*client_id_count + 1));
517 (*client_id)[k] = silc_id_payload_parse_id(tmp, len, NULL);
518 if ((*client_id)[k] == NULL) {
519 /* Cleanup all and fail */
520 for (i = 0; i < *client_id_count; i++)
521 silc_free((*client_id)[i]);
522 silc_free(*client_id);
523 silc_server_command_send_status_reply(
525 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
528 (*client_id_count)++;
535 /* Get the max count of reply messages allowed */
536 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
538 SILC_GET32_MSB(*count, tmp);
546 /* Resolve context used by both WHOIS and IDENTIFY commands */
548 SilcServerEntry router;
550 unsigned char **res_argv;
551 SilcUInt32 *res_argv_lens;
552 SilcUInt32 *res_argv_types;
554 } *SilcServerResolveContext;
557 silc_server_command_whois_check(SilcServerCommandContext cmd,
558 SilcClientEntry *clients,
559 SilcUInt32 clients_count)
561 SilcServer server = cmd->server;
562 SilcClientEntry entry;
563 SilcServerResolveContext resolve = NULL, r = NULL;
564 SilcUInt32 resolve_count = 0;
568 SILC_LOG_DEBUG(("Start"));
570 for (i = 0; i < clients_count; i++) {
575 if ((entry->nickname && entry->username && entry->userinfo) ||
576 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
580 /* If we are normal server, and we've not resolved this client from
581 router and it is global client, we'll check whether it is on some
582 channel. If not then we cannot be sure about its validity, and
583 we'll resolve it from router. */
584 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
585 entry->connection || silc_hash_table_count(entry->channels))
589 /* We need to resolve this entry since it is not complete */
591 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
592 /* The entry is being resolved (and we are not the resolver) so attach
593 to the command reply and we're done with this one. */
594 silc_server_command_pending(server, SILC_COMMAND_NONE,
595 entry->resolve_cmd_ident,
596 silc_server_command_whois,
597 silc_server_command_dup(cmd));
600 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
601 /* We've resolved this and it still is not ready. We'll return
602 and are that this will be handled again after it is resolved. */
603 for (i = 0; i < resolve_count; i++) {
604 for (k = 0; k < r->res_argc; k++)
605 silc_free(r->res_argv[k]);
606 silc_free(r->res_argv);
607 silc_free(r->res_argv_lens);
608 silc_free(r->res_argv_types);
613 /* We'll resolve this client */
617 for (k = 0; k < resolve_count; k++) {
618 if (resolve[k].router == entry->router) {
625 resolve = silc_realloc(resolve, sizeof(*resolve) *
626 (resolve_count + 1));
627 r = &resolve[resolve_count];
628 memset(r, 0, sizeof(*r));
629 r->router = entry->router;
630 r->ident = ++server->cmd_ident;
634 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
636 r->res_argv_lens = silc_realloc(r->res_argv_lens,
637 sizeof(*r->res_argv_lens) *
639 r->res_argv_types = silc_realloc(r->res_argv_types,
640 sizeof(*r->res_argv_types) *
642 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
643 r->res_argv[r->res_argc] = silc_calloc(idp->len,
644 sizeof(**r->res_argv));
645 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
646 r->res_argv_lens[r->res_argc] = idp->len;
647 r->res_argv_types[r->res_argc] = r->res_argc + 3;
649 silc_buffer_free(idp);
651 entry->resolve_cmd_ident = r->ident;
652 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
653 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
658 /* Do the resolving */
659 for (i = 0; i < resolve_count; i++) {
664 /* Send WHOIS request. We send WHOIS since we're doing the requesting
665 now anyway so make it a good one. */
666 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
667 r->res_argc, r->res_argv,
671 silc_server_packet_send(server, r->router->connection,
672 SILC_PACKET_COMMAND, cmd->packet->flags,
673 res_cmd->data, res_cmd->len, FALSE);
675 /* Reprocess this packet after received reply */
676 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
678 silc_server_command_whois,
679 silc_server_command_dup(cmd));
682 silc_buffer_free(res_cmd);
683 for (k = 0; k < r->res_argc; k++)
684 silc_free(r->res_argv[k]);
685 silc_free(r->res_argv);
686 silc_free(r->res_argv_lens);
687 silc_free(r->res_argv_types);
696 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
697 SilcClientEntry *clients,
698 SilcUInt32 clients_count,
700 const char *nickname,
701 SilcClientID **client_ids)
703 SilcServer server = cmd->server;
705 int i, k, len, valid_count;
706 SilcBuffer packet, idp, channels, umode_list = NULL;
707 SilcClientEntry entry;
709 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
710 char nh[256], uh[256];
711 unsigned char idle[4], mode[4];
712 unsigned char *fingerprint;
713 SilcSocketConnection hsock;
715 /* Process only valid clients and ignore those that are not registered. */
717 for (i = 0; i < clients_count; i++) {
718 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
725 /* No valid clients found, send error reply */
727 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
728 SILC_STATUS_ERR_NO_SUCH_NICK,
729 3, nickname, strlen(nickname));
730 } else if (client_ids && client_ids[0]) {
731 SilcBuffer idp = silc_id_payload_encode(client_ids[0], SILC_ID_CLIENT);
732 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
733 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
734 2, idp->data, idp->len);
735 silc_buffer_free(idp);
740 /* Start processing found clients. */
742 status = SILC_STATUS_LIST_START;
744 status = SILC_STATUS_OK;
746 for (i = 0, k = 0; i < clients_count; i++) {
752 status = SILC_STATUS_LIST_ITEM;
753 if (valid_count > 1 && k == valid_count - 1)
754 status = SILC_STATUS_LIST_END;
755 if (count && k - 1 == count)
756 status = SILC_STATUS_LIST_END;
758 /* Send WHOIS reply */
759 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
760 tmp = silc_argument_get_first_arg(cmd->args, NULL);
762 memset(uh, 0, sizeof(uh));
763 memset(nh, 0, sizeof(nh));
764 memset(idle, 0, sizeof(idle));
766 strncat(nh, entry->nickname, strlen(entry->nickname));
767 if (!strchr(entry->nickname, '@')) {
769 if (entry->servername) {
770 strncat(nh, entry->servername, strlen(entry->servername));
772 len = entry->router ? strlen(entry->router->server_name) :
773 strlen(server->server_name);
774 strncat(nh, entry->router ? entry->router->server_name :
775 server->server_name, len);
779 strncat(uh, entry->username, strlen(entry->username));
780 if (!strchr(entry->username, '@')) {
782 hsock = (SilcSocketConnection)entry->connection;
783 len = strlen(hsock->hostname);
784 strncat(uh, hsock->hostname, len);
787 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
788 channels = silc_server_get_client_channel_list(server, entry, FALSE,
791 channels = silc_server_get_client_channel_list(server, entry, TRUE,
794 if (entry->data.fingerprint[0] != 0 && entry->data.fingerprint[1] != 0)
795 fingerprint = entry->data.fingerprint;
799 SILC_PUT32_MSB(entry->mode, mode);
801 if (entry->connection) {
802 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
806 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
808 2, idp->data, idp->len,
812 strlen(entry->userinfo),
813 6, channels ? channels->data : NULL,
814 channels ? channels->len : 0,
818 fingerprint ? 20 : 0,
819 10, umode_list ? umode_list->data :
820 NULL, umode_list ? umode_list->len :
823 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
824 0, packet->data, packet->len, FALSE);
826 silc_buffer_free(packet);
827 silc_buffer_free(idp);
829 silc_buffer_free(channels);
831 silc_buffer_free(umode_list);
840 silc_server_command_whois_send_router(SilcServerCommandContext cmd)
842 SilcServer server = cmd->server;
844 SilcUInt16 old_ident;
846 old_ident = silc_command_get_ident(cmd->payload);
847 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
848 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
850 /* Send WHOIS command to our router */
851 silc_server_packet_send(server, (SilcSocketConnection)
852 server->router->connection,
853 SILC_PACKET_COMMAND, cmd->packet->flags,
854 tmpbuf->data, tmpbuf->len, TRUE);
856 /* Reprocess this packet after received reply from router */
857 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
858 silc_command_get_ident(cmd->payload),
859 silc_server_command_whois,
860 silc_server_command_dup(cmd));
862 silc_command_set_ident(cmd->payload, old_ident);
863 silc_buffer_free(tmpbuf);
867 silc_server_command_whois_process(SilcServerCommandContext cmd)
869 SilcServer server = cmd->server;
870 char *nick = NULL, *server_name = NULL;
872 SilcClientEntry *clients = NULL, entry;
873 SilcClientID **client_id = NULL;
874 SilcUInt32 client_id_count = 0, clients_count = 0;
876 bool check_global = FALSE;
878 /* Parse the whois request */
879 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
880 &nick, &server_name, &count,
884 /* Send the WHOIS request to the router only if it included nickname.
885 Since nicknames can be expanded into many clients we need to send it
886 to router. If the WHOIS included only client ID's we will check them
887 first locally since we just might have them. */
888 if (nick && !client_id_count && cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
889 server->server_type == SILC_SERVER && !cmd->pending &&
890 !server->standalone) {
891 silc_server_command_whois_send_router(cmd);
896 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
898 else if (server->server_type != SILC_SERVER)
901 /* Get all clients matching that ID or nickname from local list */
902 if (client_id_count) {
903 /* Check all Client ID's received in the command packet */
904 for (i = 0; i < client_id_count; i++) {
905 entry = silc_idlist_find_client_by_id(server->local_list,
906 client_id[i], TRUE, NULL);
907 if (!entry && check_global)
908 entry = silc_idlist_find_client_by_id(server->global_list,
909 client_id[i], TRUE, NULL);
911 clients = silc_realloc(clients, sizeof(*clients) *
912 (clients_count + 1));
913 clients[clients_count++] = entry;
915 /* If we are normal server and did not send the request first to router
916 do it now, since we do not have the Client ID information. */
917 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
918 server->server_type == SILC_SERVER && !cmd->pending &&
919 !server->standalone) {
920 silc_server_command_whois_send_router(cmd);
927 /* Find by nickname */
928 if (!silc_idlist_get_clients_by_hash(server->local_list,
929 nick, server->md5hash,
930 &clients, &clients_count))
931 silc_idlist_get_clients_by_nickname(server->local_list,
933 &clients, &clients_count);
935 if (!silc_idlist_get_clients_by_hash(server->global_list,
936 nick, server->md5hash,
937 &clients, &clients_count))
938 silc_idlist_get_clients_by_nickname(server->global_list,
940 &clients, &clients_count);
945 /* If we are normal server and did not send the request first to router
946 do it now, since we do not have the information. */
947 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
948 server->server_type == SILC_SERVER && !cmd->pending &&
949 !server->standalone) {
950 silc_server_command_whois_send_router(cmd);
955 /* Such client(s) really does not exist in the SILC network. */
956 if (!client_id_count) {
957 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
958 SILC_STATUS_ERR_NO_SUCH_NICK,
959 3, nick, strlen(nick));
961 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
962 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
963 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
964 2, idp->data, idp->len);
965 silc_buffer_free(idp);
970 /* Router always finds the client entry if it exists in the SILC network.
971 However, it might be incomplete entry and does not include all the
972 mandatory fields that WHOIS command reply requires. Check for these and
973 make query from the server who owns the client if some fields are
975 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
980 /* Send the command reply */
981 silc_server_command_whois_send_reply(cmd, clients, clients_count,
982 count, nick, client_id);
985 if (client_id_count) {
986 for (i = 0; i < client_id_count; i++)
987 silc_free(client_id[i]);
988 silc_free(client_id);
992 silc_free(server_name);
997 /* Server side of command WHOIS. Processes user's query and sends found
998 results as command replies back to the client. */
1000 SILC_SERVER_CMD_FUNC(whois)
1002 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1005 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 3328);
1007 ret = silc_server_command_whois_process(cmd);
1008 silc_server_command_free(cmd);
1011 /******************************************************************************
1015 ******************************************************************************/
1018 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
1026 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1028 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
1029 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1033 /* Get the nickname@server string and parse it. */
1034 silc_parse_userfqdn(tmp, nickname, server_name);
1036 /* Get the max count of reply messages allowed */
1037 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1039 SILC_GET32_MSB(*count, tmp);
1048 silc_server_command_whowas_check(SilcServerCommandContext cmd,
1049 SilcClientEntry *clients,
1050 SilcUInt32 clients_count)
1052 SilcServer server = cmd->server;
1054 SilcClientEntry entry;
1056 for (i = 0; i < clients_count; i++) {
1059 if (!entry->nickname || !entry->username) {
1061 SilcUInt16 old_ident;
1066 old_ident = silc_command_get_ident(cmd->payload);
1067 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1068 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1070 /* Send WHOWAS command */
1071 silc_server_packet_send(server, entry->router->connection,
1072 SILC_PACKET_COMMAND, cmd->packet->flags,
1073 tmpbuf->data, tmpbuf->len, TRUE);
1075 /* Reprocess this packet after received reply */
1076 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1077 silc_command_get_ident(cmd->payload),
1078 silc_server_command_whowas,
1079 silc_server_command_dup(cmd));
1080 cmd->pending = TRUE;
1081 silc_command_set_ident(cmd->payload, old_ident);
1083 silc_buffer_free(tmpbuf);
1092 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1093 SilcClientEntry *clients,
1094 SilcUInt32 clients_count)
1096 SilcServer server = cmd->server;
1098 int i, k, count = 0, len;
1099 SilcBuffer packet, idp;
1100 SilcClientEntry entry = NULL;
1102 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1103 char nh[256], uh[256];
1106 status = SILC_STATUS_OK;
1108 /* Process only entries that are not registered anymore. */
1110 for (i = 0; i < clients_count; i++) {
1111 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1118 /* No valid entries found at all, just send error */
1121 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1123 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1124 SILC_STATUS_ERR_NO_SUCH_NICK,
1125 3, tmp, strlen(tmp));
1129 if (valid_count > 1)
1130 status = SILC_STATUS_LIST_START;
1132 for (i = 0, k = 0; i < clients_count; i++) {
1138 status = SILC_STATUS_LIST_ITEM;
1139 if (valid_count > 1 && k == valid_count - 1)
1140 status = SILC_STATUS_LIST_END;
1141 if (count && k - 1 == count)
1142 status = SILC_STATUS_LIST_END;
1143 if (count && k - 1 > count)
1146 /* Send WHOWAS reply */
1147 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1148 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1149 memset(uh, 0, sizeof(uh));
1150 memset(nh, 0, sizeof(nh));
1152 strncat(nh, entry->nickname, strlen(entry->nickname));
1153 if (!strchr(entry->nickname, '@')) {
1154 strncat(nh, "@", 1);
1155 if (entry->servername) {
1156 strncat(nh, entry->servername, strlen(entry->servername));
1158 len = entry->router ? strlen(entry->router->server_name) :
1159 strlen(server->server_name);
1160 strncat(nh, entry->router ? entry->router->server_name :
1161 server->server_name, len);
1165 strncat(uh, entry->username, strlen(entry->username));
1166 if (!strchr(entry->username, '@')) {
1167 strncat(uh, "@", 1);
1168 strcat(uh, "*private*");
1172 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1173 status, 0, ident, 4,
1174 2, idp->data, idp->len,
1179 strlen(entry->userinfo) : 0);
1180 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1181 0, packet->data, packet->len, FALSE);
1183 silc_buffer_free(packet);
1184 silc_buffer_free(idp);
1191 silc_server_command_whowas_process(SilcServerCommandContext cmd)
1193 SilcServer server = cmd->server;
1194 char *nick = NULL, *server_name = NULL;
1196 SilcClientEntry *clients = NULL;
1197 SilcUInt32 clients_count = 0;
1199 bool check_global = FALSE;
1201 /* Protocol dictates that we must always send the received WHOWAS request
1202 to our router if we are normal server, so let's do it now unless we
1203 are standalone. We will not send any replies to the client until we
1204 have received reply from the router. */
1205 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1206 server->server_type == SILC_SERVER && !cmd->pending &&
1207 !server->standalone) {
1209 SilcUInt16 old_ident;
1211 old_ident = silc_command_get_ident(cmd->payload);
1212 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1213 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1215 /* Send WHOWAS command to our router */
1216 silc_server_packet_send(server, (SilcSocketConnection)
1217 server->router->connection,
1218 SILC_PACKET_COMMAND, cmd->packet->flags,
1219 tmpbuf->data, tmpbuf->len, TRUE);
1221 /* Reprocess this packet after received reply from router */
1222 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1223 silc_command_get_ident(cmd->payload),
1224 silc_server_command_whowas,
1225 silc_server_command_dup(cmd));
1226 cmd->pending = TRUE;
1227 silc_command_set_ident(cmd->payload, old_ident);
1229 silc_buffer_free(tmpbuf);
1234 /* We are ready to process the command request. Let's search for the
1235 requested client and send reply to the requesting client. */
1237 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1238 check_global = TRUE;
1239 else if (server->server_type != SILC_SERVER)
1240 check_global = TRUE;
1242 /* Parse the whowas request */
1243 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1246 /* Get all clients matching that nickname from local list */
1247 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1249 &clients, &clients_count))
1250 silc_idlist_get_clients_by_hash(server->local_list,
1251 nick, server->md5hash,
1252 &clients, &clients_count);
1254 /* Check global list as well */
1256 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1258 &clients, &clients_count))
1259 silc_idlist_get_clients_by_hash(server->global_list,
1260 nick, server->md5hash,
1261 &clients, &clients_count);
1265 /* Such a client really does not exist in the SILC network. */
1266 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1267 SILC_STATUS_ERR_NO_SUCH_NICK,
1268 3, nick, strlen(nick));
1272 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1277 /* Send the command reply to the client */
1278 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1283 silc_free(server_name);
1287 /* Server side of command WHOWAS. */
1289 SILC_SERVER_CMD_FUNC(whowas)
1291 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1294 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1296 ret = silc_server_command_whowas_process(cmd);
1297 silc_server_command_free(cmd);
1300 /******************************************************************************
1304 ******************************************************************************/
1307 silc_server_command_identify_send_router(SilcServerCommandContext cmd)
1309 SilcServer server = cmd->server;
1311 SilcUInt16 old_ident;
1313 old_ident = silc_command_get_ident(cmd->payload);
1314 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1315 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1317 /* Send IDENTIFY command to our router */
1318 silc_server_packet_send(server, (SilcSocketConnection)
1319 server->router->connection,
1320 SILC_PACKET_COMMAND, cmd->packet->flags,
1321 tmpbuf->data, tmpbuf->len, TRUE);
1323 /* Reprocess this packet after received reply from router */
1324 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1325 silc_command_get_ident(cmd->payload),
1326 silc_server_command_identify,
1327 silc_server_command_dup(cmd));
1328 cmd->pending = TRUE;
1329 silc_command_set_ident(cmd->payload, old_ident);
1330 silc_buffer_free(tmpbuf);
1334 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1335 SilcClientEntry **clients,
1336 SilcUInt32 *clients_count,
1337 SilcServerEntry **servers,
1338 SilcUInt32 *servers_count,
1339 SilcChannelEntry **channels,
1340 SilcUInt32 *channels_count,
1343 SilcServer server = cmd->server;
1346 SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
1348 bool check_global = FALSE;
1353 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1354 check_global = TRUE;
1355 else if (server->server_type != SILC_SERVER)
1356 check_global = TRUE;
1358 /* If ID Payload is in the command it must be used instead of names */
1359 tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1361 /* No ID, get the names. */
1363 /* If we are normal server and have not resolved information from
1364 router yet, do so now. */
1365 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1366 server->server_type == SILC_SERVER && !cmd->pending &&
1367 !server->standalone) {
1368 silc_server_command_identify_send_router(cmd);
1372 /* Try to get nickname@server. */
1373 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1376 char *nick_server = NULL;
1378 silc_parse_userfqdn(tmp, &nick, &nick_server);
1380 if (!silc_idlist_get_clients_by_hash(server->local_list,
1381 nick, server->md5hash,
1382 clients, clients_count))
1383 silc_idlist_get_clients_by_nickname(server->local_list,
1385 clients, clients_count);
1387 if (!silc_idlist_get_clients_by_hash(server->global_list,
1388 nick, server->md5hash,
1389 clients, clients_count))
1390 silc_idlist_get_clients_by_nickname(server->global_list,
1392 clients, clients_count);
1396 silc_free(nick_server);
1399 /* the nickname does not exist, send error reply */
1400 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1401 SILC_STATUS_ERR_NO_SUCH_NICK,
1402 3, tmp, strlen(tmp));
1407 /* Try to get server name */
1408 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1410 entry = silc_idlist_find_server_by_name(server->local_list,
1412 if (!entry && check_global)
1413 entry = silc_idlist_find_server_by_name(server->global_list,
1416 *servers = silc_realloc(*servers, sizeof(**servers) *
1417 (*servers_count + 1));
1418 (*servers)[(*servers_count)++] = entry;
1422 /* the server does not exist, send error reply */
1423 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1424 SILC_STATUS_ERR_NO_SUCH_SERVER,
1425 3, tmp, strlen(tmp));
1430 /* Try to get channel name */
1431 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1433 entry = silc_idlist_find_channel_by_name(server->local_list,
1435 if (!entry && check_global)
1436 entry = silc_idlist_find_channel_by_name(server->global_list,
1439 *channels = silc_realloc(*channels, sizeof(**channels) *
1440 (*channels_count + 1));
1441 (*channels)[(*channels_count)++] = entry;
1445 /* The channel does not exist, send error reply */
1446 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1447 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1448 3, tmp, strlen(tmp));
1453 if (!(*clients) && !(*servers) && !(*channels)) {
1454 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1455 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1459 /* Command includes ID, we must use that. Also check whether the command
1460 has more than one ID set - take them all. */
1462 /* Take all ID's from the command packet */
1463 for (i = 0; i < argc; i++) {
1466 tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
1470 idp = silc_id_payload_parse(tmp, len);
1472 silc_free(*clients);
1473 silc_free(*servers);
1474 silc_free(*channels);
1475 silc_server_command_send_status_reply(
1476 cmd, SILC_COMMAND_IDENTIFY,
1477 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1481 id = silc_id_payload_get_id(idp);
1483 switch (silc_id_payload_get_type(idp)) {
1485 case SILC_ID_CLIENT:
1486 entry = (void *)silc_idlist_find_client_by_id(server->local_list,
1488 if (!entry && check_global)
1489 entry = (void *)silc_idlist_find_client_by_id(server->global_list,
1492 *clients = silc_realloc(*clients, sizeof(**clients) *
1493 (*clients_count + 1));
1494 (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
1496 /* If we are normal server and have not resolved information from
1497 router yet, do so now. */
1498 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1499 server->server_type == SILC_SERVER && !cmd->pending &&
1500 !server->standalone) {
1501 silc_server_command_identify_send_router(cmd);
1502 silc_free(*clients);
1503 silc_free(*servers);
1504 silc_free(*channels);
1507 silc_server_command_send_status_data(
1508 cmd, SILC_COMMAND_IDENTIFY,
1509 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1517 case SILC_ID_SERVER:
1518 entry = (void *)silc_idlist_find_server_by_id(server->local_list,
1520 if (!entry && check_global)
1521 entry = (void *)silc_idlist_find_server_by_id(server->global_list,
1524 *servers = silc_realloc(*servers, sizeof(**servers) *
1525 (*servers_count + 1));
1526 (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
1528 /* If we are normal server and have not resolved information from
1529 router yet, do so now. */
1530 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1531 server->server_type == SILC_SERVER && !cmd->pending &&
1532 !server->standalone) {
1533 silc_server_command_identify_send_router(cmd);
1534 silc_free(*clients);
1535 silc_free(*servers);
1536 silc_free(*channels);
1539 silc_server_command_send_status_data(
1540 cmd, SILC_COMMAND_IDENTIFY,
1541 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
1548 case SILC_ID_CHANNEL:
1549 entry = (void *)silc_idlist_find_channel_by_id(server->local_list,
1551 if (!entry && check_global)
1552 entry = (void *)silc_idlist_find_channel_by_id(server->global_list,
1555 *channels = silc_realloc(*channels, sizeof(**channels) *
1556 (*channels_count + 1));
1557 (*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
1559 /* If we are normal server and have not resolved information from
1560 router yet, do so now. */
1561 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1562 server->server_type == SILC_SERVER && !cmd->pending &&
1563 !server->standalone) {
1564 silc_server_command_identify_send_router(cmd);
1565 silc_free(*clients);
1566 silc_free(*servers);
1567 silc_free(*channels);
1570 silc_server_command_send_status_data(
1571 cmd, SILC_COMMAND_IDENTIFY,
1572 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
1585 silc_free(*clients);
1586 silc_free(*servers);
1587 silc_free(*channels);
1591 /* Get the max count of reply messages allowed */
1592 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1594 SILC_GET32_MSB(*count, tmp);
1602 /* Checks that all mandatory fields in client entry are present. If not
1603 then send WHOIS request to the server who owns the client. We use
1604 WHOIS because we want to get as much information as possible at once. */
1607 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1608 SilcClientEntry *clients,
1609 SilcUInt32 clients_count)
1611 SilcServer server = cmd->server;
1612 SilcClientEntry entry;
1613 SilcServerResolveContext resolve = NULL, r = NULL;
1614 SilcUInt32 resolve_count = 0;
1618 for (i = 0; i < clients_count; i++) {
1623 if (entry->nickname ||
1624 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1628 /* If we are normal server, and we've not resolved this client from
1629 router and it is global client, we'll check whether it is on some
1630 channel. If not then we cannot be sure about its validity, and
1631 we'll resolve it from router. */
1632 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
1633 entry->connection || silc_hash_table_count(entry->channels))
1637 /* We need to resolve this entry since it is not complete */
1639 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1640 /* The entry is being resolved (and we are not the resolver) so attach
1641 to the command reply and we're done with this one. */
1642 silc_server_command_pending(server, SILC_COMMAND_NONE,
1643 entry->resolve_cmd_ident,
1644 silc_server_command_identify,
1645 silc_server_command_dup(cmd));
1648 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1649 /* We've resolved this and it still is not ready. We'll return
1650 and are that this will be handled again after it is resolved. */
1651 for (i = 0; i < resolve_count; i++) {
1652 for (k = 0; k < r->res_argc; k++)
1653 silc_free(r->res_argv[k]);
1654 silc_free(r->res_argv);
1655 silc_free(r->res_argv_lens);
1656 silc_free(r->res_argv_types);
1661 /* We'll resolve this client */
1665 for (k = 0; k < resolve_count; k++) {
1666 if (resolve[k].router == entry->router) {
1673 resolve = silc_realloc(resolve, sizeof(*resolve) *
1674 (resolve_count + 1));
1675 r = &resolve[resolve_count];
1676 memset(r, 0, sizeof(*r));
1677 r->router = entry->router;
1678 r->ident = ++server->cmd_ident;
1682 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1684 r->res_argv_lens = silc_realloc(r->res_argv_lens,
1685 sizeof(*r->res_argv_lens) *
1687 r->res_argv_types = silc_realloc(r->res_argv_types,
1688 sizeof(*r->res_argv_types) *
1690 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1691 r->res_argv[r->res_argc] = silc_calloc(idp->len,
1692 sizeof(**r->res_argv));
1693 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1694 r->res_argv_lens[r->res_argc] = idp->len;
1695 r->res_argv_types[r->res_argc] = r->res_argc + 3;
1697 silc_buffer_free(idp);
1699 entry->resolve_cmd_ident = r->ident;
1700 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1701 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1706 /* Do the resolving */
1707 for (i = 0; i < resolve_count; i++) {
1712 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1713 now anyway so make it a good one. */
1714 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1715 r->res_argc, r->res_argv,
1719 silc_server_packet_send(server, r->router->connection,
1720 SILC_PACKET_COMMAND, cmd->packet->flags,
1721 res_cmd->data, res_cmd->len, FALSE);
1723 /* Reprocess this packet after received reply */
1724 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1726 silc_server_command_identify,
1727 silc_server_command_dup(cmd));
1728 cmd->pending = TRUE;
1730 silc_buffer_free(res_cmd);
1731 for (k = 0; k < r->res_argc; k++)
1732 silc_free(r->res_argv[k]);
1733 silc_free(r->res_argv);
1734 silc_free(r->res_argv_lens);
1735 silc_free(r->res_argv_types);
1744 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1745 SilcClientEntry *clients,
1746 SilcUInt32 clients_count,
1747 SilcServerEntry *servers,
1748 SilcUInt32 servers_count,
1749 SilcChannelEntry *channels,
1750 SilcUInt32 channels_count,
1753 SilcServer server = cmd->server;
1754 int i, k, len, valid_count;
1755 SilcBuffer packet, idp;
1757 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1758 char nh[256], uh[256];
1759 SilcSocketConnection hsock;
1761 status = SILC_STATUS_OK;
1764 SilcClientEntry entry;
1766 /* Process only valid entries. */
1768 for (i = 0; i < clients_count; i++) {
1769 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1776 /* No valid entries found at all, just send error */
1779 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1781 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1782 SILC_STATUS_ERR_NO_SUCH_NICK,
1783 3, tmp, strlen(tmp));
1785 tmp = silc_argument_get_arg_type(cmd->args, 5, (SilcUInt32 *)&len);
1786 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1787 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1793 /* Process all valid client entries and send command replies */
1795 if (valid_count > 1)
1796 status = SILC_STATUS_LIST_START;
1798 for (i = 0, k = 0; i < clients_count; i++) {
1804 status = SILC_STATUS_LIST_ITEM;
1805 if (valid_count > 1 && k == valid_count - 1
1806 && !servers_count && !channels_count)
1807 status = SILC_STATUS_LIST_END;
1808 if (count && k - 1 == count)
1809 status = SILC_STATUS_LIST_END;
1810 if (count && k - 1 > count)
1813 /* Send IDENTIFY reply */
1815 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1816 memset(uh, 0, sizeof(uh));
1817 memset(nh, 0, sizeof(nh));
1818 strncat(nh, entry->nickname, strlen(entry->nickname));
1819 if (!strchr(entry->nickname, '@')) {
1820 strncat(nh, "@", 1);
1821 if (entry->servername) {
1822 strncat(nh, entry->servername, strlen(entry->servername));
1824 len = entry->router ? strlen(entry->router->server_name) :
1825 strlen(server->server_name);
1826 strncat(nh, entry->router ? entry->router->server_name :
1827 server->server_name, len);
1831 if (!entry->username) {
1832 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1833 status, 0, ident, 2,
1834 2, idp->data, idp->len,
1837 strncat(uh, entry->username, strlen(entry->username));
1838 if (!strchr(entry->username, '@')) {
1839 strncat(uh, "@", 1);
1840 hsock = (SilcSocketConnection)entry->connection;
1841 len = strlen(hsock->hostname);
1842 strncat(uh, hsock->hostname, len);
1845 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1846 status, 0, ident, 3,
1847 2, idp->data, idp->len,
1852 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1853 0, packet->data, packet->len, FALSE);
1855 silc_buffer_free(packet);
1856 silc_buffer_free(idp);
1863 SilcServerEntry entry;
1865 if (status == SILC_STATUS_OK && servers_count > 1)
1866 status = SILC_STATUS_LIST_START;
1868 for (i = 0, k = 0; i < servers_count; i++) {
1872 status = SILC_STATUS_LIST_ITEM;
1873 if (servers_count > 1 && k == servers_count - 1 && !channels_count)
1874 status = SILC_STATUS_LIST_END;
1875 if (count && k - 1 == count)
1876 status = SILC_STATUS_LIST_END;
1877 if (count && k - 1 > count)
1880 /* Send IDENTIFY reply */
1881 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1883 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1884 status, 0, ident, 2,
1885 2, idp->data, idp->len,
1886 3, entry->server_name,
1887 entry->server_name ?
1888 strlen(entry->server_name) : 0);
1889 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1890 0, packet->data, packet->len, FALSE);
1892 silc_buffer_free(packet);
1893 silc_buffer_free(idp);
1900 SilcChannelEntry entry;
1902 if (status == SILC_STATUS_OK && channels_count > 1)
1903 status = SILC_STATUS_LIST_START;
1905 for (i = 0, k = 0; i < channels_count; i++) {
1906 entry = channels[i];
1909 status = SILC_STATUS_LIST_ITEM;
1910 if (channels_count > 1 && k == channels_count - 1)
1911 status = SILC_STATUS_LIST_END;
1912 if (count && k - 1 == count)
1913 status = SILC_STATUS_LIST_END;
1914 if (count && k - 1 > count)
1917 /* Send IDENTIFY reply */
1918 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1920 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1921 status, 0, ident, 2,
1922 2, idp->data, idp->len,
1923 3, entry->channel_name,
1924 entry->channel_name ?
1925 strlen(entry->channel_name): 0);
1926 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1927 0, packet->data, packet->len, FALSE);
1929 silc_buffer_free(packet);
1930 silc_buffer_free(idp);
1938 silc_server_command_identify_process(SilcServerCommandContext cmd)
1940 SilcUInt32 count = 0;
1942 SilcClientEntry *clients = NULL;
1943 SilcServerEntry *servers = NULL;
1944 SilcChannelEntry *channels = NULL;
1945 SilcUInt32 clients_count = 0, servers_count = 0, channels_count = 0;
1947 /* Parse the IDENTIFY request */
1948 ret = silc_server_command_identify_parse(cmd,
1949 &clients, &clients_count,
1950 &servers, &servers_count,
1951 &channels, &channels_count,
1957 /* Check that all mandatory fields are present and request those data
1958 from the server who owns the client if necessary. */
1959 if (clients && !silc_server_command_identify_check_client(cmd, clients,
1965 /* Send the command reply to the client */
1966 silc_server_command_identify_send_reply(cmd,
1967 clients, clients_count,
1968 servers, servers_count,
1969 channels, channels_count,
1975 silc_free(channels);
1979 SILC_SERVER_CMD_FUNC(identify)
1981 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1984 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1986 ret = silc_server_command_identify_process(cmd);
1987 silc_server_command_free(cmd);
1990 /* Server side of command NICK. Sets nickname for user. Setting
1991 nickname causes generation of a new client ID for the client. The
1992 new client ID is sent to the client after changing the nickname. */
1994 SILC_SERVER_CMD_FUNC(nick)
1996 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1997 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1998 SilcServer server = cmd->server;
1999 SilcBuffer packet, nidp, oidp = NULL;
2000 SilcClientID *new_id;
2001 SilcUInt32 nick_len;
2003 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2006 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2009 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
2011 /* Check nickname */
2012 nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
2015 if (silc_server_name_bad_chars(nick, nick_len) == TRUE) {
2016 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2017 SILC_STATUS_ERR_BAD_NICKNAME);
2021 /* Check for same nickname */
2022 if (!strcmp(client->nickname, nick)) {
2023 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2027 /* Create new Client ID */
2028 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
2030 cmd->server->md5hash, nick,
2034 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2035 SILC_STATUS_ERR_BAD_NICKNAME);
2038 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2041 /* Send notify about nickname change to our router. We send the new
2042 ID and ask to replace it with the old one. If we are router the
2043 packet is broadcasted. Send NICK_CHANGE notify. */
2044 if (!server->standalone)
2045 silc_server_send_notify_nick_change(server, server->router->connection,
2046 server->server_type == SILC_SERVER ?
2047 FALSE : TRUE, client->id,
2050 /* Check if anyone is watching the old nickname */
2051 if (server->server_type == SILC_ROUTER)
2052 silc_server_check_watcher_list(server, client, nick,
2053 SILC_NOTIFY_TYPE_NICK_CHANGE);
2055 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2057 /* Remove old cache entry */
2058 silc_idcache_del_by_context(server->local_list->clients, client);
2060 silc_free(client->id);
2061 client->id = new_id;
2063 silc_free(client->nickname);
2064 client->nickname = strdup(nick);
2066 /* Update client cache */
2067 silc_idcache_add(server->local_list->clients, client->nickname,
2068 client->id, (void *)client, 0, NULL);
2070 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2072 /* Send NICK_CHANGE notify to the client's channels */
2073 silc_server_send_notify_on_channels(server, NULL, client,
2074 SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
2075 oidp->data, oidp->len,
2076 nidp->data, nidp->len,
2078 strlen(client->nickname));
2080 /* Check if anyone is watching the new nickname */
2081 if (server->server_type == SILC_ROUTER)
2082 silc_server_check_watcher_list(server, client, NULL,
2083 SILC_NOTIFY_TYPE_NICK_CHANGE);
2086 /* Send the new Client ID as reply command back to client */
2087 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
2088 SILC_STATUS_OK, 0, ident, 1,
2089 2, nidp->data, nidp->len);
2090 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2091 0, packet->data, packet->len, FALSE);
2093 silc_buffer_free(packet);
2094 silc_buffer_free(nidp);
2096 silc_buffer_free(oidp);
2099 silc_server_command_free(cmd);
2102 /* Sends the LIST command reply */
2105 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2106 SilcChannelEntry *lch,
2107 SilcUInt32 lch_count,
2108 SilcChannelEntry *gch,
2109 SilcUInt32 gch_count)
2112 SilcBuffer packet, idp;
2113 SilcChannelEntry entry;
2115 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2117 unsigned char usercount[4];
2119 int valid_lcount = 0, valid_rcount = 0;
2121 for (i = 0; i < lch_count; i++) {
2122 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2127 for (i = 0; i < gch_count; i++) {
2128 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2134 status = SILC_STATUS_OK;
2135 if ((lch_count + gch_count) > 1)
2136 status = SILC_STATUS_LIST_START;
2139 for (i = 0, k = 0; i < lch_count; i++) {
2145 status = SILC_STATUS_LIST_ITEM;
2146 if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
2147 status = SILC_STATUS_LIST_END;
2149 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2151 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2152 topic = "*private*";
2153 memset(usercount, 0, sizeof(usercount));
2155 topic = entry->topic;
2156 users = silc_hash_table_count(entry->user_list);
2157 SILC_PUT32_MSB(users, usercount);
2160 /* Send the reply */
2162 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2163 status, 0, ident, 4,
2164 2, idp->data, idp->len,
2165 3, entry->channel_name,
2166 strlen(entry->channel_name),
2167 4, topic, topic ? strlen(topic) : 0,
2169 silc_server_packet_send(cmd->server, cmd->sock,
2170 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2171 packet->len, FALSE);
2172 silc_buffer_free(packet);
2173 silc_buffer_free(idp);
2178 for (i = 0, k = 0; i < gch_count; i++) {
2184 status = SILC_STATUS_LIST_ITEM;
2185 if (valid_rcount > 1 && k == valid_rcount - 1)
2186 status = SILC_STATUS_LIST_END;
2188 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2190 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2191 topic = "*private*";
2192 memset(usercount, 0, sizeof(usercount));
2194 topic = entry->topic;
2195 users = entry->user_count;
2196 SILC_PUT32_MSB(users, usercount);
2199 /* Send the reply */
2201 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2202 status, 0, ident, 4,
2203 2, idp->data, idp->len,
2204 3, entry->channel_name,
2205 strlen(entry->channel_name),
2206 4, topic, topic ? strlen(topic) : 0,
2208 silc_server_packet_send(cmd->server, cmd->sock,
2209 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2210 packet->len, FALSE);
2211 silc_buffer_free(packet);
2212 silc_buffer_free(idp);
2217 /* Server side of LIST command. This lists the channel of the requested
2218 server. Secret channels are not listed. */
2220 SILC_SERVER_CMD_FUNC(list)
2222 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2223 SilcServer server = cmd->server;
2224 SilcChannelID *channel_id = NULL;
2227 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2228 SilcUInt32 lch_count = 0, gch_count = 0;
2230 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2232 /* If we are normal server, send the command to router, since we
2233 want to know all channels in the network. */
2234 if (!cmd->pending && server->server_type == SILC_SERVER &&
2235 !server->standalone) {
2237 SilcUInt16 old_ident;
2239 old_ident = silc_command_get_ident(cmd->payload);
2240 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2241 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2242 silc_server_packet_send(server, server->router->connection,
2243 SILC_PACKET_COMMAND, cmd->packet->flags,
2244 tmpbuf->data, tmpbuf->len, TRUE);
2246 /* Reprocess this packet after received reply from router */
2247 silc_server_command_pending(server, SILC_COMMAND_LIST,
2248 silc_command_get_ident(cmd->payload),
2249 silc_server_command_list,
2250 silc_server_command_dup(cmd));
2251 cmd->pending = TRUE;
2252 silc_command_set_ident(cmd->payload, old_ident);
2253 silc_buffer_free(tmpbuf);
2257 /* Get Channel ID */
2258 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2260 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2262 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2263 SILC_STATUS_ERR_NO_CHANNEL_ID);
2268 /* Get the channels from local list */
2269 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2272 /* Get the channels from global list */
2273 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2276 /* Send the reply */
2277 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2278 gchannels, gch_count);
2280 silc_free(lchannels);
2281 silc_free(gchannels);
2284 silc_server_command_free(cmd);
2287 /* Server side of TOPIC command. Sets topic for channel and/or returns
2288 current topic to client. */
2290 SILC_SERVER_CMD_FUNC(topic)
2292 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2293 SilcServer server = cmd->server;
2294 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2295 SilcChannelID *channel_id;
2296 SilcChannelEntry channel;
2297 SilcChannelClientEntry chl;
2298 SilcBuffer packet, idp;
2300 SilcUInt32 argc, tmp_len;
2301 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2303 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2305 argc = silc_argument_get_arg_num(cmd->args);
2307 /* Get Channel ID */
2308 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2310 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2311 SILC_STATUS_ERR_NO_CHANNEL_ID);
2314 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2316 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2317 SILC_STATUS_ERR_NO_CHANNEL_ID);
2321 /* Check whether the channel exists */
2322 channel = silc_idlist_find_channel_by_id(server->local_list,
2325 channel = silc_idlist_find_channel_by_id(server->global_list,
2328 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2329 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2336 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2338 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2339 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2343 if (strlen(tmp) > 256) {
2344 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2345 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2349 /* See whether the client is on channel and has rights to change topic */
2350 if (!silc_server_client_on_channel(client, channel, &chl)) {
2351 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2352 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2356 if (channel->mode & SILC_CHANNEL_MODE_TOPIC &&
2357 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
2358 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
2359 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2360 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2364 /* Set the topic for channel */
2365 silc_free(channel->topic);
2366 channel->topic = strdup(tmp);
2368 /* Send TOPIC_SET notify type to the network */
2369 if (!server->standalone)
2370 silc_server_send_notify_topic_set(server, server->router->connection,
2371 server->server_type == SILC_ROUTER ?
2372 TRUE : FALSE, channel,
2373 client->id, SILC_ID_CLIENT,
2376 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2378 /* Send notify about topic change to all clients on the channel */
2379 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2380 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2381 idp->data, idp->len,
2382 channel->topic, strlen(channel->topic));
2383 silc_buffer_free(idp);
2386 /* Send the topic to client as reply packet */
2387 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2388 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2389 SILC_STATUS_OK, 0, ident, 2,
2390 2, idp->data, idp->len,
2393 strlen(channel->topic) : 0);
2394 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2395 0, packet->data, packet->len, FALSE);
2397 silc_buffer_free(packet);
2398 silc_buffer_free(idp);
2399 silc_free(channel_id);
2402 silc_server_command_free(cmd);
2405 /* Server side of INVITE command. Invites some client to join some channel.
2406 This command is also used to manage the invite list of the channel. */
2408 SILC_SERVER_CMD_FUNC(invite)
2410 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2411 SilcServer server = cmd->server;
2412 SilcSocketConnection sock = cmd->sock, dest_sock;
2413 SilcChannelClientEntry chl;
2414 SilcClientEntry sender, dest;
2415 SilcClientID *dest_id = NULL;
2416 SilcChannelEntry channel;
2417 SilcChannelID *channel_id = NULL;
2418 SilcIDListData idata;
2419 SilcBuffer idp, idp2, packet;
2420 unsigned char *tmp, *add, *del;
2422 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2424 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2426 /* Get Channel ID */
2427 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2429 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2430 SILC_STATUS_ERR_NO_CHANNEL_ID);
2433 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
2435 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2436 SILC_STATUS_ERR_NO_CHANNEL_ID);
2440 /* Get the channel entry */
2441 channel = silc_idlist_find_channel_by_id(server->local_list,
2444 channel = silc_idlist_find_channel_by_id(server->global_list,
2447 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2448 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2453 /* Check whether the sender of this command is on the channel. */
2454 sender = (SilcClientEntry)sock->user_data;
2455 if (!silc_server_client_on_channel(sender, channel, &chl)) {
2456 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2457 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2461 /* Check whether the channel is invite-only channel. If yes then the
2462 sender of this command must be at least channel operator. */
2463 if (channel->mode & SILC_CHANNEL_MODE_INVITE &&
2464 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
2465 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
2466 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2467 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2471 /* Get destination client ID */
2472 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2477 dest_id = silc_id_payload_parse_id(tmp, len, NULL);
2479 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2480 SILC_STATUS_ERR_NO_CLIENT_ID);
2484 /* Get the client entry */
2485 dest = silc_server_get_client_resolve(server, dest_id, FALSE, &resolve);
2487 if (server->server_type != SILC_SERVER || !resolve) {
2488 silc_server_command_send_status_reply(
2489 cmd, SILC_COMMAND_INVITE,
2490 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2494 /* The client info is being resolved. Reprocess this packet after
2495 receiving the reply to the query. */
2496 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2498 silc_server_command_invite,
2499 silc_server_command_dup(cmd));
2500 cmd->pending = TRUE;
2501 silc_free(channel_id);
2506 /* Check whether the requested client is already on the channel. */
2507 if (silc_server_client_on_channel(dest, channel, NULL)) {
2508 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2509 SILC_STATUS_ERR_USER_ON_CHANNEL);
2513 /* Get route to the client */
2514 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id,
2517 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2518 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2522 memset(invite, 0, sizeof(invite));
2523 strncat(invite, dest->nickname, strlen(dest->nickname));
2524 strncat(invite, "!", 1);
2525 strncat(invite, dest->username, strlen(dest->username));
2526 if (!strchr(dest->username, '@')) {
2527 strncat(invite, "@", 1);
2528 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2531 len = strlen(invite);
2532 if (!channel->invite_list)
2533 channel->invite_list = silc_calloc(len + 2,
2534 sizeof(*channel->invite_list));
2536 channel->invite_list = silc_realloc(channel->invite_list,
2537 sizeof(*channel->invite_list) *
2539 strlen(channel->invite_list) + 2));
2540 strncat(channel->invite_list, invite, len);
2541 strncat(channel->invite_list, ",", 1);
2543 /* Send notify to the client that is invited to the channel */
2544 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2545 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2546 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2548 SILC_NOTIFY_TYPE_INVITE, 3,
2549 idp->data, idp->len,
2550 channel->channel_name,
2551 strlen(channel->channel_name),
2552 idp2->data, idp2->len);
2553 silc_buffer_free(idp);
2554 silc_buffer_free(idp2);
2557 /* Add the client to the invite list of the channel */
2558 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2560 if (!channel->invite_list)
2561 channel->invite_list = silc_calloc(len + 2,
2562 sizeof(*channel->invite_list));
2564 channel->invite_list = silc_realloc(channel->invite_list,
2565 sizeof(*channel->invite_list) *
2567 strlen(channel->invite_list) + 2));
2568 if (add[len - 1] == ',')
2569 add[len - 1] = '\0';
2571 strncat(channel->invite_list, add, len);
2572 strncat(channel->invite_list, ",", 1);
2575 /* Get the invite to be removed and remove it from the list */
2576 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2577 if (del && channel->invite_list) {
2578 char *start, *end, *n;
2580 if (!strncmp(channel->invite_list, del,
2581 strlen(channel->invite_list) - 1)) {
2582 silc_free(channel->invite_list);
2583 channel->invite_list = NULL;
2585 start = strstr(channel->invite_list, del);
2586 if (start && strlen(start) >= len) {
2588 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2589 strncat(n, channel->invite_list, start - channel->invite_list);
2590 strncat(n, end + 1, ((channel->invite_list +
2591 strlen(channel->invite_list)) - end) - 1);
2592 silc_free(channel->invite_list);
2593 channel->invite_list = n;
2598 /* Send notify to the primary router */
2599 if (!server->standalone)
2600 silc_server_send_notify_invite(server, server->router->connection,
2601 server->server_type == SILC_ROUTER ?
2602 TRUE : FALSE, channel,
2603 sender->id, add, del);
2605 /* Send command reply */
2606 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2610 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2611 SILC_STATUS_OK, 0, ident, 2,
2613 3, channel->invite_list,
2614 channel->invite_list ?
2615 strlen(channel->invite_list) : 0);
2618 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2619 SILC_STATUS_OK, 0, ident, 1,
2621 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2622 packet->data, packet->len, FALSE);
2623 silc_buffer_free(packet);
2627 silc_free(channel_id);
2628 silc_server_command_free(cmd);
2633 SilcSocketConnection sock;
2637 /* Quits connection to client. This gets called if client won't
2638 close the connection even when it has issued QUIT command. */
2640 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2642 QuitInternal q = (QuitInternal)context;
2644 /* Free all client specific data, such as client entry and entires
2645 on channels this client may be on. */
2646 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2648 q->sock->user_data = NULL;
2650 /* Close the connection on our side */
2651 silc_server_close_connection(q->server, q->sock);
2653 silc_free(q->signoff);
2657 /* Quits SILC session. This is the normal way to disconnect client. */
2659 SILC_SERVER_CMD_FUNC(quit)
2661 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2662 SilcServer server = cmd->server;
2663 SilcSocketConnection sock = cmd->sock;
2665 unsigned char *tmp = NULL;
2668 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2670 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2674 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2678 q = silc_calloc(1, sizeof(*q));
2681 q->signoff = tmp ? strdup(tmp) : NULL;
2683 /* We quit the connection with little timeout */
2684 silc_schedule_task_add(server->schedule, sock->sock,
2685 silc_server_command_quit_cb, (void *)q,
2686 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2689 silc_server_command_free(cmd);
2692 /* Server side of command KILL. This command is used by router operator
2693 to remove an client from the SILC Network temporarily. */
2695 SILC_SERVER_CMD_FUNC(kill)
2697 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2698 SilcServer server = cmd->server;
2699 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2700 SilcClientEntry remote_client;
2701 SilcClientID *client_id;
2702 unsigned char *tmp, *comment;
2703 SilcUInt32 tmp_len, tmp_len2;
2706 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2708 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2711 /* KILL command works only on router */
2712 if (server->server_type != SILC_ROUTER) {
2713 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2714 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2718 /* Check whether client has the permissions. */
2719 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2720 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2721 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2725 /* Get the client ID */
2726 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2728 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2729 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2732 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2734 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2735 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2739 /* Get the client entry */
2740 remote_client = silc_idlist_find_client_by_id(server->local_list,
2741 client_id, TRUE, NULL);
2743 if (!remote_client) {
2744 remote_client = silc_idlist_find_client_by_id(server->global_list,
2745 client_id, TRUE, NULL);
2747 if (!remote_client) {
2748 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2749 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2755 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2759 /* Send reply to the sender */
2760 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2763 /* Check if anyone is watching this nickname */
2764 if (server->server_type == SILC_ROUTER)
2765 silc_server_check_watcher_list(server, client, NULL,
2766 SILC_NOTIFY_TYPE_KILLED);
2768 /* Now do the killing */
2769 silc_server_kill_client(server, remote_client, comment, client->id,
2773 silc_server_command_free(cmd);
2776 /* Server side of command INFO. This sends information about us to
2777 the client. If client requested specific server we will send the
2778 command to that server. */
2780 SILC_SERVER_CMD_FUNC(info)
2782 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2783 SilcServer server = cmd->server;
2784 SilcBuffer packet, idp;
2787 char *dest_server, *server_info = NULL, *server_name;
2788 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2789 SilcServerEntry entry = NULL;
2790 SilcServerID *server_id = NULL;
2792 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2794 /* Get server name */
2795 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2798 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2800 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2802 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2803 SILC_STATUS_ERR_NO_SERVER_ID);
2809 /* Check whether we have this server cached */
2810 entry = silc_idlist_find_server_by_id(server->local_list,
2811 server_id, TRUE, NULL);
2813 entry = silc_idlist_find_server_by_id(server->global_list,
2814 server_id, TRUE, NULL);
2815 if (!entry && server->server_type != SILC_SERVER) {
2816 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2817 SILC_STATUS_ERR_NO_SUCH_SERVER);
2823 /* Some buggy servers has sent request to router about themselves. */
2824 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2827 if ((!dest_server && !server_id && !entry) || (entry &&
2828 entry == server->id_entry) ||
2829 (dest_server && !cmd->pending &&
2830 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2831 /* Send our reply */
2832 char info_string[256];
2834 memset(info_string, 0, sizeof(info_string));
2835 snprintf(info_string, sizeof(info_string),
2836 "location: %s server: %s admin: %s <%s>",
2837 server->config->server_info->location,
2838 server->config->server_info->server_type,
2839 server->config->server_info->admin,
2840 server->config->server_info->email);
2842 server_info = info_string;
2843 entry = server->id_entry;
2845 /* Check whether we have this server cached */
2846 if (!entry && dest_server) {
2847 entry = silc_idlist_find_server_by_name(server->global_list,
2848 dest_server, TRUE, NULL);
2850 entry = silc_idlist_find_server_by_name(server->local_list,
2851 dest_server, TRUE, NULL);
2855 if (!cmd->pending &&
2856 server->server_type != SILC_SERVER && entry && !entry->server_info) {
2857 /* Send to the server */
2859 SilcUInt16 old_ident;
2861 old_ident = silc_command_get_ident(cmd->payload);
2862 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2863 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2865 silc_server_packet_send(server, entry->connection,
2866 SILC_PACKET_COMMAND, cmd->packet->flags,
2867 tmpbuf->data, tmpbuf->len, TRUE);
2869 /* Reprocess this packet after received reply from router */
2870 silc_server_command_pending(server, SILC_COMMAND_INFO,
2871 silc_command_get_ident(cmd->payload),
2872 silc_server_command_info,
2873 silc_server_command_dup(cmd));
2874 cmd->pending = TRUE;
2875 silc_command_set_ident(cmd->payload, old_ident);
2876 silc_buffer_free(tmpbuf);
2880 if (!entry && !cmd->pending && !server->standalone) {
2881 /* Send to the primary router */
2883 SilcUInt16 old_ident;
2885 old_ident = silc_command_get_ident(cmd->payload);
2886 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2887 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2889 silc_server_packet_send(server, server->router->connection,
2890 SILC_PACKET_COMMAND, cmd->packet->flags,
2891 tmpbuf->data, tmpbuf->len, TRUE);
2893 /* Reprocess this packet after received reply from router */
2894 silc_server_command_pending(server, SILC_COMMAND_INFO,
2895 silc_command_get_ident(cmd->payload),
2896 silc_server_command_info,
2897 silc_server_command_dup(cmd));
2898 cmd->pending = TRUE;
2899 silc_command_set_ident(cmd->payload, old_ident);
2900 silc_buffer_free(tmpbuf);
2905 silc_free(server_id);
2908 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2909 SILC_STATUS_ERR_NO_SUCH_SERVER);
2913 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2915 server_info = entry->server_info;
2916 server_name = entry->server_name;
2918 /* Send the reply */
2919 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2920 SILC_STATUS_OK, 0, ident, 3,
2921 2, idp->data, idp->len,
2923 strlen(server_name),
2926 strlen(server_info) : 0);
2927 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2928 packet->data, packet->len, FALSE);
2930 silc_buffer_free(packet);
2931 silc_buffer_free(idp);
2934 silc_server_command_free(cmd);
2937 /* Server side of command PING. This just replies to the ping. */
2939 SILC_SERVER_CMD_FUNC(ping)
2941 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2942 SilcServer server = cmd->server;
2947 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
2950 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2952 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2953 SILC_STATUS_ERR_NO_SERVER_ID);
2956 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2960 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2961 /* Send our reply */
2962 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2965 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2966 SILC_STATUS_ERR_NO_SUCH_SERVER);
2973 silc_server_command_free(cmd);
2976 /* Server side of command STATS. */
2978 SILC_SERVER_CMD_FUNC(stats)
2980 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2981 SilcServer server = cmd->server;
2982 SilcServerID *server_id;
2985 SilcBuffer packet, stats;
2986 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2989 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1);
2992 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2994 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2995 SILC_STATUS_ERR_NO_SERVER_ID);
2998 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3002 /* The ID must be ours */
3003 if (!SILC_ID_SERVER_COMPARE(server->id, server_id)) {
3004 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3005 SILC_STATUS_ERR_NO_SUCH_SERVER);
3006 silc_free(server_id);
3009 silc_free(server_id);
3011 /* If we are router then just send everything we got. If we are normal
3012 server then we'll send this to our router to get all the latest
3013 statistical information. */
3014 if (!cmd->pending && server->server_type != SILC_ROUTER &&
3015 !server->standalone) {
3016 /* Send request to our router */
3017 SilcBuffer idp = silc_id_payload_encode(server->router->id,
3019 packet = silc_command_payload_encode_va(SILC_COMMAND_STATS,
3020 ++server->cmd_ident, 1,
3021 1, idp->data, idp->len);
3022 silc_server_packet_send(server, server->router->connection,
3023 SILC_PACKET_COMMAND, 0, packet->data,
3024 packet->len, FALSE);
3026 /* Reprocess this packet after received reply from router */
3027 silc_server_command_pending(server, SILC_COMMAND_STATS,
3029 silc_server_command_stats,
3030 silc_server_command_dup(cmd));
3031 cmd->pending = TRUE;
3032 silc_buffer_free(packet);
3033 silc_buffer_free(idp);
3037 /* Send our reply to sender */
3038 uptime = time(NULL) - server->starttime;
3040 stats = silc_buffer_alloc_size(60);
3041 silc_buffer_format(stats,
3042 SILC_STR_UI_INT(server->starttime),
3043 SILC_STR_UI_INT(uptime),
3044 SILC_STR_UI_INT(server->stat.my_clients),
3045 SILC_STR_UI_INT(server->stat.my_channels),
3046 SILC_STR_UI_INT(server->stat.my_server_ops),
3047 SILC_STR_UI_INT(server->stat.my_router_ops),
3048 SILC_STR_UI_INT(server->stat.cell_clients),
3049 SILC_STR_UI_INT(server->stat.cell_channels),
3050 SILC_STR_UI_INT(server->stat.cell_servers),
3051 SILC_STR_UI_INT(server->stat.clients),
3052 SILC_STR_UI_INT(server->stat.channels),
3053 SILC_STR_UI_INT(server->stat.servers),
3054 SILC_STR_UI_INT(server->stat.routers),
3055 SILC_STR_UI_INT(server->stat.server_ops),
3056 SILC_STR_UI_INT(server->stat.router_ops),
3059 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_STATS,
3060 SILC_STATUS_OK, 0, ident, 2,
3062 3, stats->data, stats->len);
3063 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
3064 0, packet->data, packet->len, FALSE);
3065 silc_buffer_free(packet);
3066 silc_buffer_free(stats);
3069 silc_server_command_free(cmd);
3072 /* Internal routine to join channel. The channel sent to this function
3073 has been either created or resolved from ID lists. This joins the sent
3074 client to the channel. */
3076 static void silc_server_command_join_channel(SilcServer server,
3077 SilcServerCommandContext cmd,
3078 SilcChannelEntry channel,
3079 SilcClientID *client_id,
3083 const unsigned char *auth,
3084 SilcUInt32 auth_len)
3086 SilcSocketConnection sock = cmd->sock;
3088 SilcUInt32 tmp_len, user_count;
3089 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
3090 SilcClientEntry client;
3091 SilcChannelClientEntry chl;
3092 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
3093 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3094 char check[512], check2[512];
3095 bool founder = FALSE;
3098 SILC_LOG_DEBUG(("Start"));
3103 /* Get the client entry */
3104 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3105 client = (SilcClientEntry)sock->user_data;
3107 client = silc_server_get_client_resolve(server, client_id, FALSE,
3114 silc_server_command_send_status_reply(
3115 cmd, SILC_COMMAND_JOIN,
3116 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3120 /* The client info is being resolved. Reprocess this packet after
3121 receiving the reply to the query. */
3122 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
3124 silc_server_command_join,
3125 silc_server_command_dup(cmd));
3126 cmd->pending = TRUE;
3130 cmd->pending = FALSE;
3134 * Check founder auth payload if provided. If client can gain founder
3135 * privileges it can override various conditions on joining the channel,
3136 * and can have directly the founder mode set on the channel.
3138 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3139 SilcIDListData idata = (SilcIDListData)client;
3141 if (channel->founder_key && idata->public_key &&
3142 silc_pkcs_public_key_compare(channel->founder_key,
3143 idata->public_key)) {
3144 void *auth_data = (channel->founder_method == SILC_AUTH_PASSWORD ?
3145 (void *)channel->founder_passwd :
3146 (void *)channel->founder_key);
3147 SilcUInt32 auth_data_len =
3148 (channel->founder_method == SILC_AUTH_PASSWORD ?
3149 channel->founder_passwd_len : 0);
3151 /* Check whether the client is to become founder */
3152 if (silc_auth_verify_data(auth, auth_len, channel->founder_method,
3153 auth_data, auth_data_len,
3154 idata->hash, client->id, SILC_ID_CLIENT)) {
3155 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3162 * Check channel modes
3166 memset(check, 0, sizeof(check));
3167 memset(check2, 0, sizeof(check2));
3168 strncat(check, client->nickname, strlen(client->nickname));
3169 strncat(check, "!", 1);
3170 strncat(check, client->username, strlen(client->username));
3171 if (!strchr(client->username, '@')) {
3172 strncat(check, "@", 1);
3173 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3176 strncat(check2, client->nickname, strlen(client->nickname));
3177 if (!strchr(client->nickname, '@')) {
3178 strncat(check2, "@", 1);
3179 strncat(check2, server->server_name, strlen(server->server_name));
3181 strncat(check2, "!", 1);
3182 strncat(check2, client->username, strlen(client->username));
3183 if (!strchr(client->username, '@')) {
3184 strncat(check2, "@", 1);
3185 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3188 /* Check invite list if channel is invite-only channel */
3189 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3190 if (!channel->invite_list ||
3191 (!silc_string_match(channel->invite_list, check) &&
3192 !silc_string_match(channel->invite_list, check2))) {
3193 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3194 SILC_STATUS_ERR_NOT_INVITED);
3199 /* Check ban list if it exists. If the client's nickname, server,
3200 username and/or hostname is in the ban list the access to the
3201 channel is denied. */
3202 if (channel->ban_list) {
3203 if (silc_string_match(channel->ban_list, check) ||
3204 silc_string_match(channel->ban_list, check2)) {
3205 silc_server_command_send_status_reply(
3206 cmd, SILC_COMMAND_JOIN,
3207 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
3212 /* Check user count limit if set. */
3213 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3214 if (silc_hash_table_count(channel->user_list) + 1 >
3215 channel->user_limit) {
3216 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3217 SILC_STATUS_ERR_CHANNEL_IS_FULL);
3223 /* Check the channel passphrase if set. */
3224 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3225 /* Get passphrase */
3226 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3228 passphrase = silc_memdup(tmp, tmp_len);
3230 if (!passphrase || !channel->passphrase ||
3231 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3232 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3233 SILC_STATUS_ERR_BAD_PASSWORD);
3239 * Client is allowed to join to the channel. Make it happen.
3242 /* Check whether the client already is on the channel */
3243 if (silc_server_client_on_channel(client, channel, NULL)) {
3244 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3245 SILC_STATUS_ERR_USER_ON_CHANNEL);
3249 /* Generate new channel key as protocol dictates */
3251 if (!silc_server_create_channel_key(server, channel, 0))
3254 /* Send the channel key. This is broadcasted to the channel but is not
3255 sent to the client who is joining to the channel. */
3256 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3257 silc_server_send_channel_key(server, NULL, channel,
3258 server->server_type == SILC_ROUTER ?
3259 FALSE : !server->standalone);
3262 /* Join the client to the channel by adding it to channel's user list.
3263 Add also the channel to client entry's channels list for fast cross-
3265 chl = silc_calloc(1, sizeof(*chl));
3267 chl->client = client;
3268 chl->channel = channel;
3269 silc_hash_table_add(channel->user_list, client, chl);
3270 silc_hash_table_add(client->channels, channel, chl);
3271 channel->user_count++;
3273 /* Get users on the channel */
3274 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3277 /* Encode Client ID Payload of the original client who wants to join */
3278 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3280 /* Encode command reply packet */
3281 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3282 SILC_PUT32_MSB(channel->mode, mode);
3283 SILC_PUT32_MSB(created, tmp2);
3284 SILC_PUT32_MSB(user_count, tmp3);
3286 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3287 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3288 keyp = silc_channel_key_payload_encode(silc_id_get_len(channel->id,
3291 strlen(channel->channel_key->
3293 channel->channel_key->cipher->name,
3294 channel->key_len / 8, channel->key);
3299 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3300 SILC_STATUS_OK, 0, ident, 13,
3301 2, channel->channel_name,
3302 strlen(channel->channel_name),
3303 3, chidp->data, chidp->len,
3304 4, clidp->data, clidp->len,
3307 7, keyp ? keyp->data : NULL,
3308 keyp ? keyp->len : 0,
3309 8, channel->ban_list,
3311 strlen(channel->ban_list) : 0,
3312 9, channel->invite_list,
3313 channel->invite_list ?
3314 strlen(channel->invite_list) : 0,
3317 strlen(channel->topic) : 0,
3318 11, silc_hmac_get_name(channel->hmac),
3319 strlen(silc_hmac_get_name(channel->
3322 13, user_list->data, user_list->len,
3323 14, mode_list->data,
3326 /* Send command reply */
3327 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3328 reply->data, reply->len, FALSE);
3330 /* Send JOIN notify to locally connected clients on the channel. If
3331 we are normal server then router will send or have sent JOIN notify
3332 already. However since we've added the client already to our channel
3333 we'll ignore it (in packet_receive.c) so we must send it here. If
3334 we are router then this will send it to local clients and local
3336 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3337 SILC_NOTIFY_TYPE_JOIN, 2,
3338 clidp->data, clidp->len,
3339 chidp->data, chidp->len);
3341 if (!cmd->pending) {
3342 /* Send JOIN notify packet to our primary router */
3343 if (!server->standalone)
3344 silc_server_send_notify_join(server, server->router->connection,
3345 server->server_type == SILC_ROUTER ?
3346 TRUE : FALSE, channel, client->id);
3349 /* Distribute the channel key to all backup routers. */
3350 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3351 keyp->data, keyp->len, FALSE, TRUE);
3354 /* If client became founder by providing correct founder auth data
3355 notify the mode change to the channel. */
3357 SILC_PUT32_MSB(chl->mode, mode);
3358 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3359 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3360 clidp->data, clidp->len,
3361 mode, 4, clidp->data, clidp->len);
3363 /* Set CUMODE notify type to network */
3364 if (!server->standalone)
3365 silc_server_send_notify_cumode(server, server->router->connection,
3366 server->server_type == SILC_ROUTER ?
3367 TRUE : FALSE, channel,
3368 chl->mode, client->id, SILC_ID_CLIENT,
3372 silc_buffer_free(reply);
3373 silc_buffer_free(clidp);
3374 silc_buffer_free(chidp);
3375 silc_buffer_free(keyp);
3376 silc_buffer_free(user_list);
3377 silc_buffer_free(mode_list);
3380 silc_free(passphrase);
3383 /* Server side of command JOIN. Joins client into requested channel. If
3384 the channel does not exist it will be created. */
3386 SILC_SERVER_CMD_FUNC(join)
3388 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3389 SilcServer server = cmd->server;
3390 unsigned char *auth;
3391 SilcUInt32 tmp_len, auth_len;
3392 char *tmp, *channel_name = NULL, *cipher, *hmac;
3393 SilcChannelEntry channel;
3394 SilcUInt32 umode = 0;
3395 bool created = FALSE, create_key = TRUE;
3396 SilcClientID *client_id;
3398 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3400 /* Get channel name */
3401 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3403 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3404 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3410 channel_name[255] = '\0';
3412 if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
3413 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3414 SILC_STATUS_ERR_BAD_CHANNEL);
3418 /* Get Client ID of the client who is joining to the channel */
3419 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3421 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3422 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3425 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3427 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3428 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3432 /* Get cipher, hmac name and auth payload */
3433 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3434 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3435 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3437 /* See if the channel exists */
3438 channel = silc_idlist_find_channel_by_name(server->local_list,
3439 channel_name, NULL);
3441 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3442 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3443 client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
3445 if (!channel || channel->disabled) {
3446 /* Channel not found */
3448 /* If we are standalone server we don't have a router, we just create
3449 the channel by ourselves. */
3450 if (server->standalone) {
3451 channel = silc_server_create_new_channel(server, server->id, cipher,
3452 hmac, channel_name, TRUE);
3454 silc_server_command_send_status_reply(
3455 cmd, SILC_COMMAND_JOIN,
3456 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3460 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3466 /* The channel does not exist on our server. If we are normal server
3467 we will send JOIN command to our router which will handle the
3468 joining procedure (either creates the channel if it doesn't exist
3469 or joins the client to it). */
3470 if (server->server_type != SILC_ROUTER) {
3472 SilcUInt16 old_ident;
3474 /* If this is pending command callback then we've resolved
3475 it and it didn't work, return since we've notified the
3476 client already in the command reply callback. */
3480 old_ident = silc_command_get_ident(cmd->payload);
3481 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3482 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3484 /* Send JOIN command to our router */
3485 silc_server_packet_send(server, (SilcSocketConnection)
3486 server->router->connection,
3487 SILC_PACKET_COMMAND, cmd->packet->flags,
3488 tmpbuf->data, tmpbuf->len, TRUE);
3490 /* Reprocess this packet after received reply from router */
3491 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3492 silc_command_get_ident(cmd->payload),
3493 silc_server_command_join,
3494 silc_server_command_dup(cmd));
3495 cmd->pending = TRUE;
3496 silc_command_set_ident(cmd->payload, old_ident);
3497 silc_buffer_free(tmpbuf);
3501 /* We are router and the channel does not seem exist so we will check
3502 our global list as well for the channel. */
3503 channel = silc_idlist_find_channel_by_name(server->global_list,
3504 channel_name, NULL);
3506 /* Channel really does not exist, create it */
3507 channel = silc_server_create_new_channel(server, server->id, cipher,
3508 hmac, channel_name, TRUE);
3510 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3511 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3515 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3523 /* Channel not found */
3525 /* If the command came from router and we are normal server then
3526 something went wrong with the joining as the channel was not found.
3527 We can't do anything else but ignore this. */
3528 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3529 server->server_type != SILC_ROUTER)
3532 /* We are router and the channel does not seem exist so we will check
3533 our global list as well for the channel. */
3534 channel = silc_idlist_find_channel_by_name(server->global_list,
3535 channel_name, NULL);
3537 /* Channel really does not exist, create it */
3538 channel = silc_server_create_new_channel(server, server->id, cipher,
3539 hmac, channel_name, TRUE);
3541 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3542 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3546 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3553 /* Check whether the channel was created by our router */
3554 if (cmd->pending && context2) {
3555 SilcServerCommandReplyContext reply = context2;
3557 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3558 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3559 SILC_GET32_MSB(created, tmp);
3560 if (silc_argument_get_arg_type(reply->args, 7, NULL))
3561 create_key = FALSE; /* Router returned the key already */
3564 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
3565 !silc_hash_table_count(channel->user_list))
3569 /* If the channel does not have global users and is also empty the client
3570 will be the channel founder and operator. */
3571 if (!channel->global_users && !silc_hash_table_count(channel->user_list))
3572 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3574 /* Join to the channel */
3575 silc_server_command_join_channel(server, cmd, channel, client_id,
3576 created, create_key, umode,
3579 silc_free(client_id);
3582 silc_server_command_free(cmd);
3585 /* Server side of command MOTD. Sends server's current "message of the
3586 day" to the client. */
3588 SILC_SERVER_CMD_FUNC(motd)
3590 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3591 SilcServer server = cmd->server;
3592 SilcBuffer packet, idp;
3593 char *motd, *dest_server;
3594 SilcUInt32 motd_len;
3595 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3597 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3599 /* Get server name */
3600 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3602 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3603 SILC_STATUS_ERR_NO_SUCH_SERVER);
3607 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3610 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3612 if (server->config && server->config->server_info &&
3613 server->config->server_info->motd_file) {
3615 motd = silc_file_readfile(server->config->server_info->motd_file, &motd_len);
3620 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3627 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3633 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3634 packet->data, packet->len, FALSE);
3635 silc_buffer_free(packet);
3636 silc_buffer_free(idp);
3638 SilcServerEntry entry;
3640 /* Check whether we have this server cached */
3641 entry = silc_idlist_find_server_by_name(server->global_list,
3642 dest_server, TRUE, NULL);
3644 entry = silc_idlist_find_server_by_name(server->local_list,
3645 dest_server, TRUE, NULL);
3648 if (server->server_type != SILC_SERVER && !cmd->pending &&
3649 entry && !entry->motd) {
3650 /* Send to the server */
3652 SilcUInt16 old_ident;
3654 old_ident = silc_command_get_ident(cmd->payload);
3655 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3656 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3658 silc_server_packet_send(server, entry->connection,
3659 SILC_PACKET_COMMAND, cmd->packet->flags,
3660 tmpbuf->data, tmpbuf->len, TRUE);
3662 /* Reprocess this packet after received reply from router */
3663 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3664 silc_command_get_ident(cmd->payload),
3665 silc_server_command_motd,
3666 silc_server_command_dup(cmd));
3667 cmd->pending = TRUE;
3668 silc_command_set_ident(cmd->payload, old_ident);
3669 silc_buffer_free(tmpbuf);
3673 if (!entry && !cmd->pending && !server->standalone) {
3674 /* Send to the primary router */
3676 SilcUInt16 old_ident;
3678 old_ident = silc_command_get_ident(cmd->payload);
3679 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3680 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3682 silc_server_packet_send(server, server->router->connection,
3683 SILC_PACKET_COMMAND, cmd->packet->flags,
3684 tmpbuf->data, tmpbuf->len, TRUE);
3686 /* Reprocess this packet after received reply from router */
3687 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3688 silc_command_get_ident(cmd->payload),
3689 silc_server_command_motd,
3690 silc_server_command_dup(cmd));
3691 cmd->pending = TRUE;
3692 silc_command_set_ident(cmd->payload, old_ident);
3693 silc_buffer_free(tmpbuf);
3698 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3699 SILC_STATUS_ERR_NO_SUCH_SERVER);
3703 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3704 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3705 SILC_STATUS_OK, 0, ident, 2,
3709 strlen(entry->motd) : 0);
3710 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3711 packet->data, packet->len, FALSE);
3712 silc_buffer_free(packet);
3713 silc_buffer_free(idp);
3717 silc_server_command_free(cmd);
3720 /* Server side of command UMODE. Client can use this command to set/unset
3721 user mode. Client actually cannot set itself to be as server/router
3722 operator so this can be used only to unset the modes. */
3724 SILC_SERVER_CMD_FUNC(umode)
3726 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3727 SilcServer server = cmd->server;
3728 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3730 unsigned char *tmp_mask, m[4];
3731 SilcUInt32 mask = 0;
3732 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3733 bool set_mask = FALSE;
3735 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3738 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2);
3740 /* Get the client's mode mask */
3741 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3743 SILC_GET32_MSB(mask, tmp_mask);
3748 /* Check that mode changing is allowed. */
3749 if (!silc_server_check_umode_rights(server, client, mask)) {
3750 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3751 SILC_STATUS_ERR_PERM_DENIED);
3755 /* Anonymous mode cannot be set by client */
3756 if (mask & SILC_UMODE_ANONYMOUS) {
3757 if (!(client->mode & SILC_UMODE_ANONYMOUS)) {
3758 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3759 SILC_STATUS_ERR_PERM_DENIED);
3763 if (client->mode & SILC_UMODE_ANONYMOUS) {
3764 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3765 SILC_STATUS_ERR_PERM_DENIED);
3770 /* Change the mode */
3771 client->mode = mask;
3773 /* Send UMODE change to primary router */
3774 if (!server->standalone)
3775 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3776 client->id, client->mode);
3778 /* Check if anyone is watching this nickname */
3779 if (server->server_type == SILC_ROUTER)
3780 silc_server_check_watcher_list(server, client, NULL,
3781 SILC_NOTIFY_TYPE_UMODE_CHANGE);
3784 /* Send command reply to sender */
3785 SILC_PUT32_MSB(client->mode, m);
3786 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3787 SILC_STATUS_OK, 0, ident, 1,
3789 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3790 packet->data, packet->len, FALSE);
3791 silc_buffer_free(packet);
3794 silc_server_command_free(cmd);
3797 /* Server side command of CMODE. Changes channel mode */
3799 SILC_SERVER_CMD_FUNC(cmode)
3801 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3802 SilcServer server = cmd->server;
3803 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3804 SilcIDListData idata = (SilcIDListData)client;
3805 SilcChannelID *channel_id = NULL;
3806 SilcChannelEntry channel;
3807 SilcChannelClientEntry chl;
3808 SilcBuffer packet, cidp;
3809 unsigned char *tmp, *tmp_id, *tmp_mask;
3810 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3811 SilcUInt32 mode_mask = 0, tmp_len, tmp_len2;
3812 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3813 bool set_mask = FALSE;
3815 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 7);
3817 /* Get Channel ID */
3818 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3820 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3821 SILC_STATUS_ERR_NO_CHANNEL_ID);
3824 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
3826 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3827 SILC_STATUS_ERR_NO_CHANNEL_ID);
3831 /* Get the channel mode mask */
3832 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3834 SILC_GET32_MSB(mode_mask, tmp_mask);
3838 /* Get channel entry */
3839 channel = silc_idlist_find_channel_by_id(server->local_list,
3842 channel = silc_idlist_find_channel_by_id(server->global_list,
3845 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3846 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3851 /* Check whether this client is on the channel */
3852 if (!silc_server_client_on_channel(client, channel, &chl)) {
3853 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3854 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3858 /* Check that client has rights to change any requested channel modes */
3859 if (set_mask && !silc_server_check_cmode_rights(server, channel, chl,
3861 silc_server_command_send_status_reply(
3862 cmd, SILC_COMMAND_CMODE,
3863 (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) ?
3864 SILC_STATUS_ERR_NO_CHANNEL_PRIV :
3865 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV));
3869 /* If mode mask was not sent as argument then merely return the current
3870 mode mask to the sender. */
3873 SILC_PUT32_MSB(channel->mode, m);
3874 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3875 SILC_STATUS_OK, 0, ident, 2,
3876 2, tmp_id, tmp_len2,
3878 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3879 packet->data, packet->len, FALSE);
3880 silc_buffer_free(packet);
3885 * Check the modes. Modes that requires nothing special operation are
3889 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3890 /* Channel uses private keys to protect traffic. Client(s) has set the
3891 key locally they want to use, server does not know that key. */
3892 /* Nothing interesting to do here */
3894 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3895 /* The mode is removed and we need to generate and distribute
3896 new channel key. Clients are not using private channel keys
3897 anymore after this. */
3899 /* Re-generate channel key */
3900 if (!silc_server_create_channel_key(server, channel, 0))
3903 /* Send the channel key. This sends it to our local clients and if
3904 we are normal server to our router as well. */
3905 silc_server_send_channel_key(server, NULL, channel,
3906 server->server_type == SILC_ROUTER ?
3907 FALSE : !server->standalone);
3909 cipher = channel->channel_key->cipher->name;
3910 hmac = (char *)silc_hmac_get_name(channel->hmac);
3914 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3915 /* User limit is set on channel */
3916 SilcUInt32 user_limit;
3918 /* Get user limit */
3919 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3921 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3922 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3923 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3927 SILC_GET32_MSB(user_limit, tmp);
3928 channel->user_limit = user_limit;
3931 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3932 /* User limit mode is unset. Remove user limit */
3933 channel->user_limit = 0;
3936 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3937 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3938 /* Passphrase has been set to channel */
3940 /* Get the passphrase */
3941 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3943 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3944 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3948 /* Save the passphrase */
3949 passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
3952 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3953 /* Passphrase mode is unset. remove the passphrase */
3954 silc_free(channel->passphrase);
3955 channel->passphrase = NULL;
3959 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3960 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3961 /* Cipher to use protect the traffic */
3962 SilcCipher newkey, oldkey;
3965 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3967 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3968 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3972 /* Delete old cipher and allocate the new one */
3973 if (!silc_cipher_alloc(cipher, &newkey)) {
3974 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3975 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3979 oldkey = channel->channel_key;
3980 channel->channel_key = newkey;
3982 /* Re-generate channel key */
3983 if (!silc_server_create_channel_key(server, channel, 0)) {
3984 /* We don't have new key, revert to old one */
3985 channel->channel_key = oldkey;
3989 /* Remove old channel key for good */
3990 silc_cipher_free(oldkey);
3992 /* Send the channel key. This sends it to our local clients and if
3993 we are normal server to our router as well. */
3994 silc_server_send_channel_key(server, NULL, channel,
3995 server->server_type == SILC_ROUTER ?
3996 FALSE : !server->standalone);
3999 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
4000 /* Cipher mode is unset. Remove the cipher and revert back to
4002 SilcCipher newkey, oldkey;
4003 cipher = channel->cipher;
4005 /* Delete old cipher and allocate default one */
4006 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
4007 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4008 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4012 oldkey = channel->channel_key;
4013 channel->channel_key = newkey;
4015 /* Re-generate channel key */
4016 if (!silc_server_create_channel_key(server, channel, 0)) {
4017 /* We don't have new key, revert to old one */
4018 channel->channel_key = oldkey;
4022 /* Remove old channel key for good */
4023 silc_cipher_free(oldkey);
4025 /* Send the channel key. This sends it to our local clients and if
4026 we are normal server to our router as well. */
4027 silc_server_send_channel_key(server, NULL, channel,
4028 server->server_type == SILC_ROUTER ?
4029 FALSE : !server->standalone);
4033 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
4034 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
4035 /* HMAC to use protect the traffic */
4036 unsigned char hash[32];
4040 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4042 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4043 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4047 /* Delete old hmac and allocate the new one */
4048 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4049 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4050 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4054 silc_hmac_free(channel->hmac);
4055 channel->hmac = newhmac;
4057 /* Set the HMAC key out of current channel key. The client must do
4059 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4060 channel->key_len / 8, hash);
4061 silc_hmac_set_key(channel->hmac, hash,
4062 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4063 memset(hash, 0, sizeof(hash));
4066 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4067 /* Hmac mode is unset. Remove the hmac and revert back to
4070 unsigned char hash[32];
4071 hmac = channel->hmac_name;
4073 /* Delete old hmac and allocate default one */
4074 silc_hmac_free(channel->hmac);
4075 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4076 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4077 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4081 silc_hmac_free(channel->hmac);
4082 channel->hmac = newhmac;
4084 /* Set the HMAC key out of current channel key. The client must do
4086 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4087 channel->key_len / 8,
4089 silc_hmac_set_key(channel->hmac, hash,
4090 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4091 memset(hash, 0, sizeof(hash));
4095 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4096 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4097 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4098 /* Set the founder authentication */
4099 SilcAuthPayload auth;
4101 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4103 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4104 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4108 auth = silc_auth_payload_parse(tmp, tmp_len);
4110 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4111 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4115 /* Save the public key */
4116 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
4117 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
4120 channel->founder_method = silc_auth_get_method(auth);
4122 if (channel->founder_method == SILC_AUTH_PASSWORD) {
4123 tmp = silc_auth_get_data(auth, &tmp_len);
4124 channel->founder_passwd = silc_memdup(tmp, tmp_len);
4125 channel->founder_passwd_len = tmp_len;
4127 /* Verify the payload before setting the mode */
4128 if (!silc_auth_verify(auth, channel->founder_method,
4129 channel->founder_key, 0, idata->hash,
4130 client->id, SILC_ID_CLIENT)) {
4131 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4132 SILC_STATUS_ERR_AUTH_FAILED);
4137 silc_auth_payload_free(auth);
4141 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4142 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4143 if (channel->founder_key)
4144 silc_pkcs_public_key_free(channel->founder_key);
4145 if (channel->founder_passwd) {
4146 silc_free(channel->founder_passwd);
4147 channel->founder_passwd = NULL;
4153 /* Finally, set the mode */
4154 channel->mode = mode_mask;
4156 /* Send CMODE_CHANGE notify. */
4157 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4158 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4159 SILC_NOTIFY_TYPE_CMODE_CHANGE, 5,
4160 cidp->data, cidp->len,
4162 cipher, cipher ? strlen(cipher) : 0,
4163 hmac, hmac ? strlen(hmac) : 0,
4164 passphrase, passphrase ?
4165 strlen(passphrase) : 0);
4167 /* Set CMODE notify type to network */
4168 if (!server->standalone)
4169 silc_server_send_notify_cmode(server, server->router->connection,
4170 server->server_type == SILC_ROUTER ?
4171 TRUE : FALSE, channel,
4172 mode_mask, client->id, SILC_ID_CLIENT,
4173 cipher, hmac, passphrase);
4175 /* Send command reply to sender */
4176 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4177 SILC_STATUS_OK, 0, ident, 2,
4178 2, tmp_id, tmp_len2,
4180 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4181 packet->data, packet->len, FALSE);
4183 silc_buffer_free(packet);
4184 silc_buffer_free(cidp);
4187 silc_free(channel_id);
4188 silc_server_command_free(cmd);
4191 /* Server side of CUMODE command. Changes client's mode on a channel. */
4193 SILC_SERVER_CMD_FUNC(cumode)
4195 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4196 SilcServer server = cmd->server;
4197 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4198 SilcIDListData idata = (SilcIDListData)client;
4199 SilcChannelID *channel_id;
4200 SilcClientID *client_id;
4201 SilcChannelEntry channel;
4202 SilcClientEntry target_client;
4203 SilcChannelClientEntry chl;
4204 SilcBuffer packet, idp;
4205 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4206 SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4208 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4210 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4212 /* Get Channel ID */
4213 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4215 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4216 SILC_STATUS_ERR_NO_CHANNEL_ID);
4219 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
4221 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4222 SILC_STATUS_ERR_NO_CHANNEL_ID);
4226 /* Get channel entry */
4227 channel = silc_idlist_find_channel_by_id(server->local_list,
4230 channel = silc_idlist_find_channel_by_id(server->global_list,
4233 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4234 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4239 /* Check whether sender is on the channel */
4240 if (!silc_server_client_on_channel(client, channel, &chl)) {
4241 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4242 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4245 sender_mask = chl->mode;
4247 /* Get the target client's channel mode mask */
4248 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4250 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4251 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4254 SILC_GET32_MSB(target_mask, tmp_mask);
4256 /* Get target Client ID */
4257 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4259 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4260 SILC_STATUS_ERR_NO_CLIENT_ID);
4263 client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
4265 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4266 SILC_STATUS_ERR_NO_CLIENT_ID);
4270 /* Get target client's entry */
4271 target_client = silc_idlist_find_client_by_id(server->local_list,
4272 client_id, TRUE, NULL);
4273 if (!target_client) {
4274 target_client = silc_idlist_find_client_by_id(server->global_list,
4275 client_id, TRUE, NULL);
4278 if (target_client != client &&
4279 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4280 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4281 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4282 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4286 /* Check whether target client is on the channel */
4287 if (target_client != client) {
4288 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4289 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4290 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4299 /* If the target client is founder, no one else can change their mode
4301 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4302 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4303 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4307 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4308 if (target_client != client) {
4309 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4310 SILC_STATUS_ERR_NOT_YOU);
4314 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4315 /* The client tries to claim the founder rights. */
4316 unsigned char *tmp_auth;
4317 SilcUInt32 tmp_auth_len, auth_len;
4320 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4321 !channel->founder_key || !idata->public_key ||
4322 !silc_pkcs_public_key_compare(channel->founder_key,
4323 idata->public_key)) {
4324 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4325 SILC_STATUS_ERR_NOT_YOU);
4329 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4331 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4332 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4336 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4337 (void *)channel->founder_passwd : (void *)channel->founder_key);
4338 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4339 channel->founder_passwd_len : 0);
4341 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4342 channel->founder_method, auth, auth_len,
4343 idata->hash, client->id, SILC_ID_CLIENT)) {
4344 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4345 SILC_STATUS_ERR_AUTH_FAILED);
4349 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4353 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4354 if (target_client == client) {
4355 /* Remove channel founder rights from itself */
4356 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4359 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4360 SILC_STATUS_ERR_NOT_YOU);
4366 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4367 /* Promote to operator */
4368 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4369 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4370 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4371 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4372 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4376 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4380 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4381 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4382 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4383 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4384 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4388 /* Demote to normal user */
4389 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4394 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4395 if (target_client != client) {
4396 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4397 SILC_STATUS_ERR_NOT_YOU);
4401 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
4402 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4406 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4407 if (target_client != client) {
4408 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4409 SILC_STATUS_ERR_NOT_YOU);
4413 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4418 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4419 if (target_client != client) {
4420 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4421 SILC_STATUS_ERR_NOT_YOU);
4425 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)) {
4426 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4430 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4431 if (target_client != client) {
4432 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4433 SILC_STATUS_ERR_NOT_YOU);
4437 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4442 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4443 if (target_client != client) {
4444 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4445 SILC_STATUS_ERR_NOT_YOU);
4449 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)) {
4450 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4454 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4455 if (target_client != client) {
4456 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4457 SILC_STATUS_ERR_NOT_YOU);
4461 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4466 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4467 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4469 /* Send notify to channel, notify only if mode was actually changed. */
4471 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4472 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4473 idp->data, idp->len,
4477 /* Set CUMODE notify type to network */
4478 if (!server->standalone)
4479 silc_server_send_notify_cumode(server, server->router->connection,
4480 server->server_type == SILC_ROUTER ?
4481 TRUE : FALSE, channel,
4482 target_mask, client->id,
4487 /* Send command reply to sender */
4488 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4489 SILC_STATUS_OK, 0, ident, 3,
4491 3, tmp_ch_id, tmp_ch_len,
4492 4, tmp_id, tmp_len);
4493 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4494 packet->data, packet->len, FALSE);
4496 silc_buffer_free(packet);
4497 silc_free(channel_id);
4498 silc_free(client_id);
4499 silc_buffer_free(idp);
4502 silc_server_command_free(cmd);
4505 /* Server side of KICK command. Kicks client out of channel. */
4507 SILC_SERVER_CMD_FUNC(kick)
4509 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4510 SilcServer server = cmd->server;
4511 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4512 SilcClientEntry target_client;
4513 SilcChannelID *channel_id;
4514 SilcClientID *client_id;
4515 SilcChannelEntry channel;
4516 SilcChannelClientEntry chl;
4518 SilcUInt32 tmp_len, target_idp_len;
4519 unsigned char *tmp, *comment, *target_idp;
4521 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4523 /* Get Channel ID */
4524 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4526 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4527 SILC_STATUS_ERR_NO_CHANNEL_ID);
4530 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4532 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4533 SILC_STATUS_ERR_NO_CHANNEL_ID);
4537 /* Get channel entry */
4538 channel = silc_idlist_find_channel_by_id(server->local_list,
4541 channel = silc_idlist_find_channel_by_id(server->local_list,
4544 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4545 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4550 /* Check whether sender is on the channel */
4551 if (!silc_server_client_on_channel(client, channel, &chl)) {
4552 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4553 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4557 /* Check that the kicker is channel operator or channel founder */
4558 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
4559 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4560 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4561 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4565 /* Get target Client ID */
4566 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4568 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4569 SILC_STATUS_ERR_NO_CLIENT_ID);
4572 client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
4574 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4575 SILC_STATUS_ERR_NO_CLIENT_ID);
4579 /* Get target client's entry */
4580 target_client = silc_idlist_find_client_by_id(server->local_list,
4581 client_id, TRUE, NULL);
4582 if (!target_client) {
4583 target_client = silc_idlist_find_client_by_id(server->global_list,
4584 client_id, TRUE, NULL);
4587 /* Check whether target client is on the channel */
4588 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4589 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4590 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4594 /* Check that the target client is not channel founder. Channel founder
4595 cannot be kicked from the channel. */
4596 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4597 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4598 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4604 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4608 /* Send command reply to sender */
4609 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4612 /* Send KICKED notify to local clients on the channel */
4613 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4614 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4615 SILC_NOTIFY_TYPE_KICKED, 3,
4616 target_idp, target_idp_len,
4617 comment, comment ? strlen(comment) : 0,
4618 idp->data, idp->len);
4619 silc_buffer_free(idp);
4621 /* Remove the client from the channel. If the channel does not exist
4622 after removing the client then the client kicked itself off the channel
4623 and we don't have to send anything after that. */
4624 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4625 target_client, FALSE))
4628 /* Send KICKED notify to primary route */
4629 if (!server->standalone)
4630 silc_server_send_notify_kicked(server, server->router->connection,
4631 server->server_type == SILC_ROUTER ?
4632 TRUE : FALSE, channel,
4633 target_client->id, client->id, comment);
4635 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4636 /* Re-generate channel key */
4637 if (!silc_server_create_channel_key(server, channel, 0))
4640 /* Send the channel key to the channel. The key of course is not sent
4641 to the client who was kicked off the channel. */
4642 silc_server_send_channel_key(server, target_client->connection, channel,
4643 server->server_type == SILC_ROUTER ?
4644 FALSE : !server->standalone);
4648 silc_server_command_free(cmd);
4651 /* Server side of OPER command. Client uses this comand to obtain server
4652 operator privileges to this server/router. */
4654 SILC_SERVER_CMD_FUNC(oper)
4656 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4657 SilcServer server = cmd->server;
4658 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4659 unsigned char *username, *auth;
4661 SilcServerConfigAdmin *admin;
4662 SilcIDListData idata = (SilcIDListData)client;
4663 bool result = FALSE;
4664 SilcPublicKey cached_key;
4666 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4668 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4671 /* Get the username */
4672 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4674 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4675 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4679 /* Get the admin configuration */
4680 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4681 username, client->nickname);
4683 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4684 username, client->nickname);
4686 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4687 SILC_STATUS_ERR_AUTH_FAILED);
4692 /* Get the authentication payload */
4693 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4695 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4696 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4700 /* Verify the authentication data. If both passphrase and public key
4701 is set then try both of them. */
4702 if (admin->passphrase)
4703 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4704 admin->passphrase, admin->passphrase_len,
4705 idata->hash, client->id, SILC_ID_CLIENT);
4706 if (!result && admin->publickeys) {
4707 cached_key = silc_server_get_public_key(server, admin->publickeys);
4710 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4711 cached_key, 0, idata->hash,
4712 client->id, SILC_ID_CLIENT);
4715 /* Authentication failed */
4716 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4717 SILC_STATUS_ERR_AUTH_FAILED);
4721 /* Client is now server operator */
4722 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4724 /* Update statistics */
4725 if (client->connection)
4726 server->stat.my_server_ops++;
4727 if (server->server_type == SILC_ROUTER)
4728 server->stat.server_ops++;
4730 /* Send UMODE change to primary router */
4731 if (!server->standalone)
4732 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4733 client->id, client->mode);
4735 /* Check if anyone is watching this nickname */
4736 if (server->server_type == SILC_ROUTER)
4737 silc_server_check_watcher_list(server, client, NULL,
4738 SILC_NOTIFY_TYPE_UMODE_CHANGE);
4740 /* Send reply to the sender */
4741 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4745 silc_server_command_free(cmd);
4748 SILC_TASK_CALLBACK(silc_server_command_detach_cb)
4750 QuitInternal q = (QuitInternal)context;
4751 SilcClientEntry client = (SilcClientEntry)q->sock->user_data;
4753 /* If there is pending outgoing data for the client then purge it
4754 to the network before closing connection. */
4755 silc_server_packet_queue_purge(q->server, q->sock);
4757 /* Close the connection on our side */
4758 client->router = NULL;
4759 client->connection = NULL;
4760 q->sock->user_data = NULL;
4761 silc_server_close_connection(q->server, q->sock);
4766 SILC_TASK_CALLBACK(silc_server_command_detach_timeout)
4768 QuitInternal q = (QuitInternal)context;
4769 SilcClientEntry client = (SilcClientEntry)q->sock;
4771 SILC_LOG_DEBUG(("Start"));
4773 if (client->mode & SILC_UMODE_DETACHED)
4774 silc_server_free_client_data(q->server, NULL, client, TRUE,
4779 /* Server side of DETACH command. Detached the client from the network
4780 by closing the connection but preserving the session. */
4782 SILC_SERVER_CMD_FUNC(detach)
4784 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4785 SilcServer server = cmd->server;
4786 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4789 if (server->config->detach_disabled) {
4790 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
4791 SILC_STATUS_ERR_UNKNOWN_COMMAND);
4795 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4798 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
4800 /* Send the user mode notify to notify that client is detached */
4801 client->mode |= SILC_UMODE_DETACHED;
4802 client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
4803 if (!server->standalone)
4804 silc_server_send_notify_umode(server, server->router->connection,
4805 server->server_type == SILC_SERVER ?
4806 FALSE : TRUE, client->id, client->mode);
4808 /* Check if anyone is watching this nickname */
4809 if (server->server_type == SILC_ROUTER)
4810 silc_server_check_watcher_list(server, client, NULL,
4811 SILC_NOTIFY_TYPE_UMODE_CHANGE);
4813 q = silc_calloc(1, sizeof(*q));
4815 q->sock = cmd->sock;
4816 silc_schedule_task_add(server->schedule, 0, silc_server_command_detach_cb,
4817 q, 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
4819 if (server->config->detach_timeout) {
4820 q = silc_calloc(1, sizeof(*q));
4822 q->sock = (void *)client;
4823 silc_schedule_task_add(server->schedule, 0,
4824 silc_server_command_detach_timeout,
4825 q, server->config->detach_timeout * 60,
4826 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
4829 /* Send reply to the sender */
4830 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
4834 silc_server_command_free(cmd);
4837 /* Server side of WATCH command. */
4839 SILC_SERVER_CMD_FUNC(watch)
4841 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4842 SilcServer server = cmd->server;
4843 char *add_nick, *del_nick;
4844 SilcUInt32 add_nick_len, del_nick_len, tmp_len;
4846 unsigned char hash[16], *tmp;
4847 SilcClientEntry client;
4848 SilcClientID *client_id = NULL;
4850 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WATCH, cmd, 1, 3);
4852 if (server->server_type == SILC_SERVER && !server->standalone) {
4853 if (!cmd->pending) {
4854 /* Send the command to router */
4856 SilcUInt16 old_ident;
4858 old_ident = silc_command_get_ident(cmd->payload);
4859 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4860 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4862 silc_server_packet_send(server, server->router->connection,
4863 SILC_PACKET_COMMAND, cmd->packet->flags,
4864 tmpbuf->data, tmpbuf->len, TRUE);
4866 /* Reprocess this packet after received reply from router */
4867 silc_server_command_pending(server, SILC_COMMAND_WATCH,
4868 silc_command_get_ident(cmd->payload),
4869 silc_server_command_watch,
4870 silc_server_command_dup(cmd));
4871 cmd->pending = TRUE;
4872 silc_command_set_ident(cmd->payload, old_ident);
4873 silc_buffer_free(tmpbuf);
4874 } else if (context2) {
4875 /* Received reply from router, just send same data to the client. */
4876 SilcServerCommandReplyContext reply = context2;
4878 silc_command_get_status(reply->payload, &status, NULL);
4879 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, status);
4885 /* We are router and keep the watch list for local cell */
4887 /* Get the client ID */
4888 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4890 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4891 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4894 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4896 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4897 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
4901 /* Get the client entry which must be in local list */
4902 client = silc_idlist_find_client_by_id(server->local_list,
4903 client_id, TRUE, NULL);
4905 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4906 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
4911 add_nick = silc_argument_get_arg_type(cmd->args, 2, &add_nick_len);
4912 del_nick = silc_argument_get_arg_type(cmd->args, 3, &del_nick_len);
4913 if (!add_nick && !del_nick) {
4914 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4915 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4919 if (add_nick && add_nick_len > 128)
4920 add_nick[128] = '\0';
4921 if (del_nick && del_nick_len > 128)
4922 del_nick[128] = '\0';
4924 memset(nick, 0, sizeof(nick));
4926 /* Add new nickname to be watched in our cell */
4928 if (silc_server_name_bad_chars(add_nick, strlen(add_nick)) == TRUE) {
4929 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4930 SILC_STATUS_ERR_BAD_NICKNAME);
4934 /* Hash the nick, we have the hash saved, not nicks because we can
4935 do one to one mapping to the nick from Client ID hash this way. */
4936 silc_to_lower(add_nick, nick, sizeof(nick) - 1);
4937 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
4939 /* Check whether this client is already watching this nickname */
4940 if (silc_hash_table_find_by_context(server->watcher_list, hash,
4942 /* Nickname is alredy being watched for this client */
4943 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4944 SILC_STATUS_ERR_NICKNAME_IN_USE);
4948 /* Get the nickname from the watcher list and use the same key in
4949 new entries as well. If key doesn't exist then create it. */
4950 if (!silc_hash_table_find(server->watcher_list, hash, (void **)&tmp, NULL))
4951 tmp = silc_memdup(hash, CLIENTID_HASH_LEN);
4953 /* Add the client to the watcher list with the specified nickname hash. */
4954 silc_hash_table_add(server->watcher_list, tmp, client);
4957 /* Delete nickname from watch list */
4959 if (silc_server_name_bad_chars(del_nick, strlen(del_nick)) == TRUE) {
4960 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4961 SILC_STATUS_ERR_BAD_NICKNAME);
4965 /* Hash the nick, we have the hash saved, not nicks because we can
4966 do one to one mapping to the nick from Client ID hash this way. */
4967 silc_to_lower(del_nick, nick, sizeof(nick) - 1);
4968 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
4970 /* Check that this client is watching for this nickname */
4971 if (!silc_hash_table_find_by_context(server->watcher_list, hash,
4972 client, (void **)&tmp)) {
4973 /* Nickname is alredy being watched for this client */
4974 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4975 SILC_STATUS_ERR_NO_SUCH_NICK);
4979 /* Delete the nickname from the watcher list. */
4980 silc_hash_table_del_by_context(server->watcher_list, hash, client);
4982 /* Now check whether there still exists entries with this key, if not
4983 then free the key to not leak memory. */
4984 if (!silc_hash_table_find(server->watcher_list, hash, NULL, NULL))
4988 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4992 silc_free(client_id);
4993 silc_server_command_free(cmd);
4996 /* Server side of SILCOPER command. Client uses this comand to obtain router
4997 operator privileges to this router. */
4999 SILC_SERVER_CMD_FUNC(silcoper)
5001 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5002 SilcServer server = cmd->server;
5003 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5004 unsigned char *username, *auth;
5006 SilcServerConfigAdmin *admin;
5007 SilcIDListData idata = (SilcIDListData)client;
5008 bool result = FALSE;
5009 SilcPublicKey cached_key;
5011 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
5013 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5016 if (server->server_type != SILC_ROUTER) {
5017 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5018 SILC_STATUS_ERR_AUTH_FAILED);
5022 /* Get the username */
5023 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5025 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5026 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5030 /* Get the admin configuration */
5031 admin = silc_server_config_find_admin(server, cmd->sock->ip,
5032 username, client->nickname);
5034 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
5035 username, client->nickname);
5037 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5038 SILC_STATUS_ERR_AUTH_FAILED);
5043 /* Get the authentication payload */
5044 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5046 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5047 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5051 /* Verify the authentication data. If both passphrase and public key
5052 is set then try both of them. */
5053 if (admin->passphrase)
5054 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
5055 admin->passphrase, admin->passphrase_len,
5056 idata->hash, client->id, SILC_ID_CLIENT);
5057 if (!result && admin->publickeys) {
5058 cached_key = silc_server_get_public_key(server, admin->publickeys);
5061 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
5062 cached_key, 0, idata->hash,
5063 client->id, SILC_ID_CLIENT);
5066 /* Authentication failed */
5067 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
5068 SILC_STATUS_ERR_AUTH_FAILED);
5072 /* Client is now router operator */
5073 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
5075 /* Update statistics */
5076 if (client->connection)
5077 server->stat.my_router_ops++;
5078 if (server->server_type == SILC_ROUTER)
5079 server->stat.router_ops++;
5081 /* Send UMODE change to primary router */
5082 if (!server->standalone)
5083 silc_server_send_notify_umode(server, server->router->connection, TRUE,
5084 client->id, client->mode);
5086 /* Check if anyone is watching this nickname */
5087 if (server->server_type == SILC_ROUTER)
5088 silc_server_check_watcher_list(server, client, NULL,
5089 SILC_NOTIFY_TYPE_UMODE_CHANGE);
5091 /* Send reply to the sender */
5092 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5096 silc_server_command_free(cmd);
5099 /* Server side of command BAN. This is used to manage the ban list of the
5100 channel. To add clients and remove clients from the ban list. */
5102 SILC_SERVER_CMD_FUNC(ban)
5104 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5105 SilcServer server = cmd->server;
5106 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5108 SilcChannelEntry channel;
5109 SilcChannelClientEntry chl;
5110 SilcChannelID *channel_id = NULL;
5111 unsigned char *id, *add, *del;
5112 SilcUInt32 id_len, tmp_len;
5113 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5115 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5118 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
5120 /* Get Channel ID */
5121 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
5123 channel_id = silc_id_payload_parse_id(id, id_len, NULL);
5125 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5126 SILC_STATUS_ERR_NO_CHANNEL_ID);
5131 /* Get channel entry. The server must know about the channel since the
5132 client is expected to be on the channel. */
5133 channel = silc_idlist_find_channel_by_id(server->local_list,
5136 channel = silc_idlist_find_channel_by_id(server->global_list,
5139 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5140 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5145 /* Check whether this client is on the channel */
5146 if (!silc_server_client_on_channel(client, channel, &chl)) {
5147 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5148 SILC_STATUS_ERR_NOT_ON_CHANNEL);
5152 /* The client must be at least channel operator. */
5153 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
5154 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5155 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
5159 /* Get the new ban and add it to the ban list */
5160 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5162 if (!channel->ban_list)
5163 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
5165 channel->ban_list = silc_realloc(channel->ban_list,
5166 sizeof(*channel->ban_list) *
5168 strlen(channel->ban_list) + 2));
5169 if (add[tmp_len - 1] == ',')
5170 add[tmp_len - 1] = '\0';
5172 strncat(channel->ban_list, add, tmp_len);
5173 strncat(channel->ban_list, ",", 1);
5176 /* Get the ban to be removed and remove it from the list */
5177 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
5178 if (del && channel->ban_list) {
5179 char *start, *end, *n;
5181 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
5182 silc_free(channel->ban_list);
5183 channel->ban_list = NULL;
5185 start = strstr(channel->ban_list, del);
5186 if (start && strlen(start) >= tmp_len) {
5187 end = start + tmp_len;
5188 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
5189 strncat(n, channel->ban_list, start - channel->ban_list);
5190 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
5192 silc_free(channel->ban_list);
5193 channel->ban_list = n;
5198 /* Send the BAN notify type to our primary router. */
5199 if (!server->standalone && (add || del))
5200 silc_server_send_notify_ban(server, server->router->connection,
5201 server->server_type == SILC_ROUTER ?
5202 TRUE : FALSE, channel, add, del);
5204 /* Send the reply back to the client */
5206 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
5207 SILC_STATUS_OK, 0, ident, 2,
5209 3, channel->ban_list,
5211 strlen(channel->ban_list) -1 : 0);
5212 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5213 packet->data, packet->len, FALSE);
5215 silc_buffer_free(packet);
5218 silc_free(channel_id);
5219 silc_server_command_free(cmd);
5222 /* Server side command of LEAVE. Removes client from a channel. */
5224 SILC_SERVER_CMD_FUNC(leave)
5226 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5227 SilcServer server = cmd->server;
5228 SilcSocketConnection sock = cmd->sock;
5229 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
5230 SilcChannelID *id = NULL;
5231 SilcChannelEntry channel;
5235 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
5237 /* Get Channel ID */
5238 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
5240 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5241 SILC_STATUS_ERR_NO_CHANNEL_ID);
5244 id = silc_id_payload_parse_id(tmp, len, NULL);
5246 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5247 SILC_STATUS_ERR_NO_CHANNEL_ID);
5251 /* Get channel entry */
5252 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5254 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5256 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5257 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5262 /* Check whether this client is on the channel */
5263 if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
5264 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5265 SILC_STATUS_ERR_NOT_ON_CHANNEL);
5269 /* Notify routers that they should remove this client from their list
5270 of clients on the channel. Send LEAVE notify type. */
5271 if (!server->standalone)
5272 silc_server_send_notify_leave(server, server->router->connection,
5273 server->server_type == SILC_ROUTER ?
5274 TRUE : FALSE, channel, id_entry->id);
5276 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
5277 SILC_STATUS_OK, 2, tmp, len);
5279 /* Remove client from channel */
5280 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5282 /* If the channel does not exist anymore we won't send anything */
5285 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5286 /* Re-generate channel key */
5287 if (!silc_server_create_channel_key(server, channel, 0))
5290 /* Send the channel key */
5291 silc_server_send_channel_key(server, NULL, channel,
5292 server->server_type == SILC_ROUTER ?
5293 FALSE : !server->standalone);
5298 silc_server_command_free(cmd);
5301 /* Server side of command USERS. Resolves clients and their USERS currently
5302 joined on the requested channel. The list of Client ID's and their modes
5303 on the channel is sent back. */
5305 SILC_SERVER_CMD_FUNC(users)
5307 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5308 SilcServer server = cmd->server;
5309 SilcChannelEntry channel;
5310 SilcChannelID *id = NULL;
5311 SilcBuffer packet, idp;
5312 unsigned char *channel_id;
5313 SilcUInt32 channel_id_len;
5314 SilcBuffer client_id_list;
5315 SilcBuffer client_mode_list;
5316 unsigned char lc[4];
5317 SilcUInt32 list_count = 0;
5318 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5321 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5323 /* Get Channel ID */
5324 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5326 /* Get channel name */
5327 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5329 if (!channel_id && !channel_name) {
5330 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5331 SILC_STATUS_ERR_NO_CHANNEL_ID);
5336 id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
5338 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5339 SILC_STATUS_ERR_NO_CHANNEL_ID);
5344 /* If we are server and we don't know about this channel we will send
5345 the command to our router. If we know about the channel then we also
5346 have the list of users already. */
5348 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5350 channel = silc_idlist_find_channel_by_name(server->local_list,
5351 channel_name, NULL);
5353 if (!channel || channel->disabled || !channel->users_resolved) {
5354 if (server->server_type != SILC_ROUTER && !server->standalone &&
5358 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5359 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5361 /* Send USERS command */
5362 silc_server_packet_send(server, server->router->connection,
5363 SILC_PACKET_COMMAND, cmd->packet->flags,
5364 tmpbuf->data, tmpbuf->len, TRUE);
5366 /* Reprocess this packet after received reply */
5367 silc_server_command_pending(server, SILC_COMMAND_USERS,
5368 silc_command_get_ident(cmd->payload),
5369 silc_server_command_users,
5370 silc_server_command_dup(cmd));
5371 cmd->pending = TRUE;
5372 silc_command_set_ident(cmd->payload, ident);
5373 silc_buffer_free(tmpbuf);
5378 /* Check the global list as well. */
5380 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5382 channel = silc_idlist_find_channel_by_name(server->global_list,
5383 channel_name, NULL);
5385 /* Channel really does not exist */
5386 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5387 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5392 /* If the channel is private or secret do not send anything, unless the
5393 user requesting this command is on the channel or is server */
5394 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5395 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5396 && !silc_server_client_on_channel(cmd->sock->user_data, channel,
5398 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5399 SILC_STATUS_ERR_NOT_ON_CHANNEL);
5404 /* Get the users list */
5405 silc_server_get_users_on_channel(server, channel, &client_id_list,
5406 &client_mode_list, &list_count);
5409 SILC_PUT32_MSB(list_count, lc);
5412 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5413 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5414 SILC_STATUS_OK, 0, ident, 4,
5415 2, idp->data, idp->len,
5417 4, client_id_list->data,
5418 client_id_list->len,
5419 5, client_mode_list->data,
5420 client_mode_list->len);
5421 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5422 packet->data, packet->len, FALSE);
5424 silc_buffer_free(idp);
5425 silc_buffer_free(packet);
5426 silc_buffer_free(client_id_list);
5427 silc_buffer_free(client_mode_list);
5431 silc_server_command_free(cmd);
5434 /* Server side of command GETKEY. This fetches the client's public key
5435 from the server where to the client is connected. */
5437 SILC_SERVER_CMD_FUNC(getkey)
5439 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5440 SilcServer server = cmd->server;
5442 SilcClientEntry client;
5443 SilcServerEntry server_entry;
5444 SilcClientID *client_id = NULL;
5445 SilcServerID *server_id = NULL;
5446 SilcIDPayload idp = NULL;
5447 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5448 unsigned char *tmp, *pkdata;
5449 SilcUInt32 tmp_len, pklen;
5450 SilcBuffer pk = NULL;
5452 SilcPublicKey public_key;
5454 SILC_LOG_DEBUG(("Start"));
5456 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5458 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5459 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5462 idp = silc_id_payload_parse(tmp, tmp_len);
5464 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5465 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5469 id_type = silc_id_payload_get_type(idp);
5470 if (id_type == SILC_ID_CLIENT) {
5471 client_id = silc_id_payload_get_id(idp);
5473 /* If the client is not found from local list there is no chance it
5474 would be locally connected client so send the command further. */
5475 client = silc_idlist_find_client_by_id(server->local_list,
5476 client_id, TRUE, NULL);
5478 client = silc_idlist_find_client_by_id(server->global_list,
5479 client_id, TRUE, NULL);
5481 if ((!client && !cmd->pending && !server->standalone) ||
5482 (client && !client->connection && !cmd->pending &&
5483 !(client->mode & SILC_UMODE_DETACHED)) ||
5484 (client && !client->data.public_key && !cmd->pending)) {
5486 SilcUInt16 old_ident;
5487 SilcSocketConnection dest_sock;
5489 dest_sock = silc_server_get_client_route(server, NULL, 0,
5490 client_id, NULL, NULL);
5494 old_ident = silc_command_get_ident(cmd->payload);
5495 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5496 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5498 silc_server_packet_send(server, dest_sock,
5499 SILC_PACKET_COMMAND, cmd->packet->flags,
5500 tmpbuf->data, tmpbuf->len, TRUE);
5502 /* Reprocess this packet after received reply from router */
5503 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5504 silc_command_get_ident(cmd->payload),
5505 silc_server_command_getkey,
5506 silc_server_command_dup(cmd));
5507 cmd->pending = TRUE;
5508 silc_command_set_ident(cmd->payload, old_ident);
5509 silc_buffer_free(tmpbuf);
5514 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5515 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5519 /* The client is locally connected, just get the public key and
5520 send it back. If they key does not exist then do not send it,
5521 send just OK reply */
5522 public_key = client->data.public_key;
5527 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5528 pk = silc_buffer_alloc(4 + tmp_len);
5529 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5530 silc_buffer_format(pk,
5531 SILC_STR_UI_SHORT(tmp_len),
5532 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5533 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5539 } else if (id_type == SILC_ID_SERVER) {
5540 server_id = silc_id_payload_get_id(idp);
5542 /* If the server is not found from local list there is no chance it
5543 would be locally connected server so send the command further. */
5544 server_entry = silc_idlist_find_server_by_id(server->local_list,
5545 server_id, TRUE, NULL);
5547 server_entry = silc_idlist_find_server_by_id(server->global_list,
5548 server_id, TRUE, NULL);
5550 if (server_entry != server->id_entry &&
5551 ((!server_entry && !cmd->pending && !server->standalone) ||
5552 (server_entry && !server_entry->connection && !cmd->pending &&
5553 !server->standalone) ||
5554 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5555 !server->standalone))) {
5557 SilcUInt16 old_ident;
5559 old_ident = silc_command_get_ident(cmd->payload);
5560 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5561 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5563 silc_server_packet_send(server, server->router->connection,
5564 SILC_PACKET_COMMAND, cmd->packet->flags,
5565 tmpbuf->data, tmpbuf->len, TRUE);
5567 /* Reprocess this packet after received reply from router */
5568 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5569 silc_command_get_ident(cmd->payload),
5570 silc_server_command_getkey,
5571 silc_server_command_dup(cmd));
5572 cmd->pending = TRUE;
5573 silc_command_set_ident(cmd->payload, old_ident);
5574 silc_buffer_free(tmpbuf);
5578 if (!server_entry) {
5579 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5580 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5584 /* If they key does not exist then do not send it, send just OK reply */
5585 public_key = (!server_entry->data.public_key ?
5586 (server_entry == server->id_entry ? server->public_key :
5587 NULL) : server_entry->data.public_key);
5592 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5593 pk = silc_buffer_alloc(4 + tmp_len);
5594 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5595 silc_buffer_format(pk,
5596 SILC_STR_UI_SHORT(tmp_len),
5597 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5598 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5608 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5609 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5610 SILC_STATUS_OK, 0, ident,
5614 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5615 packet->data, packet->len, FALSE);
5616 silc_buffer_free(packet);
5619 silc_buffer_free(pk);
5623 silc_id_payload_free(idp);
5624 silc_free(client_id);
5625 silc_free(server_id);
5626 silc_server_command_free(cmd);
5630 /* Private range commands, specific to this implementation */
5632 /* Server side command of CONNECT. Connects us to the specified remote
5633 server or router. */
5635 SILC_SERVER_CMD_FUNC(connect)
5637 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5638 SilcServer server = cmd->server;
5639 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5640 unsigned char *tmp, *host;
5642 SilcUInt32 port = SILC_PORT;
5644 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
5646 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5649 /* Check whether client has the permissions. */
5650 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5651 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5652 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5653 SILC_STATUS_ERR_NO_SERVER_PRIV);
5657 if (server->server_type == SILC_ROUTER &&
5658 client->mode & SILC_UMODE_SERVER_OPERATOR) {
5659 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5660 SILC_STATUS_ERR_NO_ROUTER_PRIV);
5664 /* Get the remote server */
5665 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5667 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5668 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5673 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5675 SILC_GET32_MSB(port, tmp);
5677 /* Create the connection. It is done with timeout and is async. */
5678 silc_server_create_connection(server, host, port);
5680 /* Send reply to the sender */
5681 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5685 silc_server_command_free(cmd);
5688 /* Server side command of CLOSE. Closes connection to a specified server. */
5690 SILC_SERVER_CMD_FUNC(close)
5692 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5693 SilcServer server = cmd->server;
5694 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5695 SilcServerEntry server_entry;
5696 SilcSocketConnection sock;
5699 unsigned char *name;
5700 SilcUInt32 port = SILC_PORT;
5702 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
5704 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5707 /* Check whether client has the permissions. */
5708 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5709 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5710 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5711 SILC_STATUS_ERR_NO_SERVER_PRIV);
5715 /* Get the remote server */
5716 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5718 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5719 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5724 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5726 SILC_GET32_MSB(port, tmp);
5728 server_entry = silc_idlist_find_server_by_conn(server->local_list,
5729 name, port, FALSE, NULL);
5731 server_entry = silc_idlist_find_server_by_conn(server->global_list,
5732 name, port, FALSE, NULL);
5733 if (!server_entry) {
5734 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5735 SILC_STATUS_ERR_NO_SERVER_ID);
5739 /* Send reply to the sender */
5740 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5743 /* Close the connection to the server */
5744 sock = (SilcSocketConnection)server_entry->connection;
5746 /* If we shutdown primary router connection manually then don't trigger
5747 any reconnect or backup router connections, by setting the router
5749 if (server->router == server_entry) {
5750 server->id_entry->router = NULL;
5751 server->router = NULL;
5752 server->standalone = TRUE;
5754 silc_server_free_sock_user_data(server, sock, NULL);
5755 silc_server_close_connection(server, sock);
5758 silc_server_command_free(cmd);
5761 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
5762 active connections. */
5764 SILC_SERVER_CMD_FUNC(shutdown)
5766 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5767 SilcServer server = cmd->server;
5768 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5770 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
5772 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5775 /* Check whether client has the permission. */
5776 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5777 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5778 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5779 SILC_STATUS_ERR_NO_SERVER_PRIV);
5783 /* Send reply to the sender */
5784 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5787 /* Then, gracefully, or not, bring the server down. */
5788 silc_server_stop(server);
5792 silc_server_command_free(cmd);