5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2008 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; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
21 #include "serverincludes.h"
22 #include "server_internal.h"
24 static int silc_server_is_registered(SilcServer server,
25 SilcPacketStream sock,
26 SilcServerCommandContext cmd,
29 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
34 silc_server_command_send_status_data(SilcServerCommandContext cmd,
39 const unsigned char *arg,
42 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
43 SilcServerCommandReplyContext cmdr,
45 SILC_TASK_CALLBACK(silc_server_command_process_timeout);
47 /* Server command list. */
48 SilcServerCommand silc_command_list[] =
50 SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
51 SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
52 SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
53 SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
54 SILC_SERVER_CMD(list, LIST, SILC_CF_LAG_STRICT | SILC_CF_REG),
55 SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
56 SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
57 SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
58 SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG_STRICT | SILC_CF_REG | SILC_CF_OPER),
59 SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
60 SILC_SERVER_CMD(stats, STATS, SILC_CF_LAG | SILC_CF_REG),
61 SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
62 SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
63 SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG_STRICT | SILC_CF_REG),
64 SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
65 SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
66 SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG_STRICT | SILC_CF_REG),
67 SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
68 SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
69 SILC_SERVER_CMD(ban, BAN, SILC_CF_LAG_STRICT | SILC_CF_REG),
70 SILC_SERVER_CMD(detach, DETACH, SILC_CF_LAG_STRICT | SILC_CF_REG),
71 SILC_SERVER_CMD(watch, WATCH, SILC_CF_LAG | SILC_CF_REG),
72 SILC_SERVER_CMD(silcoper, SILCOPER,
73 SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
74 SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
75 SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
76 SILC_SERVER_CMD(getkey, GETKEY, SILC_CF_LAG | SILC_CF_REG),
77 SILC_SERVER_CMD(service, SERVICE, SILC_CF_LAG_STRICT | SILC_CF_REG),
79 SILC_SERVER_CMD(connect, PRIV_CONNECT,
80 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
81 SILC_SERVER_CMD(close, PRIV_CLOSE,
82 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
83 SILC_SERVER_CMD(shutdown, PRIV_SHUTDOWN, SILC_CF_LAG | SILC_CF_REG |
89 /* Performs several checks to the command. It first checks whether this
90 command was called as pending command callback. If it was then it checks
91 whether error occurred in the command reply where the pending command
94 It also checks that the requested command includes correct amount
96 #define SILC_SERVER_COMMAND_CHECK(command, context, min, max) \
100 if (silc_server_command_pending_error_check(cmd, context2, command)) { \
101 SILC_LOG_DEBUG(("Error occurred in command reply, command not called")); \
102 silc_server_command_free(cmd); \
106 _argc = silc_argument_get_arg_num(cmd->args); \
108 SILC_LOG_DEBUG(("Not enough parameters in command")); \
109 silc_server_command_send_status_reply(cmd, command, \
110 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, \
112 silc_server_command_free(cmd); \
116 SILC_LOG_DEBUG(("Too many parameters in command")); \
117 silc_server_command_send_status_reply(cmd, command, \
118 SILC_STATUS_ERR_TOO_MANY_PARAMS, \
120 silc_server_command_free(cmd); \
125 /* Returns TRUE if the connection is registered. Unregistered connections
126 usually cannot send commands hence the check. */
128 static int silc_server_is_registered(SilcServer server,
129 SilcPacketStream sock,
130 SilcServerCommandContext cmd,
133 SilcIDListData idata = silc_packet_get_context(sock);
138 if (idata->status & SILC_IDLIST_STATUS_REGISTERED)
141 silc_server_command_send_status_reply(cmd, command,
142 SILC_STATUS_ERR_NOT_REGISTERED, 0);
146 /* Internal context to hold data when executed command with timeout. */
148 SilcServerCommandContext ctx;
149 SilcServerCommand *cmd;
150 } *SilcServerCommandTimeout;
152 /* Timeout callback to process commands with timeout for client. Client's
153 commands are always executed with timeout. */
155 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
157 SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
158 SilcClientEntry client = silc_packet_get_context(timeout->ctx->sock);
161 SILC_LOG_DEBUG(("Client entry is invalid"));
162 silc_server_command_free(timeout->ctx);
167 /* Update access time */
168 client->last_command = time(NULL);
170 if (!(timeout->cmd->flags & SILC_CF_REG)) {
171 SILC_LOG_DEBUG(("Calling %s command",
172 silc_get_command_name(timeout->cmd->cmd)));
173 timeout->cmd->cb(timeout->ctx, NULL);
174 } else if (silc_server_is_registered(timeout->ctx->server,
177 timeout->cmd->cmd)) {
178 SILC_LOG_DEBUG(("Calling %s command",
179 silc_get_command_name(timeout->cmd->cmd)));
180 timeout->cmd->cb(timeout->ctx, NULL);
182 SILC_LOG_DEBUG(("Client is not registered"));
183 silc_server_command_free(timeout->ctx);
189 /* Processes received command packet. */
191 void silc_server_command_process(SilcServer server,
192 SilcPacketStream sock,
195 SilcIDListData idata = silc_packet_get_context(sock);
196 SilcServerCommandContext ctx;
197 SilcServerCommand *cmd;
203 /* Allocate command context. This must be free'd by the
204 command routine receiving it. */
205 ctx = silc_server_command_alloc();
206 ctx->server = server;
208 ctx->packet = packet; /* Save original packet */
209 silc_packet_stream_ref(sock);
211 /* Parse the command payload in the packet */
212 ctx->payload = silc_command_payload_parse(packet->buffer.data,
213 silc_buffer_len(&packet->buffer));
215 SILC_LOG_ERROR(("Bad command payload"));
216 silc_packet_free(packet);
217 silc_packet_stream_unref(ctx->sock);
221 ctx->args = silc_command_get_args(ctx->payload);
223 /* Get the command */
224 command = silc_command_get(ctx->payload);
225 for (cmd = silc_command_list; cmd->cb; cmd++)
226 if (cmd->cmd == command)
229 if (!cmd || !cmd->cb) {
230 SILC_LOG_DEBUG(("Unknown command %d", command));
231 silc_server_command_send_status_reply(ctx, command,
232 SILC_STATUS_ERR_UNKNOWN_COMMAND, 0);
233 silc_packet_free(packet);
234 silc_packet_stream_unref(ctx->sock);
239 /* Execute client's commands always with timeout. Normally they are
240 executed with zero (0) timeout but if client is sending command more
241 frequently than once in 2 seconds, then the timeout may be 0 to 2
243 if (idata->conn_type == SILC_CONN_CLIENT) {
244 SilcClientEntry client = silc_packet_get_context(sock);
245 SilcServerCommandTimeout timeout;
248 timeout = silc_calloc(1, sizeof(*timeout));
252 if (client->last_command && (time(NULL) - client->last_command) < 2) {
253 client->fast_command++;
256 if (client->fast_command - 2 <= 0)
257 client->fast_command = 0;
259 client->fast_command -= 2;
263 if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
264 (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
265 silc_schedule_task_add_timeout(
267 silc_server_command_process_timeout, timeout,
268 (client->fast_command < 3 ? 0 :
269 2 - (time(NULL) - client->last_command)),
270 (client->fast_command < 3 ? 200000 : 0));
272 silc_schedule_task_add_timeout(server->schedule,
273 silc_server_command_process_timeout,
278 /* Execute for server */
280 if (!(cmd->flags & SILC_CF_REG)) {
281 SILC_LOG_DEBUG(("Calling %s command", silc_get_command_name(cmd->cmd)));
283 } else if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) {
284 SILC_LOG_DEBUG(("Calling %s command", silc_get_command_name(cmd->cmd)));
287 SILC_LOG_DEBUG(("Server is not registered"));
288 silc_server_command_free(ctx);
292 /* Allocate Command Context */
294 SilcServerCommandContext silc_server_command_alloc()
296 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
301 /* Free's the command context allocated before executing the command */
303 void silc_server_command_free(SilcServerCommandContext ctx)
306 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
308 if (ctx->users < 1) {
310 silc_command_payload_free(ctx->payload);
312 silc_packet_free(ctx->packet);
314 silc_packet_stream_unref(ctx->sock);
319 /* Duplicate Command Context by adding reference counter. The context won't
320 be free'd untill it hits zero. */
322 SilcServerCommandContext
323 silc_server_command_dup(SilcServerCommandContext ctx)
326 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
331 /* Timeout for pending command. If reply to pending command never arrives
332 this is called to free resources. */
334 SILC_TASK_CALLBACK(silc_server_command_pending_timeout)
336 SilcServer server = app_context;
337 SilcServerCommandPending *reply = context;
338 SilcServerCommandReplyContext cmdr;
342 SILC_LOG_DEBUG(("Timeout pending command"));
344 /* Allocate temporary and bogus command reply context */
345 cmdr = silc_calloc(1, sizeof(*cmdr));
346 cmdr->server = server;
347 cmdr->ident = reply->ident;
349 /* Check for pending commands and mark to be exeucted */
351 silc_server_command_pending_check(server, reply->reply_cmd,
352 reply->ident, &cmdr->callbacks_count);
354 /* Create bogus command reply with an error inside */
356 silc_command_reply_payload_encode_va(reply->reply_cmd ? reply->reply_cmd :
357 SILC_COMMAND_RESERVED,
358 SILC_STATUS_ERR_TIMEDOUT, 0,
360 cmdr->payload = silc_command_payload_parse(tmpreply->data,
361 silc_buffer_len(tmpreply));
362 silc_buffer_free(tmpreply);
364 /* Call all callbacks. Same as SILC_SERVER_PENDING_EXEC macro. */
365 for (i = 0; i < cmdr->callbacks_count; i++)
366 if (cmdr->callbacks[i].callback)
367 (*cmdr->callbacks[i].callback)(cmdr->callbacks[i].context, cmdr);
369 silc_server_command_pending_del(server, reply->reply_cmd, reply->ident);
370 silc_server_command_reply_free(cmdr);
373 /* Add new pending command to be executed when reply to a command has been
374 received. The `reply_cmd' is the command that will call the `callback'
375 with `context' when reply has been received. It can be SILC_COMMAND_NONE
376 to match any command with the `ident'. If `ident' is non-zero
377 the `callback' will be executed when received reply with command
378 identifier `ident'. If there already exists pending command for the
379 specified command, ident, callback and context this function has no
382 SilcBool silc_server_command_pending(SilcServer server,
383 SilcCommand reply_cmd,
385 SilcCommandCb callback,
388 return silc_server_command_pending_timed(server, reply_cmd, ident, callback,
392 /* Same as silc_server_command_pending with specific timeout for pending
393 commands. If the `timeout' is zero default timeout is used. */
395 SilcBool silc_server_command_pending_timed(SilcServer server,
396 SilcCommand reply_cmd,
398 SilcCommandCb callback,
402 SilcServerCommandPending *reply;
404 /* Check whether identical pending already exists for same command,
405 ident, callback and callback context. If it does then it would be
406 error to register it again. */
407 silc_dlist_start(server->pending_commands);
408 while ((reply = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
409 if (reply->reply_cmd == reply_cmd && reply->ident == ident &&
410 reply->callback == callback && reply->context == context)
414 reply = silc_calloc(1, sizeof(*reply));
415 reply->reply_cmd = reply_cmd;
416 reply->ident = ident;
417 reply->context = context;
418 reply->callback = callback;
420 silc_schedule_task_add_timeout(server->schedule,
421 silc_server_command_pending_timeout, reply,
422 timeout ? timeout : 12, 0);
423 silc_dlist_add(server->pending_commands, reply);
428 /* Deletes pending command by reply command type. */
430 void silc_server_command_pending_del(SilcServer server,
431 SilcCommand reply_cmd,
434 SilcServerCommandPending *r;
436 silc_dlist_start(server->pending_commands);
437 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
438 if ((r->reply_cmd == reply_cmd || (r->reply_cmd == SILC_COMMAND_NONE &&
440 && r->ident == ident) {
441 silc_dlist_del(server->pending_commands, r);
443 silc_schedule_task_del(server->schedule, r->timeout);
449 /* Checks for pending commands and marks callbacks to be called from
450 the command reply function. Returns TRUE if there were pending command. */
452 SilcServerCommandPendingCallbacks
453 silc_server_command_pending_check(SilcServer server,
456 SilcUInt32 *callbacks_count)
458 SilcServerCommandPending *r;
459 SilcServerCommandPendingCallbacks callbacks = NULL;
462 silc_dlist_start(server->pending_commands);
463 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
464 if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE)
465 && r->ident == ident) {
466 callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
467 callbacks[i].context = r->context;
468 callbacks[i].callback = r->callback;
469 r->reply_check = TRUE;
474 *callbacks_count = i;
478 /* Sends simple status message as command reply packet */
481 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
489 cmd->server->stat.commands_sent++;
491 SILC_LOG_DEBUG(("Sending command status %d", status));
494 silc_command_reply_payload_encode_va(command, status, error,
495 silc_command_get_ident(cmd->payload),
497 silc_server_packet_send(cmd->server, cmd->sock,
498 SILC_PACKET_COMMAND_REPLY, 0,
499 buffer->data, silc_buffer_len(buffer));
500 silc_buffer_free(buffer);
503 /* Sends command status reply with one extra argument. The argument
504 type must be sent as argument. */
507 silc_server_command_send_status_data(SilcServerCommandContext cmd,
512 const unsigned char *arg,
518 cmd->server->stat.commands_sent++;
520 SILC_LOG_DEBUG(("Sending command status %d", status));
523 silc_command_reply_payload_encode_va(command, status, 0,
524 silc_command_get_ident(cmd->payload),
525 1, arg_type, arg, arg_len);
526 silc_server_packet_send(cmd->server, cmd->sock,
527 SILC_PACKET_COMMAND_REPLY, 0,
528 buffer->data, silc_buffer_len(buffer));
529 silc_buffer_free(buffer);
533 silc_server_command_send_status_data2(SilcServerCommandContext cmd,
537 SilcUInt32 arg_type1,
538 const unsigned char *arg1,
540 SilcUInt32 arg_type2,
541 const unsigned char *arg2,
547 cmd->server->stat.commands_sent++;
549 SILC_LOG_DEBUG(("Sending command status %d", status));
552 silc_command_reply_payload_encode_va(command, status, 0,
553 silc_command_get_ident(cmd->payload),
554 2, arg_type1, arg1, arg_len1,
555 arg_type2, arg2, arg_len2);
556 silc_server_packet_send(cmd->server, cmd->sock,
557 SILC_PACKET_COMMAND_REPLY, 0,
558 buffer->data, silc_buffer_len(buffer));
559 silc_buffer_free(buffer);
562 /* This function can be called to check whether in the command reply
563 an error occurred. This function has no effect if this is called
564 when the command function was not called as pending command callback.
565 This returns TRUE if error had occurred. */
568 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
569 SilcServerCommandReplyContext cmdr,
572 if (!cmd->pending || !cmdr)
575 if (!silc_command_get_status(cmdr->payload, NULL, NULL)) {
579 cmd->server->stat.commands_sent++;
581 /* Send the same command reply payload */
582 silc_command_set_command(cmdr->payload, silc_command_get(cmd->payload));
583 silc_command_set_ident(cmdr->payload,
584 silc_command_get_ident(cmd->payload));
585 buffer = silc_command_payload_encode_payload(cmdr->payload);
586 silc_server_packet_send(cmd->server, cmd->sock,
587 SILC_PACKET_COMMAND_REPLY, 0,
588 buffer->data, silc_buffer_len(buffer));
589 silc_buffer_free(buffer);
596 /* Server side of command WHOIS. */
598 SILC_SERVER_CMD_FUNC(whois)
600 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
601 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 256);
602 silc_server_query_command(cmd->server, SILC_COMMAND_WHOIS, cmd, NULL);
603 silc_server_command_free(cmd);
606 /* Server side of command WHOWAS. */
608 SILC_SERVER_CMD_FUNC(whowas)
610 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
611 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
612 silc_server_query_command(cmd->server, SILC_COMMAND_WHOWAS, cmd, NULL);
613 silc_server_command_free(cmd);
616 /* Server side of command IDENTIFY. */
618 SILC_SERVER_CMD_FUNC(identify)
620 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
621 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 256);
622 silc_server_query_command(cmd->server, SILC_COMMAND_IDENTIFY, cmd, NULL);
623 silc_server_command_free(cmd);
626 /* Server side of command NICK. Sets nickname for user. Setting
627 nickname causes generation of a new client ID for the client. The
628 new client ID is sent to the client after changing the nickname. */
630 SILC_SERVER_CMD_FUNC(nick)
632 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
633 SilcClientEntry client = silc_packet_get_context(cmd->sock);
634 SilcServer server = cmd->server;
635 SilcBuffer nidp, oidp = NULL;
636 SilcClientID *new_id;
638 unsigned char *nick, *nickc = NULL;
639 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
641 if (client->data.conn_type != SILC_CONN_CLIENT || !client)
644 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
647 nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
649 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
650 SILC_STATUS_ERR_BAD_NICKNAME, 0);
654 /* Truncate over long nicks */
655 if (nick_len > 128) {
657 nick[nick_len - 1] = '\0';
660 /* Check for valid nickname string. This is cached, original is saved
661 in the client context. */
662 nickc = silc_identifier_check(nick, nick_len, SILC_STRING_UTF8, 128, NULL);
664 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
665 SILC_STATUS_ERR_BAD_NICKNAME, 0);
669 /* Check for same nickname */
670 if (strlen(client->nickname) == nick_len &&
671 !memcmp(client->nickname, nick, nick_len)) {
672 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
677 /* Create new Client ID */
678 if (!silc_id_create_client_id(cmd->server, cmd->server->id,
680 cmd->server->md5hash,
681 nickc, strlen(nickc), &new_id)) {
682 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
683 SILC_STATUS_ERR_BAD_NICKNAME, 0);
688 /* Send notify about nickname change to our router. We send the new
689 ID and ask to replace it with the old one. If we are router the
690 packet is broadcasted. Send NICK_CHANGE notify. */
691 silc_server_send_notify_nick_change(server, SILC_PRIMARY_ROUTE(server),
692 SILC_BROADCAST(server), client->id,
695 /* Check if anyone is watching the old nickname */
696 if (server->server_type == SILC_ROUTER)
697 silc_server_check_watcher_list(server, client, nick,
698 SILC_NOTIFY_TYPE_NICK_CHANGE);
700 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
702 /* Update client entry */
703 silc_idcache_update_by_context(server->local_list->clients, client,
704 new_id, nickc, TRUE);
706 silc_free(client->nickname);
707 client->nickname = strdup(nick);
709 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
711 /* Send NICK_CHANGE notify to the client's channels */
712 silc_server_send_notify_on_channels(server, NULL, client,
713 SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
714 oidp->data, silc_buffer_len(oidp),
715 nidp->data, silc_buffer_len(nidp),
717 strlen(client->nickname));
719 /* Check if anyone is watching the new nickname */
720 if (server->server_type == SILC_ROUTER)
721 silc_server_check_watcher_list(server, client, NULL,
722 SILC_NOTIFY_TYPE_NICK_CHANGE);
725 /* Send the new Client ID as reply command back to client */
726 silc_server_send_command_reply(cmd->server, cmd->sock,
728 SILC_STATUS_OK, 0, ident, 2,
729 2, nidp->data, silc_buffer_len(nidp),
731 silc_buffer_free(nidp);
733 silc_buffer_free(oidp);
736 silc_server_command_free(cmd);
739 /* Sends the LIST command reply */
742 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
743 SilcChannelEntry *lch,
744 SilcUInt32 lch_count,
745 SilcChannelEntry *gch,
746 SilcUInt32 gch_count)
750 SilcChannelEntry entry;
752 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
754 unsigned char usercount[4];
756 int valid_lcount = 0, valid_rcount = 0;
758 for (i = 0; i < lch_count; i++) {
759 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
764 for (i = 0; i < gch_count; i++) {
765 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
771 if (!lch_count && !gch_count) {
772 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
777 status = SILC_STATUS_OK;
778 if ((lch_count + gch_count) > 1)
779 status = SILC_STATUS_LIST_START;
782 for (i = 0, k = 0; i < lch_count; i++) {
788 status = SILC_STATUS_LIST_ITEM;
789 if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
790 status = SILC_STATUS_LIST_END;
792 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
794 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
796 memset(usercount, 0, sizeof(usercount));
798 topic = entry->topic;
799 users = silc_hash_table_count(entry->user_list);
800 SILC_PUT32_MSB(users, usercount);
804 silc_server_send_command_reply(cmd->server, cmd->sock, SILC_COMMAND_LIST,
806 2, idp->data, silc_buffer_len(idp),
807 3, entry->channel_name,
808 strlen(entry->channel_name),
809 4, topic, topic ? strlen(topic) : 0,
811 silc_buffer_free(idp);
816 for (i = 0, k = 0; i < gch_count; i++) {
822 status = SILC_STATUS_LIST_ITEM;
823 if (valid_rcount > 1 && k == valid_rcount - 1)
824 status = SILC_STATUS_LIST_END;
826 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
828 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
830 memset(usercount, 0, sizeof(usercount));
832 topic = entry->topic;
833 users = entry->user_count;
834 SILC_PUT32_MSB(users, usercount);
838 silc_server_send_command_reply(cmd->server, cmd->sock, SILC_COMMAND_LIST,
840 2, idp->data, silc_buffer_len(idp),
841 3, entry->channel_name,
842 strlen(entry->channel_name),
843 4, topic, topic ? strlen(topic) : 0,
845 silc_buffer_free(idp);
850 /* Server side of LIST command. This lists the channel of the requested
851 server. Secret channels are not listed. */
853 SILC_SERVER_CMD_FUNC(list)
855 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
856 SilcServer server = cmd->server;
858 SilcChannelID *channel_id = NULL;
859 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
860 SilcUInt32 lch_count = 0, gch_count = 0;
862 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
864 /* If we are normal server, send the command to router, since we
865 want to know all channels in the network. */
866 if (!cmd->pending && server->server_type != SILC_ROUTER &&
867 !server->standalone) {
869 SilcUInt16 old_ident;
872 cmd->server->stat.commands_sent++;
874 old_ident = silc_command_get_ident(cmd->payload);
875 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
876 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
877 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
878 SILC_PACKET_COMMAND, cmd->packet->flags,
879 tmpbuf->data, silc_buffer_len(tmpbuf));
881 /* Reprocess this packet after received reply from router */
882 silc_server_command_pending(server, SILC_COMMAND_LIST,
883 silc_command_get_ident(cmd->payload),
884 silc_server_command_list,
885 silc_server_command_dup(cmd));
887 silc_command_set_ident(cmd->payload, old_ident);
888 silc_buffer_free(tmpbuf);
893 if (silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL))
894 channel_id = SILC_ID_GET_ID(id);
896 /* Get the channels from local list */
897 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
900 /* Get the channels from global list */
901 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
905 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
906 gchannels, gch_count);
908 silc_free(lchannels);
909 silc_free(gchannels);
912 silc_server_command_free(cmd);
915 /* Server side of TOPIC command. Sets topic for channel and/or returns
916 current topic to client. */
918 SILC_SERVER_CMD_FUNC(topic)
920 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
921 SilcServer server = cmd->server;
922 SilcClientEntry client = silc_packet_get_context(cmd->sock);
924 SilcChannelEntry channel;
925 SilcChannelClientEntry chl;
928 SilcUInt32 argc, tmp_len;
929 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
931 if (client->data.conn_type != SILC_CONN_CLIENT || !client)
934 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
936 argc = silc_argument_get_arg_num(cmd->args);
939 if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
940 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
941 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
945 /* Check whether the channel exists */
946 channel = silc_idlist_find_channel_by_id(server->local_list,
947 SILC_ID_GET_ID(id), NULL);
949 channel = silc_idlist_find_channel_by_id(server->global_list,
950 SILC_ID_GET_ID(id), NULL);
952 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
953 silc_server_command_send_status_data(cmd, SILC_COMMAND_TOPIC,
954 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
962 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
964 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
965 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
971 tmp[tmp_len - 1] = '\0';
974 if (!silc_utf8_valid(tmp, tmp_len)) {
975 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
976 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
981 /* See whether the client is on channel and has rights to change topic */
982 if (!silc_server_client_on_channel(client, channel, &chl)) {
983 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
984 silc_server_command_send_status_data(cmd, SILC_COMMAND_TOPIC,
985 SILC_STATUS_ERR_NOT_ON_CHANNEL,
990 if (channel->mode & SILC_CHANNEL_MODE_TOPIC &&
991 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
992 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
993 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
994 silc_server_command_send_status_data(cmd, SILC_COMMAND_TOPIC,
995 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
1000 if (!channel->topic || strcmp(channel->topic, tmp)) {
1001 /* Set the topic for channel */
1002 silc_free(channel->topic);
1003 channel->topic = strdup(tmp);
1005 /* Send TOPIC_SET notify type to the network */
1006 silc_server_send_notify_topic_set(server, SILC_PRIMARY_ROUTE(server),
1007 SILC_BROADCAST(server), channel,
1008 client->id, SILC_ID_CLIENT,
1011 /* Send notify about topic change to all clients on the channel */
1012 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1013 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
1014 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
1015 idp->data, silc_buffer_len(idp),
1017 strlen(channel->topic));
1018 silc_buffer_free(idp);
1022 /* Send the topic to client as reply packet */
1023 idp = silc_id_payload_encode(SILC_ID_GET_ID(id), SILC_ID_CHANNEL);
1024 silc_server_send_command_reply(cmd->server, cmd->sock, SILC_COMMAND_TOPIC,
1025 SILC_STATUS_OK, 0, ident, 2,
1026 2, idp->data, silc_buffer_len(idp),
1029 strlen(channel->topic) : 0);
1030 silc_buffer_free(idp);
1033 silc_server_command_free(cmd);
1036 /* Server side of INVITE command. Invites some client to join some channel.
1037 This command is also used to manage the invite list of the channel. */
1039 SILC_SERVER_CMD_FUNC(invite)
1041 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1042 SilcServer server = cmd->server;
1043 SilcPacketStream sock = cmd->sock, dest_sock;
1044 SilcChannelClientEntry chl;
1045 SilcClientEntry sender, dest;
1046 SilcChannelEntry channel;
1048 SilcIDListData idata;
1049 SilcArgumentPayload args;
1050 SilcHashTableList htl;
1051 SilcBuffer list, tmp2;
1052 SilcBufferStruct alist;
1053 unsigned char *tmp, *atype = NULL;
1054 SilcUInt32 len, len2, ttype;
1056 SilcUInt16 argc = 0, ident = silc_command_get_ident(cmd->payload);
1058 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
1060 /* Get Channel ID */
1061 if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
1062 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1063 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
1067 /* Get the channel entry */
1068 channel = silc_idlist_find_channel_by_id(server->local_list,
1069 SILC_ID_GET_ID(id), NULL);
1071 channel = silc_idlist_find_channel_by_id(server->global_list,
1072 SILC_ID_GET_ID(id), NULL);
1074 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1075 silc_server_command_send_status_data(cmd, SILC_COMMAND_INVITE,
1076 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
1082 /* Check whether the sender of this command is on the channel. */
1083 sender = silc_packet_get_context(sock);
1084 if (!sender || !silc_server_client_on_channel(sender, channel, &chl)) {
1085 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1086 silc_server_command_send_status_data(cmd, SILC_COMMAND_INVITE,
1087 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
1092 /* Check whether the channel is invite-only channel. If yes then the
1093 sender of this command must be at least channel operator. */
1094 if (channel->mode & SILC_CHANNEL_MODE_INVITE &&
1095 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
1096 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
1097 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1098 silc_server_command_send_status_data(cmd, SILC_COMMAND_INVITE,
1099 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
1104 /* Get destination client ID */
1105 if (silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id2, NULL)) {
1108 /* Get the client entry */
1109 dest = silc_server_query_client(server, SILC_ID_GET_ID(id2),
1112 if (server->server_type != SILC_SERVER || !resolve || cmd->pending) {
1113 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1114 silc_server_command_send_status_data(
1115 cmd, SILC_COMMAND_INVITE,
1116 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0,
1121 /* The client info is being resolved. Reprocess this packet after
1122 receiving the reply to the query. */
1123 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1125 silc_server_command_invite,
1126 silc_server_command_dup(cmd));
1127 cmd->pending = TRUE;
1131 /* Check whether the requested client is already on the channel. */
1132 if (silc_server_client_on_channel(dest, channel, NULL)) {
1133 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1134 atype = silc_argument_get_arg_type(cmd->args, 1, &len2);
1135 silc_server_command_send_status_data2(cmd, SILC_COMMAND_INVITE,
1136 SILC_STATUS_ERR_USER_ON_CHANNEL,
1142 /* Get route to the client */
1143 dest_sock = silc_server_get_client_route(server, NULL, 0,
1144 SILC_ID_GET_ID(id2),
1147 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1148 silc_server_command_send_status_data(cmd, SILC_COMMAND_INVITE,
1149 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1154 /* Add the client to the invite list */
1156 /* Allocate hash table for invite list if it doesn't exist yet */
1157 if (!channel->invite_list)
1158 channel->invite_list =
1159 silc_hash_table_alloc(0, silc_hash_ptr,
1161 silc_server_inviteban_destruct, channel, TRUE);
1163 /* Check if the ID is in the list already */
1164 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1165 silc_hash_table_list(channel->invite_list, &htl);
1166 while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) {
1167 if (SILC_PTR_TO_32(type) == 3 && !memcmp(tmp2->data, tmp, len)) {
1172 silc_hash_table_list_reset(&htl);
1174 /* Add new Client ID to invite list */
1176 list = silc_buffer_alloc_size(len);
1177 silc_buffer_put(list, tmp, len);
1178 silc_hash_table_add(channel->invite_list, (void *)3, list);
1181 if (!(dest->mode & SILC_UMODE_BLOCK_INVITE)) {
1182 /* Send notify to the client that is invited to the channel */
1183 SilcBuffer idp, idp2;
1184 idp = silc_id_payload_encode(SILC_ID_GET_ID(id), SILC_ID_CHANNEL);
1185 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1186 silc_server_send_notify_dest(server, dest_sock, FALSE,
1187 SILC_ID_GET_ID(id2), SILC_ID_CLIENT,
1188 SILC_NOTIFY_TYPE_INVITE, 3,
1189 idp->data, silc_buffer_len(idp),
1190 channel->channel_name,
1191 strlen(channel->channel_name),
1192 idp2->data, silc_buffer_len(idp2));
1193 silc_buffer_free(idp);
1194 silc_buffer_free(idp2);
1198 /* Get the invite information */
1199 tmp = silc_argument_get_arg_type(cmd->args, 4, &len2);
1200 if (tmp && len2 > 2) {
1201 /* Parse the arguments to see they are constructed correctly */
1202 SILC_GET16_MSB(argc, tmp);
1203 args = silc_argument_payload_parse(tmp + 2, len2 - 2, argc);
1205 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1206 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1211 /* Get the type of action */
1212 atype = silc_argument_get_arg_type(cmd->args, 3, &len);
1213 if (atype && len == 1) {
1214 if (atype[0] == 0x00) {
1215 /* Allocate hash table for invite list if it doesn't exist yet */
1216 if (!channel->invite_list)
1217 channel->invite_list =
1218 silc_hash_table_alloc(0, silc_hash_ptr,
1220 silc_server_inviteban_destruct, channel,
1223 /* Check for resource limit */
1224 if (silc_hash_table_count(channel->invite_list) > 64) {
1225 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1226 SILC_STATUS_ERR_RESOURCE_LIMIT,
1232 /* Now add or delete the information. */
1233 if (!silc_server_inviteban_process(server, channel->invite_list,
1234 (SilcUInt8)atype[0], args)) {
1235 silc_server_command_send_status_reply(
1236 cmd, SILC_COMMAND_INVITE,
1237 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1242 silc_argument_payload_free(args);
1245 /* Encode invite list */
1247 if (channel->invite_list && silc_hash_table_count(channel->invite_list)) {
1248 list = silc_buffer_alloc_size(2);
1249 silc_buffer_format(list,
1250 SILC_STR_UI_SHORT(silc_hash_table_count(
1251 channel->invite_list)),
1253 silc_hash_table_list(channel->invite_list, &htl);
1254 while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2))
1255 list = silc_argument_payload_encode_one(list, tmp2->data,
1256 silc_buffer_len(tmp2),
1257 SILC_PTR_TO_32(type));
1258 silc_hash_table_list_reset(&htl);
1261 /* The notify is sent to local servers (not clients), and to network. */
1262 if (atype && tmp && len2) {
1263 silc_buffer_set(&alist, tmp, len2);
1265 /* Send to local servers if we are router */
1266 if (server->server_type == SILC_ROUTER) {
1267 SilcBuffer idp, idp2;
1268 idp = silc_id_payload_encode(SILC_ID_GET_ID(id), SILC_ID_CHANNEL);
1269 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1270 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, FALSE,
1271 SILC_NOTIFY_TYPE_INVITE, 5,
1272 idp->data, silc_buffer_len(idp),
1273 channel->channel_name,
1274 strlen(channel->channel_name),
1275 idp2->data, silc_buffer_len(idp2),
1277 tmp ? alist.data : NULL,
1278 tmp ? silc_buffer_len(&alist) : 0);
1279 silc_buffer_free(idp);
1280 silc_buffer_free(idp2);
1283 /* Send to network */
1284 silc_server_send_notify_invite(server, SILC_PRIMARY_ROUTE(server),
1285 SILC_BROADCAST(server), channel,
1287 tmp ? &alist : NULL);
1290 /* Send invite list back only if the list was modified, or no arguments
1293 argc = silc_argument_get_arg_num(cmd->args);
1296 if (silc_argument_get_arg_type(cmd->args, 3, &len))
1299 /* Send command reply */
1300 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1301 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_INVITE,
1302 SILC_STATUS_OK, 0, ident, 2,
1306 ttype && list ? silc_buffer_len(list) : 0);
1307 silc_buffer_free(list);
1310 silc_server_command_free(cmd);
1314 SilcPacketStream sock;
1318 /* Quits connection to client. This gets called if client won't
1319 close the connection even when it has issued QUIT command. */
1321 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
1323 SilcServer server = app_context;
1324 QuitInternal q = (QuitInternal)context;
1325 SilcClientEntry client = silc_packet_get_context(q->sock);
1328 /* Free all client specific data, such as client entry and entires
1329 on channels this client may be on. */
1330 silc_server_free_sock_user_data(server, q->sock, q->signoff);
1331 silc_server_close_connection(server, q->sock);
1334 silc_packet_stream_unref(q->sock);
1335 silc_free(q->signoff);
1339 /* Quits SILC session. This is the normal way to disconnect client. */
1341 SILC_SERVER_CMD_FUNC(quit)
1343 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1344 SilcServer server = cmd->server;
1345 SilcPacketStream sock = cmd->sock;
1346 SilcClientEntry client = silc_packet_get_context(sock);
1348 unsigned char *tmp = NULL;
1351 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
1353 if (client->data.conn_type != SILC_CONN_CLIENT)
1357 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1361 q = silc_calloc(1, sizeof(*q));
1363 q->signoff = tmp ? strdup(tmp) : NULL;
1364 silc_packet_stream_ref(q->sock);
1366 /* We quit the connection with little timeout */
1367 silc_schedule_task_add_timeout(server->schedule,
1368 silc_server_command_quit_cb, (void *)q,
1372 silc_server_command_free(cmd);
1375 /* Server side of command KILL. This command is used by router operator
1376 to remove an client from the SILC Network temporarily. */
1378 SILC_SERVER_CMD_FUNC(kill)
1380 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1381 SilcServer server = cmd->server;
1382 SilcClientEntry client = silc_packet_get_context(cmd->sock);
1383 SilcClientEntry remote_client;
1385 unsigned char *tmp, *comment, *auth;
1386 SilcUInt32 tmp_len, tmp_len2, auth_len;
1388 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 3);
1390 if (client->data.conn_type != SILC_CONN_CLIENT || !client)
1393 /* Get authentication payload if present */
1394 auth = silc_argument_get_arg_type(cmd->args, 3, &auth_len);
1397 /* Router operator killing */
1399 /* KILL command works only on router */
1400 if (server->server_type != SILC_ROUTER) {
1401 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1402 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
1406 /* Check whether client has the permissions. */
1407 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
1408 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1409 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
1414 /* Get the client ID */
1415 if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
1416 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1417 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
1421 /* Get the client entry */
1422 remote_client = silc_idlist_find_client_by_id(server->local_list,
1425 if (!remote_client) {
1426 remote_client = silc_idlist_find_client_by_id(server->global_list,
1429 if (!remote_client) {
1430 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1431 silc_server_command_send_status_data(cmd, SILC_COMMAND_KILL,
1432 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1433 0, 2, tmp, tmp_len);
1439 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
1440 if (comment && tmp_len2 > 128) {
1442 comment[tmp_len2 - 1] = '\0';
1445 /* If authentication data is provided then verify that killing is
1447 if (auth && auth_len) {
1448 SilcPacketStream sock;
1450 if (!SILC_IS_LOCAL(remote_client) || !remote_client->data.public_key) {
1451 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1452 SILC_STATUS_ERR_OPERATION_ALLOWED,
1457 /* Verify the signature */
1458 if (!silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
1459 remote_client->data.public_key, 0,
1460 server->sha1hash, remote_client->id,
1462 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1463 SILC_STATUS_ERR_AUTH_FAILED, 0);
1467 /* Send reply to the sender */
1468 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1469 silc_server_command_send_status_data(cmd, SILC_COMMAND_KILL,
1473 /* Do normal signoff for the destination client */
1474 sock = remote_client->connection;
1477 silc_packet_stream_ref(sock);
1479 silc_server_remove_from_channels(server, NULL, remote_client,
1480 TRUE, (char *)"Killed", TRUE, TRUE);
1481 silc_server_free_sock_user_data(server, sock, comment ? comment :
1482 (unsigned char *)"Killed");
1484 silc_packet_set_context(sock, NULL);
1485 silc_server_close_connection(server, sock);
1486 silc_packet_stream_unref(sock);
1489 /* Router operator killing */
1491 /* Send reply to the sender */
1492 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1493 silc_server_command_send_status_data(cmd, SILC_COMMAND_KILL,
1497 /* Check if anyone is watching this nickname */
1498 if (server->server_type == SILC_ROUTER)
1499 silc_server_check_watcher_list(server, client, NULL,
1500 SILC_NOTIFY_TYPE_KILLED);
1502 /* Now do the killing */
1503 silc_server_kill_client(server, remote_client, comment, client->id,
1508 silc_server_command_free(cmd);
1511 /* Server side of command INFO. This sends information about us to
1512 the client. If client requested specific server we will send the
1513 command to that server. */
1515 SILC_SERVER_CMD_FUNC(info)
1517 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1518 SilcServer server = cmd->server;
1522 char *dest_server = NULL, *server_info = NULL, *server_name;
1523 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1524 SilcServerEntry entry = NULL;
1527 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
1529 /* Get server name */
1530 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1532 /* Check server name. */
1533 dest_server = silc_identifier_check(dest_server, strlen(dest_server),
1534 SILC_STRING_UTF8, 256, &tmp_len);
1536 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1537 SILC_STATUS_ERR_BAD_SERVER, 0);
1543 if (silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL)) {
1544 /* Check whether we have this server cached */
1545 entry = silc_idlist_find_server_by_id(server->local_list,
1546 SILC_ID_GET_ID(id), TRUE, NULL);
1548 entry = silc_idlist_find_server_by_id(server->global_list,
1549 SILC_ID_GET_ID(id), TRUE, NULL);
1550 if (!entry && server->server_type != SILC_SERVER) {
1551 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1552 silc_server_command_send_status_data(cmd, SILC_COMMAND_INFO,
1553 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
1554 0, 2, tmp, tmp_len);
1560 if ((!dest_server && !entry) || (entry && entry == server->id_entry) ||
1561 (dest_server && !cmd->pending &&
1562 !memcmp(dest_server, server->server_name, strlen(dest_server)))) {
1563 /* Send our reply */
1564 char info_string[256];
1566 memset(info_string, 0, sizeof(info_string));
1567 snprintf(info_string, sizeof(info_string),
1568 "location: %s server: %s admin: %s <%s>",
1569 server->config->server_info->location,
1570 server->config->server_info->server_type,
1571 server->config->server_info->admin,
1572 server->config->server_info->email);
1574 server_info = info_string;
1575 entry = server->id_entry;
1577 /* Check whether we have this server cached */
1578 if (!entry && dest_server) {
1579 entry = silc_idlist_find_server_by_name(server->global_list,
1580 dest_server, TRUE, NULL);
1582 entry = silc_idlist_find_server_by_name(server->local_list,
1583 dest_server, TRUE, NULL);
1587 if (!cmd->pending &&
1588 server->server_type != SILC_SERVER && entry && !entry->server_info) {
1589 /* Send to the server */
1591 SilcUInt16 old_ident;
1594 cmd->server->stat.commands_sent++;
1596 old_ident = silc_command_get_ident(cmd->payload);
1597 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1598 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1600 silc_server_packet_send(server, entry->connection,
1601 SILC_PACKET_COMMAND, cmd->packet->flags,
1602 tmpbuf->data, silc_buffer_len(tmpbuf));
1604 /* Reprocess this packet after received reply from router */
1605 silc_server_command_pending(server, SILC_COMMAND_INFO,
1606 silc_command_get_ident(cmd->payload),
1607 silc_server_command_info,
1608 silc_server_command_dup(cmd));
1609 cmd->pending = TRUE;
1610 silc_command_set_ident(cmd->payload, old_ident);
1611 silc_buffer_free(tmpbuf);
1615 if (!entry && !cmd->pending && !server->standalone) {
1616 /* Send to the primary router */
1618 SilcUInt16 old_ident;
1621 cmd->server->stat.commands_sent++;
1623 old_ident = silc_command_get_ident(cmd->payload);
1624 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1625 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1627 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
1628 SILC_PACKET_COMMAND, cmd->packet->flags,
1629 tmpbuf->data, silc_buffer_len(tmpbuf));
1631 /* Reprocess this packet after received reply from router */
1632 silc_server_command_pending(server, SILC_COMMAND_INFO,
1633 silc_command_get_ident(cmd->payload),
1634 silc_server_command_info,
1635 silc_server_command_dup(cmd));
1636 cmd->pending = TRUE;
1637 silc_command_set_ident(cmd->payload, old_ident);
1638 silc_buffer_free(tmpbuf);
1645 silc_free(dest_server);
1646 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1647 silc_server_command_send_status_data(cmd, SILC_COMMAND_INFO,
1648 SILC_STATUS_ERR_NO_SUCH_SERVER, 0,
1650 strlen(dest_server));
1656 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1658 server_info = entry->server_info;
1659 server_name = entry->server_name;
1661 /* Send the reply */
1662 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_INFO,
1663 SILC_STATUS_OK, 0, ident, 3,
1664 2, idp->data, silc_buffer_len(idp),
1666 strlen(server_name),
1669 strlen(server_info) : 0);
1670 silc_buffer_free(idp);
1673 silc_free(dest_server);
1674 silc_server_command_free(cmd);
1677 /* Server side of command PING. This just replies to the ping. */
1679 SILC_SERVER_CMD_FUNC(ping)
1681 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1682 SilcServer server = cmd->server;
1687 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PING, cmd, 1, 1);
1690 if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
1691 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1692 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1697 if (SILC_ID_SERVER_COMPARE(SILC_ID_GET_ID(id), server->id)) {
1698 /* Send our reply */
1699 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1702 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1703 silc_server_command_send_status_data(cmd, SILC_COMMAND_PING,
1704 SILC_STATUS_ERR_NO_SUCH_SERVER_ID, 0,
1710 silc_server_command_free(cmd);
1713 /* Server side of command STATS. */
1715 SILC_SERVER_CMD_FUNC(stats)
1717 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1718 SilcServer server = cmd->server;
1722 SilcBuffer packet, stats;
1723 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1726 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1);
1729 if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
1730 silc_server_command_send_status_reply(cmd, SILC_COMMAND_STATS,
1731 SILC_STATUS_ERR_NO_SERVER_ID, 0);
1735 SILC_LOG_DEBUG(("id %s", silc_id_render(SILC_ID_GET_ID(id),
1738 /* The ID must be ours */
1739 if (!SILC_ID_SERVER_COMPARE(server->id, SILC_ID_GET_ID(id))) {
1740 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1741 silc_server_command_send_status_data(cmd, SILC_COMMAND_STATS,
1742 SILC_STATUS_ERR_NO_SUCH_SERVER_ID, 0,
1747 /* If we are router then just send everything we got. If we are normal
1748 server then we'll send this to our router to get all the latest
1749 statistical information. */
1750 if (!cmd->pending && server->server_type != SILC_ROUTER &&
1751 !server->standalone) {
1755 cmd->server->stat.commands_sent++;
1757 /* Send request to our router */
1758 idp = silc_id_payload_encode(server->router->id,
1760 packet = silc_command_payload_encode_va(SILC_COMMAND_STATS,
1761 ++server->cmd_ident, 1,
1763 silc_buffer_len(idp));
1764 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
1765 SILC_PACKET_COMMAND, 0, packet->data,
1766 silc_buffer_len(packet));
1768 /* Reprocess this packet after received reply from router */
1769 silc_server_command_pending(server, SILC_COMMAND_STATS,
1771 silc_server_command_stats,
1772 silc_server_command_dup(cmd));
1773 cmd->pending = TRUE;
1774 silc_buffer_free(packet);
1775 silc_buffer_free(idp);
1779 /* Send our reply to sender */
1780 uptime = time(NULL) - server->starttime;
1782 stats = silc_buffer_alloc_size(60);
1783 silc_buffer_format(stats,
1784 SILC_STR_UI_INT(server->starttime),
1785 SILC_STR_UI_INT(uptime),
1786 SILC_STR_UI_INT(server->stat.my_clients),
1787 SILC_STR_UI_INT(server->stat.my_channels),
1788 SILC_STR_UI_INT(server->stat.my_server_ops),
1789 SILC_STR_UI_INT(server->stat.my_router_ops),
1790 SILC_STR_UI_INT(server->stat.cell_clients),
1791 SILC_STR_UI_INT(server->stat.cell_channels),
1792 SILC_STR_UI_INT(server->stat.cell_servers),
1793 SILC_STR_UI_INT(server->stat.clients),
1794 SILC_STR_UI_INT(server->stat.channels),
1795 SILC_STR_UI_INT(server->stat.servers),
1796 SILC_STR_UI_INT(server->stat.routers),
1797 SILC_STR_UI_INT(server->stat.server_ops),
1798 SILC_STR_UI_INT(server->stat.router_ops),
1801 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1802 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_STATS,
1803 SILC_STATUS_OK, 0, ident, 2,
1805 3, stats->data, silc_buffer_len(stats));
1806 silc_buffer_free(stats);
1809 silc_server_command_free(cmd);
1812 /* Internal routine to join channel. The channel sent to this function
1813 has been either created or resolved from ID lists. This joins the sent
1814 client to the channel. */
1816 static void silc_server_command_join_channel(SilcServer server,
1817 SilcServerCommandContext cmd,
1818 SilcChannelEntry channel,
1819 SilcClientID *client_id,
1821 SilcBool create_key,
1823 const unsigned char *auth,
1824 SilcUInt32 auth_len,
1825 const unsigned char *cauth,
1826 SilcUInt32 cauth_len)
1828 SilcPacketStream sock = cmd->sock;
1829 SilcIDListData idata = silc_packet_get_context(sock);
1831 SilcUInt32 tmp_len, user_count;
1832 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4], ulimit[4];
1833 SilcClientEntry client;
1834 SilcChannelClientEntry chl;
1835 SilcBuffer reply, chidp, clidp, keyp = NULL;
1836 SilcBuffer user_list, mode_list, invite_list, ban_list;
1837 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1838 char check[512], check2[512];
1840 SilcBool founder = FALSE;
1842 SilcBuffer fkey = NULL, chpklist = NULL;
1843 const char *cipher, *hostname, *ip;
1845 SILC_LOG_DEBUG(("Joining client to channel"));
1850 silc_socket_stream_get_info(silc_packet_stream_get_stream(sock),
1851 NULL, &hostname, &ip, NULL);
1853 /* Get the client entry */
1854 if (idata->conn_type == SILC_CONN_CLIENT) {
1855 client = (SilcClientEntry)idata;
1859 client = silc_server_query_client(server, client_id, FALSE,
1862 if (!resolve || cmd->pending) {
1863 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1864 silc_server_command_send_status_data(
1865 cmd, SILC_COMMAND_JOIN,
1866 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0,
1871 /* The client info is being resolved. Reprocess this packet after
1872 receiving the reply to the query. */
1873 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1875 silc_server_command_join,
1876 silc_server_command_dup(cmd));
1877 cmd->pending = TRUE;
1881 if (!client->data.public_key &&
1882 (auth || cauth || channel->ban_list ||
1883 (channel->mode & SILC_CHANNEL_MODE_INVITE))) {
1884 if (cmd->pending == 2)
1887 /* We must retrieve the client's public key by sending
1888 GETKEY command. Reprocess this packet after receiving the key */
1889 clidp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
1890 silc_server_send_command(server, cmd->sock,
1891 SILC_COMMAND_GETKEY, ++server->cmd_ident,
1892 1, 1, clidp->data, silc_buffer_len(clidp));
1893 silc_buffer_free(clidp);
1894 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
1896 silc_server_command_join,
1897 silc_server_command_dup(cmd));
1902 cmd->pending = FALSE;
1906 * Check founder auth payload if provided. If client can gain founder
1907 * privileges it can override various conditions on joining the channel,
1908 * and can have directly the founder mode set on the channel.
1910 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1911 SilcIDListData idata = (SilcIDListData)client;
1912 SilcChannelClientEntry chl2;
1913 SilcHashTableList htl;
1915 if (channel->founder_key && idata->public_key &&
1916 silc_pkcs_public_key_compare(channel->founder_key,
1917 idata->public_key)) {
1918 /* Check whether the client is to become founder */
1919 if (silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
1920 channel->founder_key, 0, server->sha1hash,
1921 client->id, SILC_ID_CLIENT)) {
1923 /* There cannot be anyone else as founder on the channel now. This
1924 client is definitely the founder due to this authentication */
1925 silc_hash_table_list(channel->user_list, &htl);
1926 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
1927 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
1928 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
1929 silc_server_force_cumode_change(server, NULL, channel, chl2,
1933 silc_hash_table_list_reset(&htl);
1935 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
1942 * Check channel modes
1946 memset(check, 0, sizeof(check));
1947 memset(check2, 0, sizeof(check2));
1948 silc_strncat(check, sizeof(check),
1949 client->nickname, strlen(client->nickname));
1950 silc_strncat(check, sizeof(check), "!", 1);
1951 silc_strncat(check, sizeof(check),
1952 client->username, strlen(client->username));
1953 if (!strchr(client->username, '@')) {
1954 silc_strncat(check, sizeof(check), "@", 1);
1955 silc_strncat(check, sizeof(check),
1956 hostname, strlen(hostname));
1959 silc_strncat(check2, sizeof(check2),
1960 client->nickname, strlen(client->nickname));
1961 if (!strchr(client->nickname, '@')) {
1962 silc_strncat(check2, sizeof(check2), "@", 1);
1963 silc_strncat(check2, sizeof(check2),
1964 SILC_IS_LOCAL(client) ? server->server_name :
1965 client->router->server_name,
1966 SILC_IS_LOCAL(client) ? strlen(server->server_name) :
1967 strlen(client->router->server_name));
1969 silc_strncat(check2, sizeof(check2), "!", 1);
1970 silc_strncat(check2, sizeof(check2),
1971 client->username, strlen(client->username));
1972 if (!strchr(client->username, '@')) {
1973 silc_strncat(check2, sizeof(check2), "@", 1);
1974 silc_strncat(check2, sizeof(check2),
1975 hostname, strlen(hostname));
1978 /* Check invite list if channel is invite-only channel */
1979 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1980 if (!channel->invite_list ||
1981 !silc_hash_table_count(channel->invite_list) ||
1982 (!silc_server_inviteban_match(server, channel->invite_list,
1984 !silc_server_inviteban_match(server, channel->invite_list,
1985 2, client->data.public_key) &&
1986 !silc_server_inviteban_match(server, channel->invite_list,
1987 1, client->nickname) &&
1988 !silc_server_inviteban_match(server, channel->invite_list,
1990 !silc_server_inviteban_match(server, channel->invite_list,
1992 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1993 silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
1994 SILC_STATUS_ERR_NOT_INVITED, 0,
1996 silc_buffer_len(chidp));
1997 silc_buffer_free(chidp);
2002 /* Check ban list if it exists. If the client's nickname, server,
2003 username and/or hostname is in the ban list the access to the
2004 channel is denied. */
2005 if (channel->ban_list && silc_hash_table_count(channel->ban_list)) {
2006 if (silc_server_inviteban_match(server, channel->ban_list,
2008 silc_server_inviteban_match(server, channel->ban_list,
2009 2, client->data.public_key) ||
2010 silc_server_inviteban_match(server, channel->ban_list,
2011 1, client->nickname) ||
2012 silc_server_inviteban_match(server, channel->ban_list,
2014 silc_server_inviteban_match(server, channel->ban_list,
2016 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2017 silc_server_command_send_status_data(
2018 cmd, SILC_COMMAND_JOIN,
2019 SILC_STATUS_ERR_BANNED_FROM_CHANNEL, 0,
2021 silc_buffer_len(chidp));
2022 silc_buffer_free(chidp);
2027 /* Check user count limit if set. */
2028 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
2029 if (silc_hash_table_count(channel->user_list) + 1 >
2030 channel->user_limit) {
2031 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2032 silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
2033 SILC_STATUS_ERR_CHANNEL_IS_FULL,
2035 silc_buffer_len(chidp));
2036 silc_buffer_free(chidp);
2042 /* Check the channel passphrase if set. */
2043 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2044 /* Get passphrase */
2045 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2047 passphrase = silc_memdup(tmp, tmp_len);
2049 if (!passphrase || !channel->passphrase ||
2050 strlen(channel->passphrase) != strlen(passphrase) ||
2051 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
2052 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2053 silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
2054 SILC_STATUS_ERR_BAD_PASSWORD, 0,
2056 silc_buffer_len(chidp));
2057 silc_buffer_free(chidp);
2062 /* Verify channel authentication with channel public keys if set. */
2063 if (channel->mode & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
2064 if (!silc_server_verify_channel_auth(server, channel, client->id,
2065 cauth, cauth_len)) {
2066 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2067 SILC_STATUS_ERR_PERM_DENIED, 0);
2073 * Client is allowed to join to the channel. Make it happen.
2076 /* Check whether the client already is on the channel */
2077 if (silc_server_client_on_channel(client, channel, NULL)) {
2078 clidp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
2079 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2080 silc_server_command_send_status_data2(cmd, SILC_COMMAND_JOIN,
2081 SILC_STATUS_ERR_USER_ON_CHANNEL, 0,
2083 silc_buffer_len(clidp),
2085 silc_buffer_len(chidp));
2086 silc_buffer_free(clidp);
2087 silc_buffer_free(chidp);
2091 /* Generate new channel key as protocol dictates */
2093 if (!silc_server_create_channel_key(server, channel, 0))
2096 /* Send the channel key. This is broadcasted to the channel but is not
2097 sent to the client who is joining to the channel. */
2098 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
2099 silc_server_send_channel_key(server, NULL, channel,
2100 server->server_type == SILC_ROUTER ?
2101 FALSE : !server->standalone);
2104 /* Join the client to the channel by adding it to channel's user list.
2105 Add also the channel to client entry's channels list for fast cross-
2107 chl = silc_calloc(1, sizeof(*chl));
2109 chl->client = client;
2110 chl->channel = channel;
2111 silc_hash_table_add(channel->user_list, client, chl);
2112 silc_hash_table_add(client->channels, channel, chl);
2113 channel->user_count++;
2114 channel->disabled = FALSE;
2116 /* Get users on the channel */
2117 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
2120 /* Encode Client ID Payload of the original client who wants to join */
2121 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2123 /* Encode command reply packet */
2124 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2125 SILC_PUT32_MSB(channel->mode, mode);
2126 SILC_PUT32_MSB(created, tmp2);
2127 SILC_PUT32_MSB(user_count, tmp3);
2128 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2129 SILC_PUT32_MSB(channel->user_limit, ulimit);
2131 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
2132 unsigned char cid[32];
2134 silc_id_id2str(channel->id, SILC_ID_CHANNEL, cid, sizeof(cid), &cid_len);
2135 cipher = silc_cipher_get_name(channel->send_key);
2136 keyp = silc_channel_key_payload_encode(cid_len, cid,
2137 strlen(cipher), cipher,
2138 channel->key_len / 8, channel->key);
2141 if (channel->founder_key)
2142 fkey = silc_public_key_payload_encode(channel->founder_key);
2144 /* Encode invite list */
2146 if (channel->invite_list && silc_hash_table_count(channel->invite_list)) {
2147 SilcHashTableList htl;
2149 invite_list = silc_buffer_alloc_size(2);
2150 silc_buffer_format(invite_list,
2151 SILC_STR_UI_SHORT(silc_hash_table_count(
2152 channel->invite_list)),
2155 silc_hash_table_list(channel->invite_list, &htl);
2156 while (silc_hash_table_get(&htl, (void *)&plen, (void *)&reply))
2157 invite_list = silc_argument_payload_encode_one(invite_list,
2159 silc_buffer_len(reply),
2160 SILC_PTR_TO_32(plen));
2161 silc_hash_table_list_reset(&htl);
2164 /* Encode ban list */
2166 if (channel->ban_list && silc_hash_table_count(channel->ban_list)) {
2167 SilcHashTableList htl;
2169 ban_list = silc_buffer_alloc_size(2);
2170 silc_buffer_format(ban_list,
2171 SILC_STR_UI_SHORT(silc_hash_table_count(
2172 channel->ban_list)),
2175 silc_hash_table_list(channel->ban_list, &htl);
2176 while (silc_hash_table_get(&htl, (void *)&plen, (void *)&reply))
2177 ban_list = silc_argument_payload_encode_one(ban_list,
2179 silc_buffer_len(reply),
2180 SILC_PTR_TO_32(plen));
2181 silc_hash_table_list_reset(&htl);
2184 if (channel->channel_pubkeys)
2185 chpklist = silc_server_get_channel_pk_list(server, channel, FALSE, FALSE);
2188 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2189 SILC_STATUS_OK, 0, ident, 16,
2190 2, channel->channel_name,
2191 strlen(channel->channel_name),
2193 silc_buffer_len(chidp),
2195 silc_buffer_len(clidp),
2198 7, keyp ? keyp->data : NULL,
2199 keyp ? silc_buffer_len(keyp) : 0,
2200 8, ban_list ? ban_list->data : NULL,
2202 silc_buffer_len(ban_list): 0,
2203 9, invite_list ? invite_list->data :
2206 silc_buffer_len(invite_list) : 0,
2209 strlen(channel->topic) : 0,
2210 11, silc_hmac_get_name(channel->hmac),
2211 strlen(silc_hmac_get_name(channel->
2214 13, user_list->data,
2215 silc_buffer_len(user_list),
2216 14, mode_list->data,
2217 silc_buffer_len(mode_list),
2218 15, fkey ? fkey->data : NULL,
2219 fkey ? silc_buffer_len(fkey) : 0,
2220 16, chpklist ? chpklist->data : NULL,
2221 chpklist ? silc_buffer_len(chpklist) : 0,
2222 17, (channel->mode &
2223 SILC_CHANNEL_MODE_ULIMIT ?
2226 SILC_CHANNEL_MODE_ULIMIT ?
2227 sizeof(ulimit) : 0));
2229 /* Send command reply */
2230 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
2231 reply->data, silc_buffer_len(reply));
2234 cmd->server->stat.commands_sent++;
2236 /* Send JOIN notify to locally connected clients on the channel. If
2237 we are normal server then router will send or have sent JOIN notify
2238 already. However since we've added the client already to our channel
2239 we'll ignore it (in packet_receive.c) so we must send it here. If
2240 we are router then this will send it to local clients and local
2242 SILC_LOG_DEBUG(("Send JOIN notify to channel"));
2243 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
2244 SILC_NOTIFY_TYPE_JOIN, 2,
2245 clidp->data, silc_buffer_len(clidp),
2246 chidp->data, silc_buffer_len(chidp));
2248 /* Update statistics */
2249 server->stat.my_chanclients++;
2250 if (server->server_type == SILC_ROUTER) {
2251 server->stat.cell_chanclients++;
2252 server->stat.chanclients++;
2255 if (!cmd->pending) {
2256 /* Send JOIN notify packet to our primary router */
2257 silc_server_send_notify_join(server, SILC_PRIMARY_ROUTE(server),
2258 SILC_BROADCAST(server), channel, client->id);
2261 /* Distribute the channel key to all backup routers. */
2262 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
2263 keyp->data, silc_buffer_len(keyp), FALSE, TRUE);
2265 /* If client became founder by providing correct founder auth data
2266 notify the mode change to the channel. */
2268 SILC_PUT32_MSB(chl->mode, mode);
2269 SILC_LOG_DEBUG(("Send CUMODE_CHANGE notify to channel"));
2270 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
2271 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
2273 silc_buffer_len(clidp),
2274 mode, 4, clidp->data,
2275 silc_buffer_len(clidp),
2276 fkey ? fkey->data : NULL,
2277 fkey ? silc_buffer_len(fkey) : 0);
2281 /* Set CUMODE notify type to network */
2283 silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
2284 SILC_BROADCAST(server), channel,
2285 chl->mode, client->id, SILC_ID_CLIENT,
2286 client->id, channel->founder_key);
2288 silc_buffer_free(reply);
2289 silc_buffer_free(clidp);
2290 silc_buffer_free(chidp);
2291 silc_buffer_free(keyp);
2292 silc_buffer_free(user_list);
2293 silc_buffer_free(mode_list);
2294 silc_buffer_free(fkey);
2295 silc_buffer_free(chpklist);
2296 silc_buffer_free(invite_list);
2297 silc_buffer_free(ban_list);
2301 memset(passphrase, 0, strlen(passphrase));
2302 silc_free(passphrase);
2305 /* Server side of command JOIN. Joins client into requested channel. If
2306 the channel does not exist it will be created. */
2308 void silc_server_command_join_connected(SilcServer server,
2309 SilcServerEntry server_entry,
2312 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2314 if (!server_entry) {
2316 unsigned char *tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2319 SILC_LOG_DEBUG(("Connecting to router failed"));
2320 silc_parse_userfqdn(tmp, NULL, 0, serv, sizeof(serv));
2323 silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
2324 SILC_STATUS_ERR_NO_SUCH_SERVER, 0,
2325 2, serv, strlen(serv));
2327 silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
2328 SILC_STATUS_ERR_NO_SUCH_CHANNEL, 0,
2331 silc_server_command_free(cmd);
2335 /* Reprocess command */
2336 SILC_LOG_DEBUG(("Reprocess JOIN after connecting to router"));
2337 silc_server_command_join(cmd, NULL);
2340 SILC_SERVER_CMD_FUNC(join)
2342 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2343 SilcServer server = cmd->server;
2344 SilcIDListData idata = silc_packet_get_context(cmd->sock);
2345 unsigned char *auth, *cauth;
2346 SilcUInt32 tmp_len, auth_len, cauth_len;
2347 char *tmp, *channel_name, *channel_namec = NULL, *cipher, *hmac;
2348 char parsed[256 + 1], serv[256 + 1];
2349 SilcChannelEntry channel;
2350 SilcUInt32 umode = 0;
2351 SilcBool created = FALSE, create_key = TRUE;
2354 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 7);
2356 /* Get channel name */
2357 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2359 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2360 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2365 /* Truncate over long channel names */
2366 if (tmp_len > 256) {
2368 tmp[tmp_len - 1] = '\0';
2371 /* Parse server name from the channel name */
2372 silc_parse_userfqdn(tmp, parsed, sizeof(parsed), serv,
2374 channel_name = parsed;
2376 if (server->config->dynamic_server) {
2377 /* If server name is not specified but local channels is FALSE then the
2378 channel will be global, based on our router name. */
2379 if (!serv[0] && !server->config->local_channels) {
2380 if (!server->standalone) {
2381 silc_snprintf(serv, sizeof(serv), server->router->server_name);
2383 SilcServerConfigRouter *router;
2384 router = silc_server_config_get_primary_router(server);
2386 /* Create connection to primary router */
2387 SILC_LOG_DEBUG(("Create dynamic connection to primary router %s:%d",
2388 router->host, router->port));
2389 silc_server_create_connection(server, FALSE, TRUE,
2390 router->host, router->port,
2391 silc_server_command_join_connected,
2398 /* If server name is ours, ignore it. */
2399 if (serv[0] && silc_utf8_strcasecmp(serv, server->server_name))
2400 memset(serv, 0, sizeof(serv));
2402 /* Create connection */
2403 if (serv[0] && server->standalone) {
2404 SilcServerConfigRouter *router;
2405 router = silc_server_config_get_primary_router(server);
2407 /* Create connection to primary router */
2408 SILC_LOG_DEBUG(("Create dynamic connection to primary router %s:%d",
2409 router->host, router->port));
2410 silc_server_create_connection(server, FALSE, TRUE,
2411 router->host, router->port,
2412 silc_server_command_join_connected, cmd);
2418 /* Check for valid channel name. This is cached, the original is saved
2419 in the channel context. */
2420 channel_namec = silc_channel_name_check(channel_name, strlen(channel_name),
2421 SILC_STRING_UTF8, 256, NULL);
2422 if (!channel_namec) {
2423 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2424 SILC_STATUS_ERR_BAD_CHANNEL, 0);
2428 /* Get Client ID of the client who is joining to the channel */
2429 if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL)) {
2430 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2431 SILC_STATUS_ERR_NO_CLIENT_ID,
2435 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2437 /* Get cipher, hmac name and auth payload */
2438 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2439 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2440 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
2441 cauth = silc_argument_get_arg_type(cmd->args, 7, &cauth_len);
2443 /* See if the channel exists */
2444 channel = silc_idlist_find_channel_by_name(server->local_list,
2445 channel_namec, NULL);
2447 if (idata->conn_type == SILC_CONN_CLIENT) {
2448 SilcClientEntry entry = (SilcClientEntry)idata;
2450 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2451 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2456 #ifndef SILC_DIST_INPLACE
2457 /* Limit how many channels client can join */
2458 if (!cmd->pending && entry->channels &&
2459 silc_hash_table_count(entry->channels) >=
2460 server->config->param.chlimit) {
2461 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2462 SILC_STATUS_ERR_RESOURCE_LIMIT,
2466 #endif /* SILC_DIST_INPLACE */
2469 (channel->disabled && server->server_type != SILC_ROUTER)) {
2470 /* Channel not found or not valid */
2472 /* If we are standalone server we don't have a router, we just create
2473 the channel by ourselves (unless it existed). */
2474 if (server->standalone) {
2476 channel = silc_server_create_new_channel(server, server->id, cipher,
2477 hmac, channel_name, TRUE);
2480 silc_server_command_send_status_data(
2481 cmd, SILC_COMMAND_JOIN,
2482 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
2483 0, 2, cipher, strlen(cipher));
2485 silc_server_command_send_status_data(
2486 cmd, SILC_COMMAND_JOIN,
2487 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
2488 0, 2, hmac, strlen(hmac));
2490 silc_server_command_send_status_reply(
2491 cmd, SILC_COMMAND_JOIN,
2492 SILC_STATUS_ERR_RESOURCE_LIMIT,
2498 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2504 /* The channel does not exist on our server. If we are normal server
2505 we will send JOIN command to our router which will handle the
2506 joining procedure (either creates the channel if it doesn't exist
2507 or joins the client to it). */
2508 if (server->server_type != SILC_ROUTER) {
2510 SilcUInt16 old_ident;
2512 /* If this is pending command callback then we've resolved
2513 it and it didn't work, return since we've notified the
2514 client already in the command reply callback. */
2519 cmd->server->stat.commands_sent++;
2521 old_ident = silc_command_get_ident(cmd->payload);
2522 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2523 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2525 /* Send JOIN command to our router */
2526 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
2527 SILC_PACKET_COMMAND, cmd->packet->flags,
2528 tmpbuf->data, silc_buffer_len(tmpbuf));
2530 /* Reprocess this packet after received reply from router */
2531 silc_server_command_pending(server, SILC_COMMAND_JOIN,
2532 silc_command_get_ident(cmd->payload),
2533 silc_server_command_join,
2534 silc_server_command_dup(cmd));
2535 cmd->pending = TRUE;
2536 silc_command_set_ident(cmd->payload, old_ident);
2537 silc_buffer_free(tmpbuf);
2541 /* We are router and the channel does not seem exist so we will check
2542 our global list as well for the channel. */
2543 channel = silc_idlist_find_channel_by_name(server->global_list,
2544 channel_namec, NULL);
2546 /* Channel really does not exist, create it */
2547 channel = silc_server_create_new_channel(server, server->id, cipher,
2548 hmac, channel_name, TRUE);
2551 silc_server_command_send_status_data(
2552 cmd, SILC_COMMAND_JOIN,
2553 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
2554 0, 2, cipher, strlen(cipher));
2556 silc_server_command_send_status_data(
2557 cmd, SILC_COMMAND_JOIN,
2558 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
2559 0, 2, hmac, strlen(hmac));
2561 silc_server_command_send_status_reply(
2562 cmd, SILC_COMMAND_JOIN,
2563 SILC_STATUS_ERR_RESOURCE_LIMIT,
2569 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2577 /* Channel not found */
2579 /* If the command came from router and we are normal server then
2580 something went wrong with the joining as the channel was not found.
2581 We can't do anything else but ignore this. */
2582 if (idata->conn_type == SILC_CONN_ROUTER ||
2583 server->server_type != SILC_ROUTER)
2586 /* We are router and the channel does not seem exist so we will check
2587 our global list as well for the channel. */
2588 channel = silc_idlist_find_channel_by_name(server->global_list,
2589 channel_namec, NULL);
2591 /* Channel really does not exist, create it */
2592 channel = silc_server_create_new_channel(server, server->id, cipher,
2593 hmac, channel_name, TRUE);
2596 silc_server_command_send_status_data(
2597 cmd, SILC_COMMAND_JOIN,
2598 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
2599 0, 2, cipher, strlen(cipher));
2601 silc_server_command_send_status_data(
2602 cmd, SILC_COMMAND_JOIN,
2603 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
2604 0, 2, hmac, strlen(hmac));
2606 silc_server_command_send_status_reply(
2607 cmd, SILC_COMMAND_JOIN,
2608 SILC_STATUS_ERR_RESOURCE_LIMIT,
2614 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2621 /* Check whether the channel was created by our router */
2622 if (cmd->pending && context2) {
2623 SilcServerCommandReplyContext reply = context2;
2625 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
2626 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
2627 SILC_GET32_MSB(created, tmp);
2628 if (silc_argument_get_arg_type(reply->args, 7, NULL))
2629 create_key = FALSE; /* Router returned the key already */
2631 if (silc_command_get_status(reply->payload, NULL, NULL) &&
2632 channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2633 /* Save channel passphrase, if user provided it successfully */
2636 pa = silc_argument_get_arg_type(cmd->args, 3, &pa_len);
2638 silc_free(channel->passphrase);
2639 channel->passphrase = silc_memdup(pa, pa_len);
2644 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
2645 !channel->disabled && !silc_hash_table_count(channel->user_list))
2649 /* If the channel does not have global users and is also empty the client
2650 will be the channel founder and operator. */
2651 if (!channel->disabled &&
2652 !channel->global_users && !silc_hash_table_count(channel->user_list))
2653 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2655 /* Join to the channel */
2656 silc_server_command_join_channel(server, cmd, channel, SILC_ID_GET_ID(id),
2657 created, create_key, umode,
2658 auth, auth_len, cauth, cauth_len);
2661 silc_free(channel_namec);
2662 silc_server_command_free(cmd);
2665 /* Server side of command MOTD. Sends server's current "message of the
2666 day" to the client. */
2668 SILC_SERVER_CMD_FUNC(motd)
2670 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2671 SilcServer server = cmd->server;
2673 char *motd, *dest_server = NULL;
2674 SilcUInt32 motd_len;
2675 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2677 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
2679 /* Get server name */
2680 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2682 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2683 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2688 /* Check server name */
2689 dest_server = silc_identifier_check(dest_server, strlen(dest_server),
2690 SILC_STRING_UTF8, 256, NULL);
2692 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2693 SILC_STATUS_ERR_BAD_SERVER,
2698 if (!memcmp(dest_server, server->server_name, strlen(dest_server))) {
2701 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
2703 if (server->config && server->config->server_info &&
2704 server->config->server_info->motd_file) {
2706 motd = silc_file_readfile(server->config->server_info->motd_file,
2710 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_MOTD,
2711 SILC_STATUS_OK, 0, ident, 1,
2712 2, idp->data, silc_buffer_len(idp));
2717 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_MOTD,
2718 SILC_STATUS_OK, 0, ident, 2,
2719 2, idp->data, silc_buffer_len(idp),
2723 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_MOTD,
2724 SILC_STATUS_OK, 0, ident, 1,
2725 2, idp->data, silc_buffer_len(idp));
2727 silc_buffer_free(idp);
2729 SilcServerEntry entry;
2731 /* Check whether we have this server cached */
2732 entry = silc_idlist_find_server_by_name(server->global_list,
2733 dest_server, TRUE, NULL);
2735 entry = silc_idlist_find_server_by_name(server->local_list,
2736 dest_server, TRUE, NULL);
2739 if (server->server_type != SILC_SERVER && !cmd->pending &&
2740 entry && !entry->motd) {
2741 /* Send to the server */
2743 SilcUInt16 old_ident;
2746 cmd->server->stat.commands_sent++;
2748 old_ident = silc_command_get_ident(cmd->payload);
2749 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2750 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2752 silc_server_packet_send(server, entry->connection,
2753 SILC_PACKET_COMMAND, cmd->packet->flags,
2754 tmpbuf->data, silc_buffer_len(tmpbuf));
2756 /* Reprocess this packet after received reply from router */
2757 silc_server_command_pending(server, SILC_COMMAND_MOTD,
2758 silc_command_get_ident(cmd->payload),
2759 silc_server_command_motd,
2760 silc_server_command_dup(cmd));
2761 cmd->pending = TRUE;
2762 silc_command_set_ident(cmd->payload, old_ident);
2763 silc_buffer_free(tmpbuf);
2767 /* Send to primary router only if we don't know the server
2768 * the client requested or if the server is not locally connected */
2769 if ((!entry || !(entry->data.status & SILC_IDLIST_STATUS_LOCAL))
2770 && !cmd->pending && !server->standalone) {
2771 /* Send to the primary router */
2773 SilcUInt16 old_ident;
2776 cmd->server->stat.commands_sent++;
2778 old_ident = silc_command_get_ident(cmd->payload);
2779 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2780 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2782 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
2783 SILC_PACKET_COMMAND, cmd->packet->flags,
2784 tmpbuf->data, silc_buffer_len(tmpbuf));
2786 /* Reprocess this packet after received reply from router */
2787 silc_server_command_pending(server, SILC_COMMAND_MOTD,
2788 silc_command_get_ident(cmd->payload),
2789 silc_server_command_motd,
2790 silc_server_command_dup(cmd));
2791 cmd->pending = TRUE;
2792 silc_command_set_ident(cmd->payload, old_ident);
2793 silc_buffer_free(tmpbuf);
2798 silc_free(dest_server);
2799 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2800 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2801 SILC_STATUS_ERR_NO_SUCH_SERVER, 0,
2803 strlen(dest_server));
2808 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2809 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_MOTD,
2810 SILC_STATUS_OK, 0, ident, 2,
2811 2, idp->data, silc_buffer_len(idp),
2814 strlen(entry->motd) : 0);
2815 silc_buffer_free(idp);
2819 silc_free(dest_server);
2820 silc_server_command_free(cmd);
2823 /* Server side of command UMODE. Client can use this command to set/unset
2824 user mode. Client actually cannot set itself to be as server/router
2825 operator so this can be used only to unset the modes. */
2827 SILC_SERVER_CMD_FUNC(umode)
2829 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2830 SilcServer server = cmd->server;
2831 SilcClientEntry client = silc_packet_get_context(cmd->sock);
2832 unsigned char *tmp_mask, m[4];
2833 SilcUInt32 mask = 0;
2834 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2835 SilcBool set_mask = FALSE;
2837 if (client->data.conn_type != SILC_CONN_CLIENT || !client)
2840 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2);
2842 /* Get the client's mode mask */
2843 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2845 SILC_GET32_MSB(mask, tmp_mask);
2850 /* Check that mode changing is allowed. */
2851 if (!silc_server_check_umode_rights(server, client, mask)) {
2852 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2853 SILC_STATUS_ERR_PERM_DENIED, 0);
2857 /* Anonymous mode cannot be set by client */
2858 if (mask & SILC_UMODE_ANONYMOUS &&
2859 !(client->mode & SILC_UMODE_ANONYMOUS)) {
2860 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2861 SILC_STATUS_ERR_PERM_DENIED, 0);
2865 /* Update statistics */
2866 if (mask & SILC_UMODE_GONE) {
2867 if (!(client->mode & SILC_UMODE_GONE))
2868 server->stat.my_aways++;
2870 if (client->mode & SILC_UMODE_GONE)
2871 server->stat.my_aways--;
2874 /* If the client has anonymous mode set, preserve it. */
2875 if (client->mode & SILC_UMODE_ANONYMOUS)
2876 mask |= SILC_UMODE_ANONYMOUS;
2878 /* Change the mode */
2879 client->mode = mask;
2881 /* Send UMODE change to primary router */
2882 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
2883 SILC_BROADCAST(server), client->id,
2886 /* Check if anyone is watching this nickname */
2887 if (server->server_type == SILC_ROUTER)
2888 silc_server_check_watcher_list(server, client, NULL,
2889 SILC_NOTIFY_TYPE_UMODE_CHANGE);
2892 /* Send command reply to sender */
2893 SILC_PUT32_MSB(client->mode, m);
2894 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_UMODE,
2895 SILC_STATUS_OK, 0, ident, 1,
2899 silc_server_command_free(cmd);
2902 /* Server side command of CMODE. Changes channel mode */
2904 SILC_SERVER_CMD_FUNC(cmode)
2906 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2907 SilcServer server = cmd->server;
2908 SilcClientEntry client = silc_packet_get_context(cmd->sock);
2909 SilcIDListData idata = (SilcIDListData)client;
2911 SilcChannelEntry channel;
2912 SilcChannelClientEntry chl;
2914 unsigned char *tmp, *tmp_id, *tmp_mask, *chpkdata = NULL;
2915 char *cipher = NULL, *hmac = NULL, *passphrase = NULL, ulimit[4];
2916 SilcUInt32 mode_mask = 0, old_mask = 0, tmp_len, tmp_len2, chpklen;
2917 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2918 SilcBool set_mask = FALSE, set_chpk = FALSE;
2919 SilcPublicKey founder_key = NULL;
2920 SilcBuffer fkey = NULL, chpklist = NULL;
2921 SilcBufferStruct chpk;
2924 silc_server_command_free(cmd);
2928 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 9);
2930 /* Get Channel ID */
2931 if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
2932 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2933 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2934 silc_server_command_free(cmd);
2938 /* Get channel entry */
2939 channel = silc_idlist_find_channel_by_id(server->local_list,
2940 SILC_ID_GET_ID(id), NULL);
2942 channel = silc_idlist_find_channel_by_id(server->global_list,
2943 SILC_ID_GET_ID(id), NULL);
2945 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2946 silc_server_command_send_status_data(cmd, SILC_COMMAND_CMODE,
2947 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
2948 0, 2, tmp_id, tmp_len2);
2949 silc_server_command_free(cmd);
2953 old_mask = channel->mode;
2955 /* Get the channel mode mask */
2956 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2958 SILC_GET32_MSB(mode_mask, tmp_mask);
2962 /* Check whether this client is on the channel */
2963 if (!silc_server_client_on_channel(client, channel, &chl)) {
2964 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2965 silc_server_command_send_status_data(cmd, SILC_COMMAND_CMODE,
2966 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
2967 2, tmp_id, tmp_len2);
2971 /* Check that client has rights to change any requested channel modes */
2972 if (set_mask && !silc_server_check_cmode_rights(server, channel, chl,
2974 SILC_LOG_DEBUG(("Client does not have rights to change mode"));
2975 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2976 silc_server_command_send_status_data(
2977 cmd, SILC_COMMAND_CMODE,
2978 (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) ?
2979 SILC_STATUS_ERR_NO_CHANNEL_PRIV :
2980 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV), 0,
2981 2, tmp_id, tmp_len2);
2985 /* If mode mask was not sent as argument then merely return the current
2986 mode mask, founder key and channel public key list to the sender. */
2989 SILC_PUT32_MSB(channel->mode, m);
2990 if (channel->founder_key)
2991 fkey = silc_public_key_payload_encode(channel->founder_key);
2992 if (channel->channel_pubkeys)
2993 chpklist = silc_server_get_channel_pk_list(server, channel,
2995 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2996 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_CMODE,
2997 SILC_STATUS_OK, 0, ident, 4,
2998 2, tmp_id, tmp_len2,
3000 4, fkey ? fkey->data : NULL,
3001 fkey ? silc_buffer_len(fkey) : 0,
3002 5, chpklist ? chpklist->data : NULL,
3003 chpklist ? silc_buffer_len(chpklist) : 0);
3008 * Check the modes. Modes that requires nothing special operation are
3012 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3013 /* Channel uses private keys to protect traffic. Client(s) has set the
3014 key locally they want to use, server does not know that key. */
3015 /* Nothing interesting to do here */
3017 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3018 /* The mode is removed and we need to generate and distribute
3019 new channel key. Clients are not using private channel keys
3020 anymore after this. */
3022 /* if we don't remove the flag from the mode
3023 * silc_server_create_channel_key won't create a new key */
3024 channel->mode &= ~SILC_CHANNEL_MODE_PRIVKEY;
3026 /* Re-generate channel key */
3027 if (!silc_server_create_channel_key(server, channel, 0))
3030 /* Send the channel key. This sends it to our local clients and if
3031 we are normal server to our router as well. */
3032 silc_server_send_channel_key(server, NULL, channel,
3033 server->server_type == SILC_ROUTER ?
3034 FALSE : !server->standalone);
3036 cipher = (char *)silc_cipher_get_name(channel->send_key);
3037 hmac = (char *)silc_hmac_get_name(channel->hmac);
3041 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3042 /* User limit is set on channel */
3043 SilcUInt32 user_limit;
3045 /* Get user limit */
3046 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3048 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3049 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3050 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3054 SILC_GET32_MSB(user_limit, tmp);
3055 channel->user_limit = user_limit;
3058 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3059 /* User limit mode is unset. Remove user limit */
3060 channel->user_limit = 0;
3063 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3064 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3065 /* Passphrase has been set to channel */
3067 /* Get the passphrase */
3068 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3070 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3071 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3075 /* Save the passphrase */
3076 passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
3079 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3080 /* Passphrase mode is unset. remove the passphrase */
3081 silc_free(channel->passphrase);
3082 channel->passphrase = NULL;
3086 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3087 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3088 /* Cipher to use protect the traffic */
3089 SilcCipher send_key, receive_key, olds, oldr;
3092 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3094 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3095 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3099 /* Delete old cipher and allocate the new one */
3100 if (!silc_cipher_alloc(cipher, &send_key)) {
3101 silc_server_command_send_status_data(
3102 cmd, SILC_COMMAND_CMODE,
3103 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
3104 2, cipher, strlen(cipher));
3107 if (!silc_cipher_alloc(cipher, &receive_key)) {
3108 silc_server_command_send_status_data(
3109 cmd, SILC_COMMAND_CMODE,
3110 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
3111 2, cipher, strlen(cipher));
3115 olds = channel->send_key;
3116 oldr = channel->receive_key;
3117 channel->send_key = send_key;
3118 channel->receive_key = receive_key;
3120 /* Re-generate channel key */
3121 if (!silc_server_create_channel_key(server, channel, 0)) {
3122 /* We don't have new key, revert to old one */
3123 channel->send_key = olds;
3124 channel->receive_key = oldr;
3128 /* Remove old channel key for good */
3129 silc_cipher_free(olds);
3130 silc_cipher_free(oldr);
3132 /* Send the channel key. This sends it to our local clients and if
3133 we are normal server to our router as well. */
3134 silc_server_send_channel_key(server, NULL, channel,
3135 server->server_type == SILC_ROUTER ?
3136 FALSE : !server->standalone);
3139 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3140 /* Cipher mode is unset. Remove the cipher and revert back to
3142 SilcCipher send_key, receive_key, olds, oldr;
3143 cipher = channel->cipher;
3145 /* Delete old cipher and allocate default one */
3146 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER,
3148 silc_server_command_send_status_data(
3149 cmd, SILC_COMMAND_CMODE,
3150 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
3151 2, cipher, strlen(cipher));
3154 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER,
3156 silc_server_command_send_status_data(
3157 cmd, SILC_COMMAND_CMODE,
3158 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
3159 2, cipher, strlen(cipher));
3163 olds = channel->send_key;
3164 oldr = channel->receive_key;
3165 channel->send_key = send_key;
3166 channel->receive_key = receive_key;
3168 /* Re-generate channel key */
3169 if (!silc_server_create_channel_key(server, channel, 0)) {
3170 /* We don't have new key, revert to old one */
3171 channel->send_key = olds;
3172 channel->receive_key = oldr;
3176 /* Remove old channel key for good */
3177 silc_cipher_free(olds);
3178 silc_cipher_free(oldr);
3180 /* Send the channel key. This sends it to our local clients and if
3181 we are normal server to our router as well. */
3182 silc_server_send_channel_key(server, NULL, channel,
3183 server->server_type == SILC_ROUTER ?
3184 FALSE : !server->standalone);
3188 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3189 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3190 /* HMAC to use protect the traffic */
3191 unsigned char hash[SILC_HASH_MAXLEN];
3195 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3197 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3198 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3202 /* Delete old hmac and allocate the new one */
3203 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
3204 silc_server_command_send_status_data(
3205 cmd, SILC_COMMAND_CMODE,
3206 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
3207 2, hmac, strlen(hmac));
3211 silc_hmac_free(channel->hmac);
3212 channel->hmac = newhmac;
3214 /* Set the HMAC key out of current channel key. The client must do
3216 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
3217 channel->key_len / 8, hash);
3218 silc_hmac_set_key(channel->hmac, hash,
3219 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3220 memset(hash, 0, sizeof(hash));
3223 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
3224 /* Hmac mode is unset. Remove the hmac and revert back to
3227 unsigned char hash[SILC_HASH_MAXLEN];
3228 hmac = channel->hmac_name;
3230 /* Delete old hmac and allocate default one */
3231 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
3232 silc_server_command_send_status_data(
3233 cmd, SILC_COMMAND_CMODE,
3234 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
3235 2, hmac, strlen(hmac));
3239 silc_hmac_free(channel->hmac);
3240 channel->hmac = newhmac;
3242 /* Set the HMAC key out of current channel key. The client must do
3244 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
3245 channel->key_len / 8,
3247 silc_hmac_set_key(channel->hmac, hash,
3248 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3249 memset(hash, 0, sizeof(hash));
3253 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3254 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3255 /* Check if the founder public key was received */
3256 founder_key = idata->public_key;
3257 tmp = silc_argument_get_arg_type(cmd->args, 8, &tmp_len);
3259 if (!silc_public_key_payload_decode(tmp, tmp_len, &founder_key)) {
3260 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3261 SILC_STATUS_ERR_AUTH_FAILED,
3266 /* If key was not sent and the channel mode has already founder
3267 then the key was not to be changed. */
3268 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)
3272 /* Set the founder authentication */
3273 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
3275 silc_server_command_send_status_reply(
3276 cmd, SILC_COMMAND_CMODE,
3277 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3281 /* Verify the payload before setting the mode */
3282 if (!silc_auth_verify_data(tmp, tmp_len, SILC_AUTH_PUBLIC_KEY,
3283 founder_key, 0, server->sha1hash,
3284 client->id, SILC_ID_CLIENT)) {
3285 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3286 SILC_STATUS_ERR_AUTH_FAILED,
3291 /* Save the public key */
3292 if (channel->founder_key)
3293 silc_pkcs_public_key_free(channel->founder_key);
3294 if (silc_argument_get_arg_type(cmd->args, 8, NULL))
3295 channel->founder_key = founder_key;
3297 channel->founder_key = silc_pkcs_public_key_copy(founder_key);
3298 if (!channel->founder_key) {
3299 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3300 SILC_STATUS_ERR_AUTH_FAILED,
3305 fkey = silc_public_key_payload_encode(channel->founder_key);
3307 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3308 SILC_STATUS_ERR_AUTH_FAILED,
3310 silc_pkcs_public_key_free(channel->founder_key);
3311 channel->founder_key = NULL;
3316 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3317 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3318 if (channel->founder_key)
3319 silc_pkcs_public_key_free(channel->founder_key);
3320 channel->founder_key = NULL;
3326 if (mode_mask & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
3327 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3330 chpkdata = silc_argument_get_arg_type(cmd->args, 9, &chpklen);
3332 if (!chpkdata && channel->mode & SILC_CHANNEL_MODE_CHANNEL_AUTH)
3337 /* Process the channel public key(s) */
3338 st = silc_server_set_channel_pk_list(server, NULL, channel,
3340 if (st != SILC_STATUS_OK) {
3341 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE, st, 0);
3346 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3347 if (channel->mode & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
3348 if (channel->channel_pubkeys)
3349 silc_hash_table_free(channel->channel_pubkeys);
3350 channel->channel_pubkeys = NULL;
3357 /* Finally, set the mode */
3358 old_mask = channel->mode = mode_mask;
3360 /* Send CMODE_CHANGE notify. */
3361 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3362 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT)
3363 SILC_PUT32_MSB(channel->user_limit, ulimit);
3364 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
3365 SILC_NOTIFY_TYPE_CMODE_CHANGE, 8,
3366 cidp->data, silc_buffer_len(cidp),
3368 cipher, cipher ? strlen(cipher) : 0,
3369 hmac, hmac ? strlen(hmac) : 0,
3370 passphrase, passphrase ?
3371 strlen(passphrase) : 0,
3372 fkey ? fkey->data : NULL,
3373 fkey ? silc_buffer_len(fkey) : 0,
3374 chpkdata ? chpkdata : NULL,
3375 chpkdata ? chpklen : 0,
3376 mode_mask & SILC_CHANNEL_MODE_ULIMIT ?
3378 mode_mask & SILC_CHANNEL_MODE_ULIMIT ?
3379 sizeof(ulimit) : 0);
3381 /* Set CMODE notify type to network */
3382 if (chpkdata && chpklen)
3383 silc_buffer_set(&chpk, chpkdata, chpklen);
3384 silc_server_send_notify_cmode(server, SILC_PRIMARY_ROUTE(server),
3385 SILC_BROADCAST(server), channel,
3386 mode_mask, client->id, SILC_ID_CLIENT,
3387 cipher, hmac, passphrase, founder_key,
3388 chpkdata ? &chpk : NULL);
3391 chpklist = silc_server_get_channel_pk_list(server, channel, FALSE, FALSE);
3393 /* Send command reply to sender */
3394 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3395 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_CMODE,
3396 SILC_STATUS_OK, 0, ident, 5,
3397 2, tmp_id, tmp_len2,
3399 4, fkey ? fkey->data : NULL,
3400 fkey ? silc_buffer_len(fkey) : 0,
3401 5, chpklist ? chpklist->data :
3402 NULL, chpklist ? silc_buffer_len(chpklist)
3405 SILC_CHANNEL_MODE_ULIMIT ?
3408 SILC_CHANNEL_MODE_ULIMIT ?
3409 sizeof(ulimit) : 0));
3410 silc_buffer_free(cidp);
3413 channel->mode = old_mask;
3414 silc_buffer_free(chpklist);
3415 silc_buffer_free(fkey);
3416 silc_server_command_free(cmd);
3419 /* Server side of CUMODE command. Changes client's mode on a channel. */
3421 SILC_SERVER_CMD_FUNC(cumode)
3423 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3424 SilcServer server = cmd->server;
3425 SilcClientEntry client = silc_packet_get_context(cmd->sock);
3427 SilcChannelEntry channel;
3428 SilcClientEntry target_client;
3429 SilcChannelClientEntry chl;
3431 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
3432 SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
3434 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3435 SilcPublicKey founder_key = NULL;
3436 SilcBuffer fkey = NULL;
3441 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
3443 /* Get Channel ID */
3444 if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
3445 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3446 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3450 /* Get channel entry */
3451 channel = silc_idlist_find_channel_by_id(server->local_list,
3452 SILC_ID_GET_ID(id), NULL);
3454 channel = silc_idlist_find_channel_by_id(server->global_list,
3455 SILC_ID_GET_ID(id), NULL);
3457 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3458 silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3459 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
3460 0, 2, tmp_ch_id, tmp_ch_len);
3465 /* Check whether sender is on the channel */
3466 if (!silc_server_client_on_channel(client, channel, &chl)) {
3467 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3468 silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3469 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
3470 2, tmp_ch_id, tmp_ch_len);
3473 sender_mask = chl->mode;
3475 /* Get the target client's channel mode mask */
3476 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3478 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3479 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3483 SILC_GET32_MSB(target_mask, tmp_mask);
3485 /* Get target Client ID */
3486 if (!silc_argument_get_decoded(cmd->args, 3, SILC_ARGUMENT_ID, &id2, NULL)) {
3487 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3488 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
3492 /* Get target client's entry */
3493 target_client = silc_idlist_find_client_by_id(server->local_list,
3494 SILC_ID_GET_ID(id2),
3497 target_client = silc_idlist_find_client_by_id(server->global_list,
3498 SILC_ID_GET_ID(id2),
3501 if (target_client != client &&
3502 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
3503 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
3504 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3505 silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3506 SILC_STATUS_ERR_NOT_YOU, 0,
3507 2, tmp_ch_id, tmp_ch_len);
3511 /* Check whether target client is on the channel */
3512 if (target_client != client) {
3513 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
3514 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3515 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3516 silc_server_command_send_status_data2(
3517 cmd, SILC_COMMAND_CUMODE,
3518 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL, 0,
3520 3, tmp_ch_id, tmp_ch_len);
3529 /* If the target client is founder, no one else can change their mode
3531 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
3532 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3533 silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3534 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
3535 0, 2, tmp_ch_id, tmp_ch_len);
3539 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
3540 if (target_client != client) {
3541 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3542 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
3547 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
3548 /* The client tries to claim the founder rights. */
3549 unsigned char *tmp_auth;
3550 SilcUInt32 tmp_auth_len;
3551 SilcChannelClientEntry chl2;
3552 SilcHashTableList htl;
3554 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
3555 !channel->founder_key) {
3556 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3557 SILC_STATUS_ERR_AUTH_FAILED, 0);
3561 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
3563 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3564 SILC_STATUS_ERR_AUTH_FAILED, 0);
3568 /* Verify the authentication payload */
3569 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len, SILC_AUTH_PUBLIC_KEY,
3570 channel->founder_key, 0, server->sha1hash,
3571 client->id, SILC_ID_CLIENT)) {
3572 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3573 SILC_STATUS_ERR_AUTH_FAILED, 0);
3578 founder_key = channel->founder_key;
3579 fkey = silc_public_key_payload_encode(founder_key);
3581 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3582 SILC_STATUS_ERR_AUTH_FAILED, 0);
3586 /* There cannot be anyone else as founder on the channel now. This
3587 client is definitely the founder due to this authentication. This
3588 is done only on router, not on server, since server cannot know
3589 whether router will accept this mode change or not. XXX This
3590 probably shouldn't be done anymore at all, may cause problems in
3591 router-router connections too (maybe just AUTH_FAILED error should
3592 be returned). -Pekka */
3593 if (server->server_type == SILC_ROUTER) {
3594 silc_hash_table_list(channel->user_list, &htl);
3595 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
3596 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
3597 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3598 silc_server_force_cumode_change(server, NULL, channel, chl2,
3602 silc_hash_table_list_reset(&htl);
3605 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
3608 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3609 if (target_client == client) {
3610 /* Remove channel founder rights from itself */
3611 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3614 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3615 SILC_STATUS_ERR_NOT_YOU, 0);
3621 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
3622 /* Promote to operator */
3623 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3624 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3625 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3626 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3627 silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3628 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
3629 0, 2, tmp_ch_id, tmp_ch_len);
3633 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
3637 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
3638 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3639 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3640 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3641 silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3642 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
3643 0, 2, tmp_ch_id, tmp_ch_len);
3647 /* Demote to normal user */
3648 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
3653 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
3654 if (target_client != client) {
3655 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3656 SILC_STATUS_ERR_NOT_YOU, 0);
3660 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
3661 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
3665 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
3666 if (target_client != client) {
3667 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3668 SILC_STATUS_ERR_NOT_YOU, 0);
3672 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
3677 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
3678 if (target_client != client) {
3679 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3680 SILC_STATUS_ERR_NOT_YOU, 0);
3684 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)) {
3685 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
3689 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
3690 if (target_client != client) {
3691 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3692 SILC_STATUS_ERR_NOT_YOU, 0);
3696 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
3701 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
3702 if (target_client != client) {
3703 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3704 SILC_STATUS_ERR_NOT_YOU, 0);
3708 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)) {
3709 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
3713 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
3714 if (target_client != client) {
3715 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3716 SILC_STATUS_ERR_NOT_YOU, 0);
3720 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
3725 if (target_mask & SILC_CHANNEL_UMODE_QUIET) {
3726 if (!(chl->mode & SILC_CHANNEL_UMODE_QUIET)) {
3727 if (client == target_client) {
3728 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3729 SILC_STATUS_ERR_PERM_DENIED, 0);
3732 chl->mode |= SILC_CHANNEL_UMODE_QUIET;
3736 if (chl->mode & SILC_CHANNEL_UMODE_QUIET) {
3737 if (client == target_client) {
3738 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3739 SILC_STATUS_ERR_PERM_DENIED, 0);
3742 chl->mode &= ~SILC_CHANNEL_UMODE_QUIET;
3747 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3748 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3749 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3751 /* Send notify to channel, notify only if mode was actually changed. */
3753 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
3754 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
3755 idp->data, silc_buffer_len(idp),
3758 fkey ? fkey->data : NULL,
3759 fkey ? silc_buffer_len(fkey) : 0);
3761 /* Set CUMODE notify type to network */
3762 silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
3763 SILC_BROADCAST(server), channel,
3764 target_mask, client->id, SILC_ID_CLIENT,
3765 target_client->id, founder_key);
3768 /* Send command reply to sender */
3769 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_CUMODE,
3770 SILC_STATUS_OK, 0, ident, 3,
3772 3, tmp_ch_id, tmp_ch_len,
3773 4, tmp_id, tmp_len);
3774 silc_buffer_free(idp);
3777 silc_buffer_free(fkey);
3778 silc_server_command_free(cmd);
3781 /* Server side of KICK command. Kicks client out of channel. */
3783 SILC_SERVER_CMD_FUNC(kick)
3785 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3786 SilcServer server = cmd->server;
3787 SilcClientEntry client = silc_packet_get_context(cmd->sock);
3788 SilcClientEntry target_client;
3790 SilcChannelEntry channel;
3791 SilcChannelClientEntry chl;
3793 SilcUInt32 tmp_len, target_idp_len, clen;
3794 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3795 unsigned char *tmp, *comment, *target_idp;
3800 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
3802 /* Get Channel ID */
3803 if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
3804 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3805 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3809 /* Get channel entry */
3810 channel = silc_idlist_find_channel_by_id(server->local_list,
3811 SILC_ID_GET_ID(id), NULL);
3813 channel = silc_idlist_find_channel_by_id(server->local_list,
3814 SILC_ID_GET_ID(id), NULL);
3816 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3817 silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3818 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
3819 0, 2, tmp, tmp_len);
3824 /* Check whether sender is on the channel */
3825 if (!silc_server_client_on_channel(client, channel, &chl)) {
3826 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3827 silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3828 SILC_STATUS_ERR_NOT_ON_CHANNEL,
3829 0, 2, tmp, tmp_len);
3833 /* Check that the kicker is channel operator or channel founder */
3834 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
3835 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
3836 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3837 silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3838 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
3839 0, 2, tmp, tmp_len);
3843 /* Get target Client ID */
3844 if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id2, NULL)) {
3845 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3846 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
3850 /* Get target client's entry */
3851 target_client = silc_idlist_find_client_by_id(server->local_list,
3852 SILC_ID_GET_ID(id2),
3855 target_client = silc_idlist_find_client_by_id(server->global_list,
3856 SILC_ID_GET_ID(id2),
3859 /* Check whether target client is on the channel */
3860 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
3861 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3862 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
3863 silc_server_command_send_status_data2(cmd, SILC_COMMAND_KICK,
3864 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL,
3865 0, 2, target_idp, target_idp_len,
3870 /* Check that the target client is not channel founder. Channel founder
3871 cannot be kicked from the channel. */
3872 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3873 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3874 silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3875 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
3876 0, 2, tmp, tmp_len);
3881 comment = silc_argument_get_arg_type(cmd->args, 3, &clen);
3885 /* Send the reply back to the client */
3886 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3887 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
3888 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_KICK,
3889 SILC_STATUS_OK, 0, ident, 2,
3891 3, target_idp, target_idp_len);
3893 /* Send KICKED notify to local clients on the channel */
3894 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3895 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
3896 SILC_NOTIFY_TYPE_KICKED, 3,
3897 target_idp, target_idp_len,
3898 comment, comment ? strlen(comment) : 0,
3899 idp->data, silc_buffer_len(idp));
3900 silc_buffer_free(idp);
3902 /* Send KICKED notify to primary route */
3903 silc_server_send_notify_kicked(server, SILC_PRIMARY_ROUTE(server),
3904 SILC_BROADCAST(server), channel,
3905 target_client->id, client->id, comment);
3907 /* Remove the client from channel's invite list */
3908 if (channel->invite_list && silc_hash_table_count(channel->invite_list)) {
3910 silc_argument_payload_encode_one(NULL, target_idp, target_idp_len, 3);
3911 SilcArgumentPayload args =
3912 silc_argument_payload_parse(ab->data, silc_buffer_len(ab), 1);
3914 silc_server_inviteban_process(server, channel->invite_list, 1, args);
3915 silc_buffer_free(ab);
3916 silc_argument_payload_free(args);
3919 /* Remove the client from the channel. If the channel does not exist
3920 after removing the client then the client kicked itself off the channel
3921 and we don't have to send anything after that. */
3922 if (!silc_server_remove_from_one_channel(server, NULL, channel,
3923 target_client, FALSE))
3926 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3927 /* Re-generate channel key */
3928 if (!silc_server_create_channel_key(server, channel, 0))
3931 /* Send the channel key to the channel. The key of course is not sent
3932 to the client who was kicked off the channel. */
3933 silc_server_send_channel_key(server, target_client->connection, channel,
3934 server->server_type == SILC_ROUTER ?
3935 FALSE : !server->standalone);
3939 silc_server_command_free(cmd);
3942 /* Server side of OPER command. Client uses this comand to obtain server
3943 operator privileges to this server/router. */
3945 SILC_SERVER_CMD_FUNC(oper)
3947 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3948 SilcServer server = cmd->server;
3949 SilcClientEntry client = silc_packet_get_context(cmd->sock);
3950 unsigned char *username = NULL, *auth;
3952 SilcServerConfigAdmin *admin;
3953 SilcIDListData idata = (SilcIDListData)client;
3954 SilcBool result = FALSE;
3955 SilcPublicKey cached_key;
3956 const char *hostname, *ip;
3958 if (client->data.conn_type != SILC_CONN_CLIENT || !client)
3961 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
3963 silc_socket_stream_get_info(silc_packet_stream_get_stream(cmd->sock),
3964 NULL, &hostname, &ip, NULL);
3966 /* Get the username */
3967 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3969 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3970 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3975 /* Check username */
3976 username = silc_identifier_check(username, strlen(username),
3977 SILC_STRING_UTF8, 128, &tmp_len);
3979 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3980 SILC_STATUS_ERR_BAD_USERNAME,
3985 /* Get the admin configuration */
3986 admin = silc_server_config_find_admin(server, (char *)ip,
3987 username, client->nickname);
3989 admin = silc_server_config_find_admin(server, (char *)hostname,
3990 username, client->nickname);
3992 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3993 SILC_STATUS_ERR_AUTH_FAILED,
3995 SILC_LOG_INFO(("OPER authentication failed for username '%s' by "
3996 "nickname '%s' from %s", username,
3997 client->nickname, hostname));
4002 /* Get the authentication payload */
4003 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4005 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4006 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4011 /* Verify the authentication data. If both passphrase and public key
4012 is set then try both of them. */
4013 if (admin->passphrase)
4014 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4015 admin->passphrase, admin->passphrase_len,
4016 idata->hash, client->id, SILC_ID_CLIENT);
4017 if (!result && admin->publickeys) {
4019 silc_server_get_public_key(server,
4020 SILC_SKR_USAGE_SERVICE_AUTHORIZATION, admin);
4023 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4024 cached_key, 0, idata->hash,
4025 client->id, SILC_ID_CLIENT);
4028 /* Authentication failed */
4029 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4030 SILC_STATUS_ERR_AUTH_FAILED,
4035 /* Client is now server operator */
4036 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4038 /* Update statistics */
4039 if (SILC_IS_LOCAL(client))
4040 server->stat.my_server_ops++;
4041 if (server->server_type == SILC_ROUTER)
4042 server->stat.server_ops++;
4044 /* Send UMODE change to primary router */
4045 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
4046 SILC_BROADCAST(server), client->id,
4049 /* Check if anyone is watching this nickname */
4050 if (server->server_type == SILC_ROUTER)
4051 silc_server_check_watcher_list(server, client, NULL,
4052 SILC_NOTIFY_TYPE_UMODE_CHANGE);
4054 /* Send reply to the sender */
4055 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4059 silc_free(username);
4060 silc_server_command_free(cmd);
4063 SILC_TASK_CALLBACK(silc_server_command_detach_cb)
4065 SilcServer server = app_context;
4066 QuitInternal q = (QuitInternal)context;
4067 SilcClientID *client_id = (SilcClientID *)q->sock;
4068 SilcClientEntry client;
4069 SilcPacketStream sock;
4071 client = silc_idlist_find_client_by_id(server->local_list, client_id,
4073 if (client && client->connection) {
4074 sock = client->connection;
4076 /* Close the connection on our side */
4077 client->router = NULL;
4078 client->connection = NULL;
4079 silc_server_close_connection(server, sock);
4082 silc_free(client_id);
4086 SILC_TASK_CALLBACK(silc_server_command_detach_timeout)
4088 SilcServer server = app_context;
4089 QuitInternal q = (QuitInternal)context;
4090 SilcClientID *client_id = (SilcClientID *)q->sock;
4091 SilcClientEntry client;
4093 client = silc_idlist_find_client_by_id(server->local_list, client_id,
4095 if (client && client->mode & SILC_UMODE_DETACHED) {
4096 SILC_LOG_DEBUG(("Detach timeout"));
4097 silc_server_free_client_data(server, NULL, client, TRUE,
4101 silc_free(client_id);
4105 /* Server side of DETACH command. Detached the client from the network
4106 by closing the connection but preserving the session. */
4108 SILC_SERVER_CMD_FUNC(detach)
4110 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4111 SilcServer server = cmd->server;
4112 SilcClientEntry client = silc_packet_get_context(cmd->sock);
4115 if (server->config->detach_disabled) {
4116 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
4117 SILC_STATUS_ERR_OPERATION_ALLOWED,
4122 if (client->data.conn_type != SILC_CONN_CLIENT || !client)
4125 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
4127 /* Remove operator privileges, since the client may resume in some
4128 other server which to it does not have operator privileges. */
4129 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
4130 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
4132 /* Send the user mode notify to notify that client is detached */
4133 client->mode |= SILC_UMODE_DETACHED;
4134 client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
4135 client->data.status &= ~SILC_IDLIST_STATUS_NOATTR;
4136 client->last_command = 0;
4137 client->fast_command = 0;
4138 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
4139 SILC_BROADCAST(server), client->id,
4141 server->stat.my_detached++;
4143 /* Check if anyone is watching this nickname */
4144 if (server->server_type == SILC_ROUTER)
4145 silc_server_check_watcher_list(server, client, NULL,
4146 SILC_NOTIFY_TYPE_UMODE_CHANGE);
4148 q = silc_calloc(1, sizeof(*q));
4149 q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
4150 silc_schedule_task_add_timeout(server->schedule,
4151 silc_server_command_detach_cb,
4154 if (server->config->detach_timeout) {
4155 q = silc_calloc(1, sizeof(*q));
4156 q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
4157 silc_schedule_task_add_timeout(server->schedule,
4158 silc_server_command_detach_timeout,
4159 q, server->config->detach_timeout * 60, 0);
4162 /* Send reply to the sender */
4163 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
4167 silc_server_command_free(cmd);
4170 /* Server side of WATCH command. */
4172 SILC_SERVER_CMD_FUNC(watch)
4174 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4175 SilcServer server = cmd->server;
4176 char *add_nick, *del_nick;
4177 SilcUInt32 add_nick_len, del_nick_len, tmp_len, pk_len;
4178 unsigned char hash[SILC_HASH_MAXLEN], *tmp, *pk, *nick;
4179 SilcClientEntry client;
4181 SilcUInt16 old_ident;
4183 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WATCH, cmd, 1, 3);
4185 if (server->server_type != SILC_ROUTER && !server->standalone) {
4186 if (!cmd->pending) {
4187 /* Send the command to router */
4190 /* If backup receives this from primary, handle it locally */
4191 if (server->server_type == SILC_BACKUP_ROUTER &&
4192 cmd->sock == SILC_PRIMARY_ROUTE(server))
4195 SILC_LOG_DEBUG(("Forwarding WATCH to router"));
4198 cmd->server->stat.commands_sent++;
4200 old_ident = silc_command_get_ident(cmd->payload);
4201 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4202 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4204 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
4205 SILC_PACKET_COMMAND, cmd->packet->flags,
4206 tmpbuf->data, silc_buffer_len(tmpbuf));
4208 /* Reprocess this packet after received reply from router */
4209 silc_server_command_pending(server, SILC_COMMAND_WATCH,
4210 silc_command_get_ident(cmd->payload),
4211 silc_server_command_watch,
4212 silc_server_command_dup(cmd));
4213 cmd->pending = TRUE;
4214 silc_command_set_ident(cmd->payload, old_ident);
4215 silc_buffer_free(tmpbuf);
4218 SilcServerCommandReplyContext reply = context2;
4224 silc_command_get_status(reply->payload, &status, NULL);
4226 /* Backup router handles the WATCH command also. */
4227 if (server->server_type != SILC_BACKUP_ROUTER ||
4228 SILC_STATUS_IS_ERROR(status)) {
4229 /* Received reply from router, just send same data to the client. */
4230 SILC_LOG_DEBUG(("Received reply to WATCH from router"));
4231 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, status,
4238 /* We are router and keep the watch list for local cell */
4241 /* Get the client ID */
4242 if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
4243 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4244 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4249 /* Get the client entry which must be in local list */
4250 client = silc_idlist_find_client_by_id(server->local_list,
4251 SILC_ID_GET_ID(id), TRUE, NULL);
4253 /* Backup checks global list also */
4254 if (server->server_type == SILC_BACKUP_ROUTER)
4255 client = silc_idlist_find_client_by_id(server->global_list,
4256 SILC_ID_GET_ID(id), TRUE, NULL);
4258 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4259 silc_server_command_send_status_data(cmd, SILC_COMMAND_WATCH,
4260 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
4261 0, 2, tmp, tmp_len);
4266 /* Take public key for watching by public key */
4267 pk = silc_argument_get_arg_type(cmd->args, 4, &pk_len);
4270 add_nick = silc_argument_get_arg_type(cmd->args, 2, &add_nick_len);
4271 del_nick = silc_argument_get_arg_type(cmd->args, 3, &del_nick_len);
4272 if (!add_nick && !del_nick && !pk) {
4273 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4274 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4279 if (add_nick && add_nick_len > 128) {
4281 add_nick[add_nick_len - 1] = '\0';
4283 if (del_nick && del_nick_len > 128) {
4285 del_nick[del_nick_len - 1] = '\0';
4288 /* Add new nickname to be watched in our cell */
4290 nick = silc_identifier_check(add_nick, add_nick_len, SILC_STRING_UTF8, 128,
4293 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4294 SILC_STATUS_ERR_BAD_NICKNAME, 0);
4298 /* Hash the nick, we have the hash saved, not nicks because we can
4299 do one to one mapping to the nick from Client ID hash this way. */
4300 silc_hash_make(server->md5hash, nick, add_nick_len, hash);
4302 /* Check whether this client is already watching this nickname */
4303 if (silc_hash_table_find_by_context(server->watcher_list, hash,
4305 /* Nickname is alredy being watched for this client */
4306 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4307 SILC_STATUS_ERR_NICKNAME_IN_USE,
4313 /* Get the nickname from the watcher list and use the same key in
4314 new entries as well. If key doesn't exist then create it. */
4315 if (!silc_hash_table_find(server->watcher_list, hash, (void *)&tmp, NULL))
4316 tmp = silc_memdup(hash, CLIENTID_HASH_LEN);
4318 /* Add the client to the watcher list with the specified nickname hash. */
4319 silc_hash_table_add(server->watcher_list, tmp, client);
4323 /* Delete nickname from watch list */
4325 nick = silc_identifier_check(del_nick, del_nick_len, SILC_STRING_UTF8, 128,
4328 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4329 SILC_STATUS_ERR_BAD_NICKNAME, 0);
4333 /* Hash the nick, we have the hash saved, not nicks because we can
4334 do one to one mapping to the nick from Client ID hash this way. */
4335 silc_hash_make(server->md5hash, nick, del_nick_len, hash);
4337 /* Check that this client is watching for this nickname */
4338 if (!silc_hash_table_find_by_context(server->watcher_list, hash,
4339 client, (void *)&tmp)) {
4340 /* Nickname is alredy being watched for this client */
4341 silc_server_command_send_status_data(cmd, SILC_COMMAND_WATCH,
4342 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
4343 2, nick, del_nick_len);
4348 /* Delete the nickname from the watcher list. */
4349 silc_hash_table_del_by_context(server->watcher_list, hash, client);
4351 /* Now check whether there still exists entries with this key, if not
4352 then free the key to not leak memory. */
4353 if (!silc_hash_table_find(server->watcher_list, hash, NULL, NULL))
4358 /* Add/del public key */
4361 SilcArgumentPayload pkargs;
4363 SilcPublicKey public_key, pkkey;
4366 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4367 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4372 /* Get the argument from the Argument List Payload */
4373 SILC_GET16_MSB(pkargc, pk);
4374 pkargs = silc_argument_payload_parse(pk + 2, pk_len - 2, pkargc);
4376 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4377 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4382 pk = silc_argument_get_next_arg(pkargs, &type, &pk_len);
4384 if (!silc_public_key_payload_decode(pk, pk_len, &public_key)) {
4385 pk = silc_argument_get_next_arg(pkargs, &type, &pk_len);
4392 /* Add public key to watch list */
4394 /* Check whether this client is already watching this public key */
4395 if (silc_hash_table_find_by_context(server->watcher_list_pk,
4396 public_key, client, NULL)) {
4397 silc_pkcs_public_key_free(public_key);
4398 silc_server_command_send_status_reply(
4399 cmd, SILC_COMMAND_WATCH,
4400 SILC_STATUS_ERR_NICKNAME_IN_USE, 0);
4404 /* Get the public key from the watcher list and use the same key in
4405 new entries as well. If key doesn't exist then create it. */
4407 if (!silc_hash_table_find(server->watcher_list_pk, public_key,
4408 (void *)&pkkey, NULL))
4411 silc_pkcs_public_key_free(public_key);
4413 /* Add the client to the watcher list with the specified public
4415 silc_hash_table_add(server->watcher_list_pk, pkkey, client);
4417 } else if (type == 0x01) {
4418 /* Delete public key from watch list */
4420 /* Check that this client is watching this public key */
4421 if (silc_hash_table_find_by_context(server->watcher_list_pk,
4424 silc_pkcs_public_key_free(public_key);
4425 silc_server_command_send_status_reply(
4426 cmd, SILC_COMMAND_WATCH,
4427 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4431 /* Delete the public key from the watcher list. */
4432 silc_hash_table_del_by_context(server->watcher_list_pk,
4433 public_key, client);
4435 /* Now check whether there still exists entries with this key, if
4436 not then free the key to not leak memory. */
4437 if (!silc_hash_table_find(server->watcher_list_pk, hash, NULL, NULL))
4438 silc_pkcs_public_key_free(pkkey);
4439 silc_pkcs_public_key_free(public_key);
4442 pk = silc_argument_get_next_arg(pkargs, &type, &pk_len);
4447 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4450 /* Distribute the watch list to backup routers too */
4451 if (server->backup) {
4455 cmd->server->stat.commands_sent++;
4457 old_ident = silc_command_get_ident(cmd->payload);
4458 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4459 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4460 silc_server_backup_send(server, silc_packet_get_context(cmd->sock),
4461 SILC_PACKET_COMMAND,
4462 cmd->packet->flags, tmpbuf->data,
4463 silc_buffer_len(tmpbuf),
4465 silc_command_set_ident(cmd->payload, old_ident);
4466 silc_buffer_free(tmpbuf);
4470 silc_server_command_free(cmd);
4473 /* Server side of SILCOPER command. Client uses this comand to obtain router
4474 operator privileges to this router. */
4476 SILC_SERVER_CMD_FUNC(silcoper)
4478 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4479 SilcServer server = cmd->server;
4480 SilcClientEntry client = silc_packet_get_context(cmd->sock);
4481 unsigned char *username = NULL, *auth;
4483 SilcServerConfigAdmin *admin;
4484 SilcIDListData idata = (SilcIDListData)client;
4485 SilcBool result = FALSE;
4486 SilcPublicKey cached_key;
4487 const char *hostname, *ip;
4489 if (client->data.conn_type != SILC_CONN_CLIENT || !client)
4492 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4494 silc_socket_stream_get_info(silc_packet_stream_get_stream(cmd->sock),
4495 NULL, &hostname, &ip, NULL);
4497 if (server->server_type != SILC_ROUTER) {
4498 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4499 SILC_STATUS_ERR_AUTH_FAILED, 0);
4503 /* Get the username */
4504 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4506 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4507 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4512 /* Check username */
4513 username = silc_identifier_check(username, tmp_len, SILC_STRING_UTF8, 128,
4516 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4517 SILC_STATUS_ERR_BAD_USERNAME,
4522 /* Get the admin configuration */
4523 admin = silc_server_config_find_admin(server, (char *)ip,
4524 username, client->nickname);
4526 admin = silc_server_config_find_admin(server, (char *)hostname,
4527 username, client->nickname);
4529 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4530 SILC_STATUS_ERR_AUTH_FAILED, 0);
4531 SILC_LOG_INFO(("SILCOPER authentication failed for username '%s' by "
4532 "nickname '%s' from %s", username,
4533 client->nickname, hostname));
4538 /* Get the authentication payload */
4539 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4541 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4542 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4547 /* Verify the authentication data. If both passphrase and public key
4548 is set then try both of them. */
4549 if (admin->passphrase)
4550 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4551 admin->passphrase, admin->passphrase_len,
4552 idata->hash, client->id, SILC_ID_CLIENT);
4553 if (!result && admin->publickeys) {
4555 silc_server_get_public_key(server,
4556 SILC_SKR_USAGE_SERVICE_AUTHORIZATION, admin);
4559 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4560 cached_key, 0, idata->hash,
4561 client->id, SILC_ID_CLIENT);
4564 /* Authentication failed */
4565 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4566 SILC_STATUS_ERR_AUTH_FAILED, 0);
4570 /* Client is now router operator */
4571 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4573 /* Update statistics */
4574 if (SILC_IS_LOCAL(client))
4575 server->stat.my_router_ops++;
4576 if (server->server_type == SILC_ROUTER)
4577 server->stat.router_ops++;
4579 /* Send UMODE change to primary router */
4580 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
4581 SILC_BROADCAST(server), client->id,
4584 /* Check if anyone is watching this nickname */
4585 if (server->server_type == SILC_ROUTER)
4586 silc_server_check_watcher_list(server, client, NULL,
4587 SILC_NOTIFY_TYPE_UMODE_CHANGE);
4589 /* Send reply to the sender */
4590 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4594 silc_free(username);
4595 silc_server_command_free(cmd);
4598 /* Server side of command BAN. This is used to manage the ban list of the
4599 channel. To add clients and remove clients from the ban list. */
4601 SILC_SERVER_CMD_FUNC(ban)
4603 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4604 SilcServer server = cmd->server;
4605 SilcClientEntry client = silc_packet_get_context(cmd->sock);
4606 SilcBuffer list, tmp2;
4607 SilcChannelEntry channel;
4608 SilcChannelClientEntry chl;
4610 unsigned char *tmp_id, *tmp, *atype = NULL;
4611 SilcUInt32 id_len, len, len2;
4612 SilcArgumentPayload args;
4613 SilcHashTableList htl;
4615 SilcUInt16 argc = 0, ident = silc_command_get_ident(cmd->payload);
4616 SilcBufferStruct blist;
4618 if (client->data.conn_type != SILC_CONN_CLIENT || !client)
4621 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4623 /* Get Channel ID */
4624 if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
4625 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4626 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4630 /* Get channel entry. The server must know about the channel since the
4631 client is expected to be on the channel. */
4632 channel = silc_idlist_find_channel_by_id(server->local_list,
4633 SILC_ID_GET_ID(id), NULL);
4635 channel = silc_idlist_find_channel_by_id(server->global_list,
4636 SILC_ID_GET_ID(id), NULL);
4638 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4639 silc_server_command_send_status_data(
4640 cmd, SILC_COMMAND_BAN,
4641 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
4642 0, 2, tmp_id, id_len);
4647 /* Check whether this client is on the channel */
4648 if (!silc_server_client_on_channel(client, channel, &chl)) {
4649 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4650 silc_server_command_send_status_data(cmd, SILC_COMMAND_BAN,
4651 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
4656 /* The client must be at least channel operator. */
4657 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4658 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4659 silc_server_command_send_status_data(cmd, SILC_COMMAND_BAN,
4660 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0,
4665 /* Get the ban information */
4666 tmp = silc_argument_get_arg_type(cmd->args, 3, &len2);
4667 if (tmp && len2 > 2) {
4668 /* Parse the arguments to see they are constructed correctly */
4669 SILC_GET16_MSB(argc, tmp);
4670 args = silc_argument_payload_parse(tmp + 2, len2 - 2, argc);
4672 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4673 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4678 /* Get the type of action */
4679 atype = silc_argument_get_arg_type(cmd->args, 2, &len);
4680 if (atype && len == 1) {
4681 if (atype[0] == 0x00) {
4682 /* Allocate hash table for ban list if it doesn't exist yet */
4683 if (!channel->ban_list)
4685 silc_hash_table_alloc(0, silc_hash_ptr,
4687 silc_server_inviteban_destruct, channel,
4690 /* Check for resource limit */
4691 if (silc_hash_table_count(channel->ban_list) > 64) {
4692 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4693 SILC_STATUS_ERR_RESOURCE_LIMIT,
4699 /* Now add or delete the information. */
4700 if (!silc_server_inviteban_process(server, channel->ban_list,
4701 (SilcUInt8)atype[0], args)) {
4702 silc_server_command_send_status_reply(
4703 cmd, SILC_COMMAND_BAN,
4704 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4709 silc_argument_payload_free(args);
4712 /* Encode ban list */
4714 if (channel->ban_list && silc_hash_table_count(channel->ban_list)) {
4715 list = silc_buffer_alloc_size(2);
4716 silc_buffer_format(list,
4717 SILC_STR_UI_SHORT(silc_hash_table_count(
4718 channel->ban_list)),
4720 silc_hash_table_list(channel->ban_list, &htl);
4721 while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2))
4722 list = silc_argument_payload_encode_one(list, tmp2->data,
4723 silc_buffer_len(tmp2),
4724 SILC_PTR_TO_32(type));
4725 silc_hash_table_list_reset(&htl);
4728 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4730 /* Send BAN notify type to local servers (but not clients) and to
4732 if (atype && tmp && len2) {
4733 silc_buffer_set(&blist, tmp, len2);
4735 /* Send to local servers if we are router */
4736 if (server->server_type == SILC_ROUTER)
4737 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, FALSE,
4738 SILC_NOTIFY_TYPE_BAN, 3,
4741 tmp ? blist.data : NULL,
4742 tmp ? silc_buffer_len(&blist) : 0);
4744 /* Send to network. */
4745 silc_server_send_notify_ban(server, SILC_PRIMARY_ROUTE(server),
4746 SILC_BROADCAST(server), channel, atype,
4750 /* Send the reply back to the client */
4751 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_BAN,
4752 SILC_STATUS_OK, 0, ident, 2,
4754 3, list ? list->data : NULL,
4755 list ? silc_buffer_len(list) : 0);
4756 silc_buffer_free(list);
4759 silc_server_command_free(cmd);
4762 /* Server side command of LEAVE. Removes client from a channel. */
4764 SILC_SERVER_CMD_FUNC(leave)
4766 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4767 SilcServer server = cmd->server;
4768 SilcPacketStream sock = cmd->sock;
4769 SilcClientEntry id_entry = silc_packet_get_context(cmd->sock);
4771 SilcChannelEntry channel;
4775 if (id_entry->data.conn_type != SILC_CONN_CLIENT || !id_entry)
4778 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4780 /* Get Channel ID */
4781 if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
4782 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4783 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4787 /* Get channel entry */
4788 channel = silc_idlist_find_channel_by_id(server->local_list,
4789 SILC_ID_GET_ID(id), NULL);
4791 channel = silc_idlist_find_channel_by_id(server->global_list,
4792 SILC_ID_GET_ID(id), NULL);
4794 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4795 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4796 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
4802 /* Check whether this client is on the channel */
4803 if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
4804 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4805 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4806 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
4811 /* Notify routers that they should remove this client from their list
4812 of clients on the channel. Send LEAVE notify type. */
4813 silc_server_send_notify_leave(server, SILC_PRIMARY_ROUTE(server),
4814 SILC_BROADCAST(server), channel, id_entry->id);
4816 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4817 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4818 SILC_STATUS_OK, 0, 2, tmp, len);
4820 /* Remove client from channel */
4821 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4823 /* If the channel does not exist anymore we won't send anything */
4826 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4827 /* Re-generate channel key */
4828 if (!silc_server_create_channel_key(server, channel, 0))
4831 /* Send the channel key */
4832 silc_server_send_channel_key(server, NULL, channel,
4833 server->server_type == SILC_ROUTER ?
4834 FALSE : !server->standalone);
4838 silc_server_command_free(cmd);
4841 /* Server side of command USERS. Resolves clients and their USERS currently
4842 joined on the requested channel. The list of Client ID's and their modes
4843 on the channel is sent back. */
4845 SILC_SERVER_CMD_FUNC(users)
4847 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4848 SilcServer server = cmd->server;
4849 SilcIDListData idata = silc_packet_get_context(cmd->sock);
4850 SilcChannelEntry channel;
4853 unsigned char *channel_id;
4854 SilcUInt32 channel_id_len;
4855 SilcBuffer client_id_list;
4856 SilcBuffer client_mode_list;
4857 unsigned char lc[4];
4858 SilcUInt32 list_count = 0;
4859 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4860 char *channel_name, *channel_namec = NULL;
4862 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
4864 /* Get Channel ID */
4865 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4867 /* Get channel name */
4868 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
4870 if (!channel_id && !channel_name) {
4871 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4872 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4876 /* Check channel name */
4878 channel_namec = silc_channel_name_check(channel_name, strlen(channel_name),
4879 SILC_STRING_UTF8, 256, NULL);
4880 if (!channel_namec) {
4881 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4882 SILC_STATUS_ERR_BAD_CHANNEL, 0);
4887 /* Check Channel ID */
4889 if (!silc_id_payload_parse_id(channel_id, channel_id_len, &id)) {
4890 silc_server_command_send_status_data(cmd, SILC_COMMAND_USERS,
4891 SILC_STATUS_ERR_BAD_CHANNEL_ID, 0,
4892 2, channel_id, channel_id_len);
4897 /* If we are server and we don't know about this channel we will send
4898 the command to our router. If we know about the channel then we also
4899 have the list of users already. */
4901 channel = silc_idlist_find_channel_by_id(server->local_list,
4902 SILC_ID_GET_ID(id), NULL);
4904 channel = silc_idlist_find_channel_by_name(server->local_list,
4905 channel_namec, NULL);
4907 if (!channel || (!server->standalone && (channel->disabled ||
4908 !channel->users_resolved))) {
4909 if (server->server_type != SILC_ROUTER && !server->standalone &&
4914 cmd->server->stat.commands_sent++;
4916 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4917 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4919 /* Send USERS command */
4920 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
4921 SILC_PACKET_COMMAND, cmd->packet->flags,
4922 tmpbuf->data, silc_buffer_len(tmpbuf));
4924 /* Reprocess this packet after received reply */
4925 silc_server_command_pending(server, SILC_COMMAND_USERS,
4926 silc_command_get_ident(cmd->payload),
4927 silc_server_command_users,
4928 silc_server_command_dup(cmd));
4929 cmd->pending = TRUE;
4930 silc_command_set_ident(cmd->payload, ident);
4931 silc_buffer_free(tmpbuf);
4935 /* Check the global list as well. */
4937 channel = silc_idlist_find_channel_by_id(server->global_list,
4938 SILC_ID_GET_ID(id), NULL);
4940 channel = silc_idlist_find_channel_by_name(server->global_list,
4941 channel_namec, NULL);
4943 /* Channel really does not exist */
4945 silc_server_command_send_status_data(
4946 cmd, SILC_COMMAND_USERS,
4947 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID, 0,
4948 2, channel_id, channel_id_len);
4950 silc_server_command_send_status_data(
4951 cmd, SILC_COMMAND_USERS,
4952 SILC_STATUS_ERR_NO_SUCH_CHANNEL, 0,
4953 2, channel_name, strlen(channel_name));
4958 /* If the channel is private or secret do not send anything, unless the
4959 user requesting this command is on the channel or is server */
4960 if (idata->conn_type == SILC_CONN_CLIENT) {
4961 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
4962 && !silc_server_client_on_channel((SilcClientEntry)idata, channel,
4964 silc_server_command_send_status_data(cmd, SILC_COMMAND_USERS,
4965 SILC_STATUS_ERR_NO_SUCH_CHANNEL, 0,
4966 2, channel->channel_name,
4967 strlen(channel->channel_name));
4972 /* Get the users list */
4973 if (!silc_server_get_users_on_channel(server, channel, &client_id_list,
4974 &client_mode_list, &list_count)) {
4976 client_id_list = NULL;
4977 client_mode_list = NULL;
4981 SILC_PUT32_MSB(list_count, lc);
4984 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
4985 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_USERS,
4986 SILC_STATUS_OK, 0, ident, 4,
4987 2, idp->data, silc_buffer_len(idp),
4990 client_id_list->data : NULL,
4992 silc_buffer_len(client_id_list) : 0,
4993 5, client_mode_list ?
4994 client_mode_list->data : NULL,
4996 silc_buffer_len(client_mode_list) : 0);
4997 silc_buffer_free(idp);
4999 silc_buffer_free(client_id_list);
5000 if (client_mode_list)
5001 silc_buffer_free(client_mode_list);
5004 silc_free(channel_namec);
5005 silc_server_command_free(cmd);
5008 /* Server side of command GETKEY. This fetches the client's public key
5009 from the server where to the client is connected. */
5011 SILC_SERVER_CMD_FUNC(getkey)
5013 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5014 SilcServer server = cmd->server;
5015 SilcClientEntry client;
5016 SilcServerEntry server_entry;
5017 SilcClientID client_id;
5018 SilcServerID server_id;
5019 SilcIDPayload idp = NULL;
5020 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5023 SilcBuffer pk = NULL;
5025 SilcPublicKey public_key;
5027 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5029 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5030 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5034 idp = silc_id_payload_parse(tmp, tmp_len);
5036 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5037 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5042 id_type = silc_id_payload_get_type(idp);
5043 if (id_type == SILC_ID_CLIENT) {
5044 silc_id_payload_get_id(idp, &client_id, sizeof(client_id));
5046 /* If the client is not found from local list there is no chance it
5047 would be locally connected client so send the command further. */
5048 client = silc_idlist_find_client_by_id(server->local_list,
5049 &client_id, TRUE, NULL);
5051 client = silc_idlist_find_client_by_id(server->global_list,
5052 &client_id, TRUE, NULL);
5054 if ((!client && !cmd->pending && !server->standalone) ||
5055 (client && !client->connection && !cmd->pending &&
5056 !(client->mode & SILC_UMODE_DETACHED)) ||
5057 (client && !client->data.public_key && !cmd->pending)) {
5059 SilcUInt16 old_ident;
5060 SilcPacketStream dest_sock;
5062 dest_sock = silc_server_get_client_route(server, NULL, 0,
5063 &client_id, NULL, NULL);
5068 cmd->server->stat.commands_sent++;
5070 old_ident = silc_command_get_ident(cmd->payload);
5071 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5072 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5074 silc_server_packet_send(server, dest_sock,
5075 SILC_PACKET_COMMAND, cmd->packet->flags,
5076 tmpbuf->data, silc_buffer_len(tmpbuf));
5078 /* Reprocess this packet after received reply from router */
5079 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5080 silc_command_get_ident(cmd->payload),
5081 silc_server_command_getkey,
5082 silc_server_command_dup(cmd));
5083 cmd->pending = TRUE;
5084 silc_command_set_ident(cmd->payload, old_ident);
5085 silc_buffer_free(tmpbuf);
5090 silc_server_command_send_status_data(cmd, SILC_COMMAND_GETKEY,
5091 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5092 0, 2, tmp, tmp_len);
5096 /* The client is locally connected, just get the public key and
5097 send it back. If they key does not exist then do not send it,
5098 send just OK reply */
5099 public_key = client->data.public_key;
5101 pk = silc_public_key_payload_encode(public_key);
5102 } else if (id_type == SILC_ID_SERVER) {
5103 silc_id_payload_get_id(idp, &server_id, sizeof(server_id));
5105 /* If the server is not found from local list there is no chance it
5106 would be locally connected server so send the command further. */
5107 server_entry = silc_idlist_find_server_by_id(server->local_list,
5108 &server_id, TRUE, NULL);
5110 server_entry = silc_idlist_find_server_by_id(server->global_list,
5111 &server_id, TRUE, NULL);
5113 if (server_entry != server->id_entry &&
5114 ((!server_entry && !cmd->pending && !server->standalone) ||
5115 (server_entry && !server_entry->connection && !cmd->pending &&
5116 !server->standalone) ||
5117 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5118 !server->standalone))) {
5120 SilcUInt16 old_ident;
5123 cmd->server->stat.commands_sent++;
5125 old_ident = silc_command_get_ident(cmd->payload);
5126 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5127 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5129 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5130 SILC_PACKET_COMMAND, cmd->packet->flags,
5131 tmpbuf->data, silc_buffer_len(tmpbuf));
5133 /* Reprocess this packet after received reply from router */
5134 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5135 silc_command_get_ident(cmd->payload),
5136 silc_server_command_getkey,
5137 silc_server_command_dup(cmd));
5138 cmd->pending = TRUE;
5139 silc_command_set_ident(cmd->payload, old_ident);
5140 silc_buffer_free(tmpbuf);
5144 if (!server_entry) {
5145 silc_server_command_send_status_data(cmd, SILC_COMMAND_GETKEY,
5146 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
5147 0, 2, tmp, tmp_len);
5151 /* If they key does not exist then do not send it, send just OK reply */
5152 public_key = (!server_entry->data.public_key ?
5153 (server_entry == server->id_entry ? server->public_key :
5154 NULL) : server_entry->data.public_key);
5156 pk = silc_public_key_payload_encode(public_key);
5161 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5162 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_GETKEY,
5163 SILC_STATUS_OK, 0, ident, 2,
5165 3, pk ? pk->data : NULL,
5166 pk ? silc_buffer_len(pk) : 0);
5170 silc_id_payload_free(idp);
5171 silc_buffer_free(pk);
5172 silc_server_command_free(cmd);
5175 /* Server side of command SERVICE. */
5176 /* XXX currently this just sends empty reply back */
5178 SILC_SERVER_CMD_FUNC(service)
5180 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5181 SilcServer server = cmd->server;
5182 SilcUInt32 tmp_len, auth_len;
5183 unsigned char *service_name, *auth;
5184 SilcBool send_list = FALSE;
5185 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5187 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SERVICE, cmd, 0, 256);
5189 /* Get requested service */
5190 service_name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5191 if (service_name && tmp_len) {
5192 /* Verify service name */
5193 if (!silc_identifier_verify(service_name, tmp_len,
5194 SILC_STRING_UTF8, 256)) {
5195 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SERVICE,
5196 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5202 /* Get authentication payload if present */
5203 auth = silc_argument_get_arg_type(cmd->args, 2, &auth_len);
5211 /* Send our service list back */
5212 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_SERVICE,
5213 SILC_STATUS_OK, 0, ident, 0);
5216 silc_server_command_free(cmd);
5220 /* Private range commands, specific to this implementation */
5222 /* Server side command of CONNECT. Connects us to the specified remote
5223 server or router. */
5225 SILC_SERVER_CMD_FUNC(connect)
5227 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5228 SilcServer server = cmd->server;
5229 SilcClientEntry client = silc_packet_get_context(cmd->sock);
5230 unsigned char *tmp, *host;
5232 SilcUInt32 port = SILC_PORT;
5234 if (client->data.conn_type != SILC_CONN_CLIENT || !client)
5237 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
5239 /* Check whether client has the permissions. */
5240 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5241 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5242 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5243 SILC_STATUS_ERR_NO_SERVER_PRIV, 0);
5247 if (server->server_type == SILC_ROUTER && !server->backup_router &&
5248 client->mode & SILC_UMODE_SERVER_OPERATOR) {
5249 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5250 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
5254 /* Get the remote server */
5255 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5257 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5258 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5264 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5266 SILC_GET32_MSB(port, tmp);
5268 /* Create the connection. It is done with timeout and is async. */
5269 silc_server_create_connection(server, FALSE, FALSE, host, port, NULL, NULL);
5271 /* Send reply to the sender */
5272 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5276 silc_server_command_free(cmd);
5279 /* Server side command of CLOSE. Closes connection to a specified server. */
5281 SILC_SERVER_CMD_FUNC(close)
5283 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5284 SilcServer server = cmd->server;
5285 SilcClientEntry client = silc_packet_get_context(cmd->sock);
5286 SilcServerEntry server_entry;
5287 SilcPacketStream sock;
5290 unsigned char *name;
5291 SilcUInt32 port = SILC_PORT;
5293 if (client->data.conn_type != SILC_CONN_CLIENT || !client)
5296 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
5298 /* Check whether client has the permissions. */
5299 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5300 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5301 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5302 SILC_STATUS_ERR_NO_SERVER_PRIV,
5307 /* Get the remote server */
5308 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5310 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5311 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5317 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5319 SILC_GET32_MSB(port, tmp);
5321 server_entry = silc_idlist_find_server_by_conn(server->local_list,
5322 name, port, TRUE, NULL);
5324 server_entry = silc_idlist_find_server_by_conn(server->global_list,
5325 name, port, TRUE, NULL);
5326 if (!server_entry) {
5327 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5328 SILC_STATUS_ERR_NO_SERVER_ID, 0);
5332 if (server_entry == server->id_entry) {
5333 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5334 SILC_STATUS_ERR_NO_SERVER_ID, 0);
5338 /* Send reply to the sender */
5339 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5342 /* Close the connection to the server */
5343 sock = server_entry->connection;
5345 if (server_entry->server_type == SILC_BACKUP_ROUTER) {
5346 server->backup_closed = TRUE;
5347 silc_server_backup_del(server, server_entry);
5350 server->backup_noswitch = TRUE;
5351 if (server->router == server_entry) {
5352 server->id_entry->router = NULL;
5353 server->router = NULL;
5354 server->standalone = TRUE;
5356 silc_server_disconnect_remote(server, sock,
5357 SILC_STATUS_ERR_BANNED_FROM_SERVER,
5358 "Closed by administrator");
5359 silc_server_free_sock_user_data(server, sock, NULL);
5360 server->backup_noswitch = FALSE;
5363 silc_server_command_free(cmd);
5366 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
5367 active connections. */
5369 SILC_SERVER_CMD_FUNC(shutdown)
5371 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5372 SilcServer server = cmd->server;
5373 SilcClientEntry client = silc_packet_get_context(cmd->sock);
5375 if (client->data.conn_type != SILC_CONN_CLIENT || !client)
5378 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
5380 /* Check whether client has the permission. */
5381 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5382 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5383 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5384 SILC_STATUS_ERR_NO_SERVER_PRIV,
5389 /* Send reply to the sender */
5390 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5393 /* Then, gracefully, or not, bring the server down. */
5394 silc_server_stop(server);
5398 silc_server_command_free(cmd);