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 silc_snprintf(info_string, sizeof(info_string),
1568 "location: %s server: %s admin: %s <%s> version: %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,
1575 server_info = info_string;
1576 entry = server->id_entry;
1578 /* Check whether we have this server cached */
1579 if (!entry && dest_server) {
1580 entry = silc_idlist_find_server_by_name(server->global_list,
1581 dest_server, TRUE, NULL);
1583 entry = silc_idlist_find_server_by_name(server->local_list,
1584 dest_server, TRUE, NULL);
1588 if (!cmd->pending &&
1589 server->server_type != SILC_SERVER && entry && !entry->server_info) {
1590 /* Send to the server */
1592 SilcUInt16 old_ident;
1595 cmd->server->stat.commands_sent++;
1597 old_ident = silc_command_get_ident(cmd->payload);
1598 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1599 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1601 silc_server_packet_send(server, entry->connection,
1602 SILC_PACKET_COMMAND, cmd->packet->flags,
1603 tmpbuf->data, silc_buffer_len(tmpbuf));
1605 /* Reprocess this packet after received reply from router */
1606 silc_server_command_pending(server, SILC_COMMAND_INFO,
1607 silc_command_get_ident(cmd->payload),
1608 silc_server_command_info,
1609 silc_server_command_dup(cmd));
1610 cmd->pending = TRUE;
1611 silc_command_set_ident(cmd->payload, old_ident);
1612 silc_buffer_free(tmpbuf);
1616 if (!entry && !cmd->pending && !server->standalone) {
1617 /* Send to the primary router */
1619 SilcUInt16 old_ident;
1622 cmd->server->stat.commands_sent++;
1624 old_ident = silc_command_get_ident(cmd->payload);
1625 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1626 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1628 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
1629 SILC_PACKET_COMMAND, cmd->packet->flags,
1630 tmpbuf->data, silc_buffer_len(tmpbuf));
1632 /* Reprocess this packet after received reply from router */
1633 silc_server_command_pending(server, SILC_COMMAND_INFO,
1634 silc_command_get_ident(cmd->payload),
1635 silc_server_command_info,
1636 silc_server_command_dup(cmd));
1637 cmd->pending = TRUE;
1638 silc_command_set_ident(cmd->payload, old_ident);
1639 silc_buffer_free(tmpbuf);
1646 silc_free(dest_server);
1647 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1648 silc_server_command_send_status_data(cmd, SILC_COMMAND_INFO,
1649 SILC_STATUS_ERR_NO_SUCH_SERVER, 0,
1651 strlen(dest_server));
1657 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1659 server_info = entry->server_info;
1660 server_name = entry->server_name;
1662 /* Send the reply */
1663 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_INFO,
1664 SILC_STATUS_OK, 0, ident, 3,
1665 2, idp->data, silc_buffer_len(idp),
1667 strlen(server_name),
1670 strlen(server_info) : 0);
1671 silc_buffer_free(idp);
1674 silc_free(dest_server);
1675 silc_server_command_free(cmd);
1678 /* Server side of command PING. This just replies to the ping. */
1680 SILC_SERVER_CMD_FUNC(ping)
1682 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1683 SilcServer server = cmd->server;
1688 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PING, cmd, 1, 1);
1691 if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
1692 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1693 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1698 if (SILC_ID_SERVER_COMPARE(SILC_ID_GET_ID(id), server->id)) {
1699 /* Send our reply */
1700 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1703 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1704 silc_server_command_send_status_data(cmd, SILC_COMMAND_PING,
1705 SILC_STATUS_ERR_NO_SUCH_SERVER_ID, 0,
1711 silc_server_command_free(cmd);
1714 /* Server side of command STATS. */
1716 SILC_SERVER_CMD_FUNC(stats)
1718 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1719 SilcServer server = cmd->server;
1723 SilcBuffer packet, stats;
1724 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1727 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1);
1730 if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
1731 silc_server_command_send_status_reply(cmd, SILC_COMMAND_STATS,
1732 SILC_STATUS_ERR_NO_SERVER_ID, 0);
1736 SILC_LOG_DEBUG(("id %s", silc_id_render(SILC_ID_GET_ID(id),
1739 /* The ID must be ours */
1740 if (!SILC_ID_SERVER_COMPARE(server->id, SILC_ID_GET_ID(id))) {
1741 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1742 silc_server_command_send_status_data(cmd, SILC_COMMAND_STATS,
1743 SILC_STATUS_ERR_NO_SUCH_SERVER_ID, 0,
1748 /* If we are router then just send everything we got. If we are normal
1749 server then we'll send this to our router to get all the latest
1750 statistical information. */
1751 if (!cmd->pending && server->server_type != SILC_ROUTER &&
1752 !server->standalone) {
1756 cmd->server->stat.commands_sent++;
1758 /* Send request to our router */
1759 idp = silc_id_payload_encode(server->router->id,
1761 packet = silc_command_payload_encode_va(SILC_COMMAND_STATS,
1762 ++server->cmd_ident, 1,
1764 silc_buffer_len(idp));
1765 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
1766 SILC_PACKET_COMMAND, 0, packet->data,
1767 silc_buffer_len(packet));
1769 /* Reprocess this packet after received reply from router */
1770 silc_server_command_pending(server, SILC_COMMAND_STATS,
1772 silc_server_command_stats,
1773 silc_server_command_dup(cmd));
1774 cmd->pending = TRUE;
1775 silc_buffer_free(packet);
1776 silc_buffer_free(idp);
1780 /* Send our reply to sender */
1781 uptime = time(NULL) - server->starttime;
1783 stats = silc_buffer_alloc_size(60);
1784 silc_buffer_format(stats,
1785 SILC_STR_UI_INT(server->starttime),
1786 SILC_STR_UI_INT(uptime),
1787 SILC_STR_UI_INT(server->stat.my_clients),
1788 SILC_STR_UI_INT(server->stat.my_channels),
1789 SILC_STR_UI_INT(server->stat.my_server_ops),
1790 SILC_STR_UI_INT(server->stat.my_router_ops),
1791 SILC_STR_UI_INT(server->stat.cell_clients),
1792 SILC_STR_UI_INT(server->stat.cell_channels),
1793 SILC_STR_UI_INT(server->stat.cell_servers),
1794 SILC_STR_UI_INT(server->stat.clients),
1795 SILC_STR_UI_INT(server->stat.channels),
1796 SILC_STR_UI_INT(server->stat.servers),
1797 SILC_STR_UI_INT(server->stat.routers),
1798 SILC_STR_UI_INT(server->stat.server_ops),
1799 SILC_STR_UI_INT(server->stat.router_ops),
1802 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1803 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_STATS,
1804 SILC_STATUS_OK, 0, ident, 2,
1806 3, stats->data, silc_buffer_len(stats));
1807 silc_buffer_free(stats);
1810 silc_server_command_free(cmd);
1813 /* Internal routine to join channel. The channel sent to this function
1814 has been either created or resolved from ID lists. This joins the sent
1815 client to the channel. */
1817 static void silc_server_command_join_channel(SilcServer server,
1818 SilcServerCommandContext cmd,
1819 SilcChannelEntry channel,
1820 SilcClientID *client_id,
1822 SilcBool create_key,
1824 const unsigned char *auth,
1825 SilcUInt32 auth_len,
1826 const unsigned char *cauth,
1827 SilcUInt32 cauth_len)
1829 SilcPacketStream sock = cmd->sock;
1830 SilcIDListData idata = silc_packet_get_context(sock);
1832 SilcUInt32 tmp_len, user_count;
1833 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4], ulimit[4];
1834 SilcClientEntry client;
1835 SilcChannelClientEntry chl;
1836 SilcBuffer reply, chidp, clidp, keyp = NULL;
1837 SilcBuffer user_list, mode_list, invite_list, ban_list;
1838 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1839 char check[512], check2[512];
1841 SilcBool founder = FALSE;
1843 SilcBuffer fkey = NULL, chpklist = NULL;
1844 const char *cipher, *hostname, *ip;
1846 SILC_LOG_DEBUG(("Joining client to channel"));
1851 silc_socket_stream_get_info(silc_packet_stream_get_stream(sock),
1852 NULL, &hostname, &ip, NULL);
1854 /* Get the client entry */
1855 if (idata->conn_type == SILC_CONN_CLIENT) {
1856 client = (SilcClientEntry)idata;
1860 client = silc_server_query_client(server, client_id, FALSE,
1863 if (!resolve || cmd->pending) {
1864 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1865 silc_server_command_send_status_data(
1866 cmd, SILC_COMMAND_JOIN,
1867 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0,
1872 /* The client info is being resolved. Reprocess this packet after
1873 receiving the reply to the query. */
1874 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1876 silc_server_command_join,
1877 silc_server_command_dup(cmd));
1878 cmd->pending = TRUE;
1882 if (!client->data.public_key &&
1883 (auth || cauth || channel->ban_list ||
1884 (channel->mode & SILC_CHANNEL_MODE_INVITE))) {
1885 if (cmd->pending == 2)
1888 /* We must retrieve the client's public key by sending
1889 GETKEY command. Reprocess this packet after receiving the key */
1890 clidp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
1891 silc_server_send_command(server, cmd->sock,
1892 SILC_COMMAND_GETKEY, ++server->cmd_ident,
1893 1, 1, clidp->data, silc_buffer_len(clidp));
1894 silc_buffer_free(clidp);
1895 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
1897 silc_server_command_join,
1898 silc_server_command_dup(cmd));
1903 cmd->pending = FALSE;
1907 * Check founder auth payload if provided. If client can gain founder
1908 * privileges it can override various conditions on joining the channel,
1909 * and can have directly the founder mode set on the channel.
1911 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1912 SilcIDListData idata = (SilcIDListData)client;
1913 SilcChannelClientEntry chl2;
1914 SilcHashTableList htl;
1916 if (channel->founder_key && idata->public_key &&
1917 silc_pkcs_public_key_compare(channel->founder_key,
1918 idata->public_key)) {
1919 /* Check whether the client is to become founder */
1920 if (silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
1921 channel->founder_key, 0, server->sha1hash,
1922 client->id, SILC_ID_CLIENT)) {
1924 /* There cannot be anyone else as founder on the channel now. This
1925 client is definitely the founder due to this authentication */
1926 silc_hash_table_list(channel->user_list, &htl);
1927 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
1928 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
1929 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
1930 silc_server_force_cumode_change(server, NULL, channel, chl2,
1934 silc_hash_table_list_reset(&htl);
1936 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
1943 * Check channel modes
1947 memset(check, 0, sizeof(check));
1948 memset(check2, 0, sizeof(check2));
1949 silc_strncat(check, sizeof(check),
1950 client->nickname, strlen(client->nickname));
1951 silc_strncat(check, sizeof(check), "!", 1);
1952 silc_strncat(check, sizeof(check),
1953 client->username, strlen(client->username));
1954 if (!strchr(client->username, '@')) {
1955 silc_strncat(check, sizeof(check), "@", 1);
1956 silc_strncat(check, sizeof(check),
1957 hostname, strlen(hostname));
1960 silc_strncat(check2, sizeof(check2),
1961 client->nickname, strlen(client->nickname));
1962 if (!strchr(client->nickname, '@')) {
1963 silc_strncat(check2, sizeof(check2), "@", 1);
1964 silc_strncat(check2, sizeof(check2),
1965 SILC_IS_LOCAL(client) ? server->server_name :
1966 client->router->server_name,
1967 SILC_IS_LOCAL(client) ? strlen(server->server_name) :
1968 strlen(client->router->server_name));
1970 silc_strncat(check2, sizeof(check2), "!", 1);
1971 silc_strncat(check2, sizeof(check2),
1972 client->username, strlen(client->username));
1973 if (!strchr(client->username, '@')) {
1974 silc_strncat(check2, sizeof(check2), "@", 1);
1975 silc_strncat(check2, sizeof(check2),
1976 hostname, strlen(hostname));
1979 /* Check invite list if channel is invite-only channel */
1980 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1981 if (!channel->invite_list ||
1982 !silc_hash_table_count(channel->invite_list) ||
1983 (!silc_server_inviteban_match(server, channel->invite_list,
1985 !silc_server_inviteban_match(server, channel->invite_list,
1986 2, client->data.public_key) &&
1987 !silc_server_inviteban_match(server, channel->invite_list,
1988 1, client->nickname) &&
1989 !silc_server_inviteban_match(server, channel->invite_list,
1991 !silc_server_inviteban_match(server, channel->invite_list,
1993 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1994 silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
1995 SILC_STATUS_ERR_NOT_INVITED, 0,
1997 silc_buffer_len(chidp));
1998 silc_buffer_free(chidp);
2003 /* Check ban list if it exists. If the client's nickname, server,
2004 username and/or hostname is in the ban list the access to the
2005 channel is denied. */
2006 if (channel->ban_list && silc_hash_table_count(channel->ban_list)) {
2007 if (silc_server_inviteban_match(server, channel->ban_list,
2009 silc_server_inviteban_match(server, channel->ban_list,
2010 2, client->data.public_key) ||
2011 silc_server_inviteban_match(server, channel->ban_list,
2012 1, client->nickname) ||
2013 silc_server_inviteban_match(server, channel->ban_list,
2015 silc_server_inviteban_match(server, channel->ban_list,
2017 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2018 silc_server_command_send_status_data(
2019 cmd, SILC_COMMAND_JOIN,
2020 SILC_STATUS_ERR_BANNED_FROM_CHANNEL, 0,
2022 silc_buffer_len(chidp));
2023 silc_buffer_free(chidp);
2028 /* Check user count limit if set. */
2029 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
2030 if (silc_hash_table_count(channel->user_list) + 1 >
2031 channel->user_limit) {
2032 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2033 silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
2034 SILC_STATUS_ERR_CHANNEL_IS_FULL,
2036 silc_buffer_len(chidp));
2037 silc_buffer_free(chidp);
2043 /* Check the channel passphrase if set. */
2044 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2045 /* Get passphrase */
2046 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2048 passphrase = silc_memdup(tmp, tmp_len);
2050 if (!passphrase || !channel->passphrase ||
2051 strlen(channel->passphrase) != strlen(passphrase) ||
2052 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
2053 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2054 silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
2055 SILC_STATUS_ERR_BAD_PASSWORD, 0,
2057 silc_buffer_len(chidp));
2058 silc_buffer_free(chidp);
2063 /* Verify channel authentication with channel public keys if set. */
2064 if (channel->mode & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
2065 if (!silc_server_verify_channel_auth(server, channel, client->id,
2066 cauth, cauth_len)) {
2067 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2068 SILC_STATUS_ERR_PERM_DENIED, 0);
2074 * Client is allowed to join to the channel. Make it happen.
2077 /* Check whether the client already is on the channel */
2078 if (silc_server_client_on_channel(client, channel, NULL)) {
2079 clidp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
2080 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2081 silc_server_command_send_status_data2(cmd, SILC_COMMAND_JOIN,
2082 SILC_STATUS_ERR_USER_ON_CHANNEL, 0,
2084 silc_buffer_len(clidp),
2086 silc_buffer_len(chidp));
2087 silc_buffer_free(clidp);
2088 silc_buffer_free(chidp);
2092 /* Generate new channel key as protocol dictates */
2094 if (!silc_server_create_channel_key(server, channel, 0))
2097 /* Send the channel key. This is broadcasted to the channel but is not
2098 sent to the client who is joining to the channel. */
2099 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
2100 silc_server_send_channel_key(server, NULL, channel,
2101 server->server_type == SILC_ROUTER ?
2102 FALSE : !server->standalone);
2105 /* Join the client to the channel by adding it to channel's user list.
2106 Add also the channel to client entry's channels list for fast cross-
2108 chl = silc_calloc(1, sizeof(*chl));
2110 chl->client = client;
2111 chl->channel = channel;
2112 silc_hash_table_add(channel->user_list, client, chl);
2113 silc_hash_table_add(client->channels, channel, chl);
2114 channel->user_count++;
2115 channel->disabled = FALSE;
2117 /* Get users on the channel */
2118 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
2121 /* Encode Client ID Payload of the original client who wants to join */
2122 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2124 /* Encode command reply packet */
2125 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2126 SILC_PUT32_MSB(channel->mode, mode);
2127 SILC_PUT32_MSB(created, tmp2);
2128 SILC_PUT32_MSB(user_count, tmp3);
2129 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2130 SILC_PUT32_MSB(channel->user_limit, ulimit);
2132 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
2133 unsigned char cid[32];
2135 silc_id_id2str(channel->id, SILC_ID_CHANNEL, cid, sizeof(cid), &cid_len);
2136 cipher = silc_cipher_get_name(channel->send_key);
2137 keyp = silc_channel_key_payload_encode(cid_len, cid,
2138 strlen(cipher), cipher,
2139 channel->key_len / 8, channel->key);
2142 if (channel->founder_key)
2143 fkey = silc_public_key_payload_encode(channel->founder_key);
2145 /* Encode invite list */
2147 if (channel->invite_list && silc_hash_table_count(channel->invite_list)) {
2148 SilcHashTableList htl;
2150 invite_list = silc_buffer_alloc_size(2);
2151 silc_buffer_format(invite_list,
2152 SILC_STR_UI_SHORT(silc_hash_table_count(
2153 channel->invite_list)),
2156 silc_hash_table_list(channel->invite_list, &htl);
2157 while (silc_hash_table_get(&htl, (void *)&plen, (void *)&reply))
2158 invite_list = silc_argument_payload_encode_one(invite_list,
2160 silc_buffer_len(reply),
2161 SILC_PTR_TO_32(plen));
2162 silc_hash_table_list_reset(&htl);
2165 /* Encode ban list */
2167 if (channel->ban_list && silc_hash_table_count(channel->ban_list)) {
2168 SilcHashTableList htl;
2170 ban_list = silc_buffer_alloc_size(2);
2171 silc_buffer_format(ban_list,
2172 SILC_STR_UI_SHORT(silc_hash_table_count(
2173 channel->ban_list)),
2176 silc_hash_table_list(channel->ban_list, &htl);
2177 while (silc_hash_table_get(&htl, (void *)&plen, (void *)&reply))
2178 ban_list = silc_argument_payload_encode_one(ban_list,
2180 silc_buffer_len(reply),
2181 SILC_PTR_TO_32(plen));
2182 silc_hash_table_list_reset(&htl);
2185 if (channel->channel_pubkeys)
2186 chpklist = silc_server_get_channel_pk_list(server, channel, FALSE, FALSE);
2189 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2190 SILC_STATUS_OK, 0, ident, 16,
2191 2, channel->channel_name,
2192 strlen(channel->channel_name),
2194 silc_buffer_len(chidp),
2196 silc_buffer_len(clidp),
2199 7, keyp ? keyp->data : NULL,
2200 keyp ? silc_buffer_len(keyp) : 0,
2201 8, ban_list ? ban_list->data : NULL,
2203 silc_buffer_len(ban_list): 0,
2204 9, invite_list ? invite_list->data :
2207 silc_buffer_len(invite_list) : 0,
2210 strlen(channel->topic) : 0,
2211 11, silc_hmac_get_name(channel->hmac),
2212 strlen(silc_hmac_get_name(channel->
2215 13, user_list->data,
2216 silc_buffer_len(user_list),
2217 14, mode_list->data,
2218 silc_buffer_len(mode_list),
2219 15, fkey ? fkey->data : NULL,
2220 fkey ? silc_buffer_len(fkey) : 0,
2221 16, chpklist ? chpklist->data : NULL,
2222 chpklist ? silc_buffer_len(chpklist) : 0,
2223 17, (channel->mode &
2224 SILC_CHANNEL_MODE_ULIMIT ?
2227 SILC_CHANNEL_MODE_ULIMIT ?
2228 sizeof(ulimit) : 0));
2230 /* Send command reply */
2231 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
2232 reply->data, silc_buffer_len(reply));
2235 cmd->server->stat.commands_sent++;
2237 /* Send JOIN notify to locally connected clients on the channel. If
2238 we are normal server then router will send or have sent JOIN notify
2239 already. However since we've added the client already to our channel
2240 we'll ignore it (in packet_receive.c) so we must send it here. If
2241 we are router then this will send it to local clients and local
2243 SILC_LOG_DEBUG(("Send JOIN notify to channel"));
2244 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
2245 SILC_NOTIFY_TYPE_JOIN, 2,
2246 clidp->data, silc_buffer_len(clidp),
2247 chidp->data, silc_buffer_len(chidp));
2249 /* Update statistics */
2250 server->stat.my_chanclients++;
2251 if (server->server_type == SILC_ROUTER) {
2252 server->stat.cell_chanclients++;
2253 server->stat.chanclients++;
2256 if (!cmd->pending) {
2257 /* Send JOIN notify packet to our primary router */
2258 silc_server_send_notify_join(server, SILC_PRIMARY_ROUTE(server),
2259 SILC_BROADCAST(server), channel, client->id);
2262 /* Distribute the channel key to all backup routers. */
2263 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
2264 keyp->data, silc_buffer_len(keyp), FALSE, TRUE);
2266 /* If client became founder by providing correct founder auth data
2267 notify the mode change to the channel. */
2269 SILC_PUT32_MSB(chl->mode, mode);
2270 SILC_LOG_DEBUG(("Send CUMODE_CHANGE notify to channel"));
2271 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
2272 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
2274 silc_buffer_len(clidp),
2275 mode, 4, clidp->data,
2276 silc_buffer_len(clidp),
2277 fkey ? fkey->data : NULL,
2278 fkey ? silc_buffer_len(fkey) : 0);
2282 /* Set CUMODE notify type to network */
2284 silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
2285 SILC_BROADCAST(server), channel,
2286 chl->mode, client->id, SILC_ID_CLIENT,
2287 client->id, channel->founder_key);
2289 silc_buffer_free(reply);
2290 silc_buffer_free(clidp);
2291 silc_buffer_free(chidp);
2292 silc_buffer_free(keyp);
2293 silc_buffer_free(user_list);
2294 silc_buffer_free(mode_list);
2295 silc_buffer_free(fkey);
2296 silc_buffer_free(chpklist);
2297 silc_buffer_free(invite_list);
2298 silc_buffer_free(ban_list);
2302 memset(passphrase, 0, strlen(passphrase));
2303 silc_free(passphrase);
2306 /* Server side of command JOIN. Joins client into requested channel. If
2307 the channel does not exist it will be created. */
2309 void silc_server_command_join_connected(SilcServer server,
2310 SilcServerEntry server_entry,
2313 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2315 if (!server_entry) {
2317 unsigned char *tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2320 SILC_LOG_DEBUG(("Connecting to router failed"));
2321 silc_parse_userfqdn(tmp, NULL, 0, serv, sizeof(serv));
2324 silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
2325 SILC_STATUS_ERR_NO_SUCH_SERVER, 0,
2326 2, serv, strlen(serv));
2328 silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
2329 SILC_STATUS_ERR_NO_SUCH_CHANNEL, 0,
2332 silc_server_command_free(cmd);
2336 /* Reprocess command */
2337 SILC_LOG_DEBUG(("Reprocess JOIN after connecting to router"));
2338 silc_server_command_join(cmd, NULL);
2341 SILC_SERVER_CMD_FUNC(join)
2343 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2344 SilcServer server = cmd->server;
2345 SilcIDListData idata = silc_packet_get_context(cmd->sock);
2346 unsigned char *auth, *cauth;
2347 SilcUInt32 tmp_len, auth_len, cauth_len;
2348 char *tmp, *channel_name, *channel_namec = NULL, *cipher, *hmac;
2349 char parsed[256 + 1], serv[256 + 1];
2350 SilcChannelEntry channel;
2351 SilcUInt32 umode = 0;
2352 SilcBool created = FALSE, create_key = TRUE;
2355 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 7);
2357 /* Get channel name */
2358 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2360 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2361 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2366 /* Truncate over long channel names */
2367 if (tmp_len > 256) {
2369 tmp[tmp_len - 1] = '\0';
2372 /* Parse server name from the channel name */
2373 silc_parse_userfqdn(tmp, parsed, sizeof(parsed), serv,
2375 channel_name = parsed;
2377 if (server->config->dynamic_server) {
2378 /* If server name is not specified but local channels is FALSE then the
2379 channel will be global, based on our router name. */
2380 if (!serv[0] && !server->config->local_channels) {
2381 if (!server->standalone) {
2382 silc_snprintf(serv, sizeof(serv), server->router->server_name);
2384 SilcServerConfigRouter *router;
2385 router = silc_server_config_get_primary_router(server);
2387 /* Create connection to primary router */
2388 SILC_LOG_DEBUG(("Create dynamic connection to primary router %s:%d",
2389 router->host, router->port));
2390 silc_server_create_connection(server, FALSE, TRUE,
2391 router->host, router->port,
2392 silc_server_command_join_connected,
2399 /* If server name is ours, ignore it. */
2400 if (serv[0] && silc_utf8_strcasecmp(serv, server->server_name))
2401 memset(serv, 0, sizeof(serv));
2403 /* Create connection */
2404 if (serv[0] && server->standalone) {
2405 SilcServerConfigRouter *router;
2406 router = silc_server_config_get_primary_router(server);
2408 /* Create connection to primary router */
2409 SILC_LOG_DEBUG(("Create dynamic connection to primary router %s:%d",
2410 router->host, router->port));
2411 silc_server_create_connection(server, FALSE, TRUE,
2412 router->host, router->port,
2413 silc_server_command_join_connected, cmd);
2419 /* Check for valid channel name. This is cached, the original is saved
2420 in the channel context. */
2421 channel_namec = silc_channel_name_check(channel_name, strlen(channel_name),
2422 SILC_STRING_UTF8, 256, NULL);
2423 if (!channel_namec) {
2424 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2425 SILC_STATUS_ERR_BAD_CHANNEL, 0);
2429 /* Get Client ID of the client who is joining to the channel */
2430 if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL)) {
2431 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2432 SILC_STATUS_ERR_NO_CLIENT_ID,
2436 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2438 /* Get cipher, hmac name and auth payload */
2439 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2440 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2441 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
2442 cauth = silc_argument_get_arg_type(cmd->args, 7, &cauth_len);
2444 /* See if the channel exists */
2445 channel = silc_idlist_find_channel_by_name(server->local_list,
2446 channel_namec, NULL);
2448 if (idata->conn_type == SILC_CONN_CLIENT) {
2449 SilcClientEntry entry = (SilcClientEntry)idata;
2451 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2452 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2457 #ifndef SILC_DIST_INPLACE
2458 /* Limit how many channels client can join */
2459 if (!cmd->pending && entry->channels &&
2460 silc_hash_table_count(entry->channels) >=
2461 server->config->param.chlimit) {
2462 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2463 SILC_STATUS_ERR_RESOURCE_LIMIT,
2467 #endif /* SILC_DIST_INPLACE */
2470 (channel->disabled && server->server_type != SILC_ROUTER)) {
2471 /* Channel not found or not valid */
2473 /* If we are standalone server we don't have a router, we just create
2474 the channel by ourselves (unless it existed). */
2475 if (server->standalone) {
2477 channel = silc_server_create_new_channel(server, server->id, cipher,
2478 hmac, channel_name, TRUE);
2481 silc_server_command_send_status_data(
2482 cmd, SILC_COMMAND_JOIN,
2483 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
2484 0, 2, cipher, strlen(cipher));
2486 silc_server_command_send_status_data(
2487 cmd, SILC_COMMAND_JOIN,
2488 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
2489 0, 2, hmac, strlen(hmac));
2491 silc_server_command_send_status_reply(
2492 cmd, SILC_COMMAND_JOIN,
2493 SILC_STATUS_ERR_RESOURCE_LIMIT,
2499 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2505 /* The channel does not exist on our server. If we are normal server
2506 we will send JOIN command to our router which will handle the
2507 joining procedure (either creates the channel if it doesn't exist
2508 or joins the client to it). */
2509 if (server->server_type != SILC_ROUTER) {
2511 SilcUInt16 old_ident;
2513 /* If this is pending command callback then we've resolved
2514 it and it didn't work, return since we've notified the
2515 client already in the command reply callback. */
2520 cmd->server->stat.commands_sent++;
2522 old_ident = silc_command_get_ident(cmd->payload);
2523 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2524 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2526 /* Send JOIN command to our router */
2527 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
2528 SILC_PACKET_COMMAND, cmd->packet->flags,
2529 tmpbuf->data, silc_buffer_len(tmpbuf));
2531 /* Reprocess this packet after received reply from router */
2532 silc_server_command_pending(server, SILC_COMMAND_JOIN,
2533 silc_command_get_ident(cmd->payload),
2534 silc_server_command_join,
2535 silc_server_command_dup(cmd));
2536 cmd->pending = TRUE;
2537 silc_command_set_ident(cmd->payload, old_ident);
2538 silc_buffer_free(tmpbuf);
2542 /* We are router and the channel does not seem exist so we will check
2543 our global list as well for the channel. */
2544 channel = silc_idlist_find_channel_by_name(server->global_list,
2545 channel_namec, NULL);
2547 /* Channel really does not exist, create it */
2548 channel = silc_server_create_new_channel(server, server->id, cipher,
2549 hmac, channel_name, TRUE);
2552 silc_server_command_send_status_data(
2553 cmd, SILC_COMMAND_JOIN,
2554 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
2555 0, 2, cipher, strlen(cipher));
2557 silc_server_command_send_status_data(
2558 cmd, SILC_COMMAND_JOIN,
2559 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
2560 0, 2, hmac, strlen(hmac));
2562 silc_server_command_send_status_reply(
2563 cmd, SILC_COMMAND_JOIN,
2564 SILC_STATUS_ERR_RESOURCE_LIMIT,
2570 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2578 /* Channel not found */
2580 /* If the command came from router and we are normal server then
2581 something went wrong with the joining as the channel was not found.
2582 We can't do anything else but ignore this. */
2583 if (idata->conn_type == SILC_CONN_ROUTER ||
2584 server->server_type != SILC_ROUTER)
2587 /* We are router and the channel does not seem exist so we will check
2588 our global list as well for the channel. */
2589 channel = silc_idlist_find_channel_by_name(server->global_list,
2590 channel_namec, NULL);
2592 /* Channel really does not exist, create it */
2593 channel = silc_server_create_new_channel(server, server->id, cipher,
2594 hmac, channel_name, TRUE);
2597 silc_server_command_send_status_data(
2598 cmd, SILC_COMMAND_JOIN,
2599 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
2600 0, 2, cipher, strlen(cipher));
2602 silc_server_command_send_status_data(
2603 cmd, SILC_COMMAND_JOIN,
2604 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
2605 0, 2, hmac, strlen(hmac));
2607 silc_server_command_send_status_reply(
2608 cmd, SILC_COMMAND_JOIN,
2609 SILC_STATUS_ERR_RESOURCE_LIMIT,
2615 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2622 /* Check whether the channel was created by our router */
2623 if (cmd->pending && context2) {
2624 SilcServerCommandReplyContext reply = context2;
2626 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
2627 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
2628 SILC_GET32_MSB(created, tmp);
2629 if (silc_argument_get_arg_type(reply->args, 7, NULL))
2630 create_key = FALSE; /* Router returned the key already */
2632 if (silc_command_get_status(reply->payload, NULL, NULL) &&
2633 channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2634 /* Save channel passphrase, if user provided it successfully */
2637 pa = silc_argument_get_arg_type(cmd->args, 3, &pa_len);
2639 silc_free(channel->passphrase);
2640 channel->passphrase = silc_memdup(pa, pa_len);
2645 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
2646 !channel->disabled && !silc_hash_table_count(channel->user_list))
2650 /* If the channel does not have global users and is also empty the client
2651 will be the channel founder and operator. */
2652 if (!channel->disabled &&
2653 !channel->global_users && !silc_hash_table_count(channel->user_list))
2654 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2656 /* Join to the channel */
2657 silc_server_command_join_channel(server, cmd, channel, SILC_ID_GET_ID(id),
2658 created, create_key, umode,
2659 auth, auth_len, cauth, cauth_len);
2662 silc_free(channel_namec);
2663 silc_server_command_free(cmd);
2666 /* Server side of command MOTD. Sends server's current "message of the
2667 day" to the client. */
2669 SILC_SERVER_CMD_FUNC(motd)
2671 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2672 SilcServer server = cmd->server;
2674 char *motd, *dest_server = NULL;
2675 SilcUInt32 motd_len;
2676 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2678 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
2680 /* Get server name */
2681 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2683 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2684 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2689 /* Check server name */
2690 dest_server = silc_identifier_check(dest_server, strlen(dest_server),
2691 SILC_STRING_UTF8, 256, NULL);
2693 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2694 SILC_STATUS_ERR_BAD_SERVER,
2699 if (!memcmp(dest_server, server->server_name, strlen(dest_server))) {
2702 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
2704 if (server->config && server->config->server_info &&
2705 server->config->server_info->motd_file) {
2707 motd = silc_file_readfile(server->config->server_info->motd_file,
2711 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_MOTD,
2712 SILC_STATUS_OK, 0, ident, 1,
2713 2, idp->data, silc_buffer_len(idp));
2718 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_MOTD,
2719 SILC_STATUS_OK, 0, ident, 2,
2720 2, idp->data, silc_buffer_len(idp),
2724 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_MOTD,
2725 SILC_STATUS_OK, 0, ident, 1,
2726 2, idp->data, silc_buffer_len(idp));
2728 silc_buffer_free(idp);
2730 SilcServerEntry entry;
2732 /* Check whether we have this server cached */
2733 entry = silc_idlist_find_server_by_name(server->global_list,
2734 dest_server, TRUE, NULL);
2736 entry = silc_idlist_find_server_by_name(server->local_list,
2737 dest_server, TRUE, NULL);
2740 if (server->server_type != SILC_SERVER && !cmd->pending &&
2741 entry && !entry->motd) {
2742 /* Send to the server */
2744 SilcUInt16 old_ident;
2747 cmd->server->stat.commands_sent++;
2749 old_ident = silc_command_get_ident(cmd->payload);
2750 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2751 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2753 silc_server_packet_send(server, entry->connection,
2754 SILC_PACKET_COMMAND, cmd->packet->flags,
2755 tmpbuf->data, silc_buffer_len(tmpbuf));
2757 /* Reprocess this packet after received reply from router */
2758 silc_server_command_pending(server, SILC_COMMAND_MOTD,
2759 silc_command_get_ident(cmd->payload),
2760 silc_server_command_motd,
2761 silc_server_command_dup(cmd));
2762 cmd->pending = TRUE;
2763 silc_command_set_ident(cmd->payload, old_ident);
2764 silc_buffer_free(tmpbuf);
2768 /* Send to primary router only if we don't know the server
2769 * the client requested or if the server is not locally connected */
2770 if ((!entry || !(entry->data.status & SILC_IDLIST_STATUS_LOCAL))
2771 && !cmd->pending && !server->standalone) {
2772 /* Send to the primary router */
2774 SilcUInt16 old_ident;
2777 cmd->server->stat.commands_sent++;
2779 old_ident = silc_command_get_ident(cmd->payload);
2780 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2781 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2783 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
2784 SILC_PACKET_COMMAND, cmd->packet->flags,
2785 tmpbuf->data, silc_buffer_len(tmpbuf));
2787 /* Reprocess this packet after received reply from router */
2788 silc_server_command_pending(server, SILC_COMMAND_MOTD,
2789 silc_command_get_ident(cmd->payload),
2790 silc_server_command_motd,
2791 silc_server_command_dup(cmd));
2792 cmd->pending = TRUE;
2793 silc_command_set_ident(cmd->payload, old_ident);
2794 silc_buffer_free(tmpbuf);
2799 silc_free(dest_server);
2800 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2801 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2802 SILC_STATUS_ERR_NO_SUCH_SERVER, 0,
2804 strlen(dest_server));
2809 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2810 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_MOTD,
2811 SILC_STATUS_OK, 0, ident, 2,
2812 2, idp->data, silc_buffer_len(idp),
2815 strlen(entry->motd) : 0);
2816 silc_buffer_free(idp);
2820 silc_free(dest_server);
2821 silc_server_command_free(cmd);
2824 /* Server side of command UMODE. Client can use this command to set/unset
2825 user mode. Client actually cannot set itself to be as server/router
2826 operator so this can be used only to unset the modes. */
2828 SILC_SERVER_CMD_FUNC(umode)
2830 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2831 SilcServer server = cmd->server;
2832 SilcClientEntry client = silc_packet_get_context(cmd->sock);
2833 unsigned char *tmp_mask, m[4];
2834 SilcUInt32 mask = 0, tmp_len;
2835 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2836 SilcBool set_mask = FALSE;
2838 if (client->data.conn_type != SILC_CONN_CLIENT || !client)
2841 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2);
2843 /* Get the client's mode mask */
2844 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2845 if (tmp_mask && tmp_len == 4) {
2846 SILC_GET32_MSB(mask, tmp_mask);
2851 /* Check that mode changing is allowed. */
2852 if (!silc_server_check_umode_rights(server, client, mask)) {
2853 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2854 SILC_STATUS_ERR_PERM_DENIED, 0);
2858 /* Anonymous mode cannot be set by client */
2859 if (mask & SILC_UMODE_ANONYMOUS &&
2860 !(client->mode & SILC_UMODE_ANONYMOUS)) {
2861 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2862 SILC_STATUS_ERR_PERM_DENIED, 0);
2866 /* Update statistics */
2867 if (mask & SILC_UMODE_GONE) {
2868 if (!(client->mode & SILC_UMODE_GONE))
2869 server->stat.my_aways++;
2871 if (client->mode & SILC_UMODE_GONE)
2872 server->stat.my_aways--;
2875 /* If the client has anonymous mode set, preserve it. */
2876 if (client->mode & SILC_UMODE_ANONYMOUS)
2877 mask |= SILC_UMODE_ANONYMOUS;
2879 /* Change the mode */
2880 client->mode = mask;
2882 /* Send UMODE change to primary router */
2883 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
2884 SILC_BROADCAST(server), client->id,
2887 /* Check if anyone is watching this nickname */
2888 if (server->server_type == SILC_ROUTER)
2889 silc_server_check_watcher_list(server, client, NULL,
2890 SILC_NOTIFY_TYPE_UMODE_CHANGE);
2893 /* Send command reply to sender */
2894 SILC_PUT32_MSB(client->mode, m);
2895 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_UMODE,
2896 SILC_STATUS_OK, 0, ident, 1,
2900 silc_server_command_free(cmd);
2903 /* Server side command of CMODE. Changes channel mode */
2905 SILC_SERVER_CMD_FUNC(cmode)
2907 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2908 SilcServer server = cmd->server;
2909 SilcClientEntry client = silc_packet_get_context(cmd->sock);
2910 SilcIDListData idata = (SilcIDListData)client;
2912 SilcChannelEntry channel;
2913 SilcChannelClientEntry chl;
2915 unsigned char *tmp, *tmp_id, *tmp_mask, *chpkdata = NULL;
2916 char *cipher = NULL, *hmac = NULL, *passphrase = NULL, ulimit[4];
2917 SilcUInt32 mode_mask = 0, old_mask = 0, tmp_len, tmp_len2, chpklen;
2918 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2919 SilcBool set_mask = FALSE, set_chpk = FALSE;
2920 SilcPublicKey founder_key = NULL;
2921 SilcBuffer fkey = NULL, chpklist = NULL;
2922 SilcBufferStruct chpk;
2925 silc_server_command_free(cmd);
2929 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 9);
2931 /* Get Channel ID */
2932 if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
2933 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2934 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2935 silc_server_command_free(cmd);
2939 /* Get channel entry */
2940 channel = silc_idlist_find_channel_by_id(server->local_list,
2941 SILC_ID_GET_ID(id), NULL);
2943 channel = silc_idlist_find_channel_by_id(server->global_list,
2944 SILC_ID_GET_ID(id), NULL);
2946 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2947 silc_server_command_send_status_data(cmd, SILC_COMMAND_CMODE,
2948 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
2949 0, 2, tmp_id, tmp_len2);
2950 silc_server_command_free(cmd);
2954 old_mask = channel->mode;
2956 /* Get the channel mode mask */
2957 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2958 if (tmp_mask && tmp_len == 4) {
2959 SILC_GET32_MSB(mode_mask, tmp_mask);
2963 /* Check whether this client is on the channel */
2964 if (!silc_server_client_on_channel(client, channel, &chl)) {
2965 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2966 silc_server_command_send_status_data(cmd, SILC_COMMAND_CMODE,
2967 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
2968 2, tmp_id, tmp_len2);
2972 /* Check that client has rights to change any requested channel modes */
2973 if (set_mask && !silc_server_check_cmode_rights(server, channel, chl,
2975 SILC_LOG_DEBUG(("Client does not have rights to change mode"));
2976 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2977 silc_server_command_send_status_data(
2978 cmd, SILC_COMMAND_CMODE,
2979 (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) ?
2980 SILC_STATUS_ERR_NO_CHANNEL_PRIV :
2981 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV), 0,
2982 2, tmp_id, tmp_len2);
2986 /* If mode mask was not sent as argument then merely return the current
2987 mode mask, founder key and channel public key list to the sender. */
2990 SILC_PUT32_MSB(channel->mode, m);
2991 if (channel->founder_key)
2992 fkey = silc_public_key_payload_encode(channel->founder_key);
2993 if (channel->channel_pubkeys)
2994 chpklist = silc_server_get_channel_pk_list(server, channel,
2996 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2997 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_CMODE,
2998 SILC_STATUS_OK, 0, ident, 4,
2999 2, tmp_id, tmp_len2,
3001 4, fkey ? fkey->data : NULL,
3002 fkey ? silc_buffer_len(fkey) : 0,
3003 5, chpklist ? chpklist->data : NULL,
3004 chpklist ? silc_buffer_len(chpklist) : 0);
3009 * Check the modes. Modes that requires nothing special operation are
3013 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3014 /* Channel uses private keys to protect traffic. Client(s) has set the
3015 key locally they want to use, server does not know that key. */
3016 /* Nothing interesting to do here */
3018 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3019 /* The mode is removed and we need to generate and distribute
3020 new channel key. Clients are not using private channel keys
3021 anymore after this. */
3023 /* if we don't remove the flag from the mode
3024 * silc_server_create_channel_key won't create a new key */
3025 channel->mode &= ~SILC_CHANNEL_MODE_PRIVKEY;
3027 /* Re-generate channel key */
3028 if (!silc_server_create_channel_key(server, channel, 0))
3031 /* Send the channel key. This sends it to our local clients and if
3032 we are normal server to our router as well. */
3033 silc_server_send_channel_key(server, NULL, channel,
3034 server->server_type == SILC_ROUTER ?
3035 FALSE : !server->standalone);
3037 cipher = (char *)silc_cipher_get_name(channel->send_key);
3038 hmac = (char *)silc_hmac_get_name(channel->hmac);
3042 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3043 /* User limit is set on channel */
3044 SilcUInt32 user_limit;
3046 /* Get user limit */
3047 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3049 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3050 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3051 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3055 SILC_GET32_MSB(user_limit, tmp);
3056 channel->user_limit = user_limit;
3059 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3060 /* User limit mode is unset. Remove user limit */
3061 channel->user_limit = 0;
3064 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3065 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3066 /* Passphrase has been set to channel */
3068 /* Get the passphrase */
3069 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3071 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3072 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3076 /* Save the passphrase */
3077 passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
3080 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3081 /* Passphrase mode is unset. remove the passphrase */
3082 silc_free(channel->passphrase);
3083 channel->passphrase = NULL;
3087 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3088 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3089 /* Cipher to use protect the traffic */
3090 SilcCipher send_key, receive_key, olds, oldr;
3093 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3095 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3096 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3100 /* Delete old cipher and allocate the new one */
3101 if (!silc_cipher_alloc(cipher, &send_key)) {
3102 silc_server_command_send_status_data(
3103 cmd, SILC_COMMAND_CMODE,
3104 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
3105 2, cipher, strlen(cipher));
3108 if (!silc_cipher_alloc(cipher, &receive_key)) {
3109 silc_server_command_send_status_data(
3110 cmd, SILC_COMMAND_CMODE,
3111 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
3112 2, cipher, strlen(cipher));
3116 olds = channel->send_key;
3117 oldr = channel->receive_key;
3118 channel->send_key = send_key;
3119 channel->receive_key = receive_key;
3121 /* Re-generate channel key */
3122 if (!silc_server_create_channel_key(server, channel, 0)) {
3123 /* We don't have new key, revert to old one */
3124 channel->send_key = olds;
3125 channel->receive_key = oldr;
3129 /* Remove old channel key for good */
3130 silc_cipher_free(olds);
3131 silc_cipher_free(oldr);
3133 /* Send the channel key. This sends it to our local clients and if
3134 we are normal server to our router as well. */
3135 silc_server_send_channel_key(server, NULL, channel,
3136 server->server_type == SILC_ROUTER ?
3137 FALSE : !server->standalone);
3140 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3141 /* Cipher mode is unset. Remove the cipher and revert back to
3143 SilcCipher send_key, receive_key, olds, oldr;
3144 cipher = channel->cipher;
3146 /* Delete old cipher and allocate default one */
3147 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER,
3149 silc_server_command_send_status_data(
3150 cmd, SILC_COMMAND_CMODE,
3151 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
3152 2, cipher, strlen(cipher));
3155 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER,
3157 silc_server_command_send_status_data(
3158 cmd, SILC_COMMAND_CMODE,
3159 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
3160 2, cipher, strlen(cipher));
3164 olds = channel->send_key;
3165 oldr = channel->receive_key;
3166 channel->send_key = send_key;
3167 channel->receive_key = receive_key;
3169 /* Re-generate channel key */
3170 if (!silc_server_create_channel_key(server, channel, 0)) {
3171 /* We don't have new key, revert to old one */
3172 channel->send_key = olds;
3173 channel->receive_key = oldr;
3177 /* Remove old channel key for good */
3178 silc_cipher_free(olds);
3179 silc_cipher_free(oldr);
3181 /* Send the channel key. This sends it to our local clients and if
3182 we are normal server to our router as well. */
3183 silc_server_send_channel_key(server, NULL, channel,
3184 server->server_type == SILC_ROUTER ?
3185 FALSE : !server->standalone);
3189 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3190 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3191 /* HMAC to use protect the traffic */
3192 unsigned char hash[SILC_HASH_MAXLEN];
3196 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3198 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3199 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3203 /* Delete old hmac and allocate the new one */
3204 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
3205 silc_server_command_send_status_data(
3206 cmd, SILC_COMMAND_CMODE,
3207 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
3208 2, hmac, strlen(hmac));
3212 silc_hmac_free(channel->hmac);
3213 channel->hmac = newhmac;
3215 /* Set the HMAC key out of current channel key. The client must do
3217 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
3218 channel->key_len / 8, hash);
3219 silc_hmac_set_key(channel->hmac, hash,
3220 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3221 memset(hash, 0, sizeof(hash));
3224 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
3225 /* Hmac mode is unset. Remove the hmac and revert back to
3228 unsigned char hash[SILC_HASH_MAXLEN];
3229 hmac = channel->hmac_name;
3231 /* Delete old hmac and allocate default one */
3232 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
3233 silc_server_command_send_status_data(
3234 cmd, SILC_COMMAND_CMODE,
3235 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
3236 2, hmac, strlen(hmac));
3240 silc_hmac_free(channel->hmac);
3241 channel->hmac = newhmac;
3243 /* Set the HMAC key out of current channel key. The client must do
3245 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
3246 channel->key_len / 8,
3248 silc_hmac_set_key(channel->hmac, hash,
3249 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3250 memset(hash, 0, sizeof(hash));
3254 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3255 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3256 /* Check if the founder public key was received */
3257 founder_key = idata->public_key;
3258 tmp = silc_argument_get_arg_type(cmd->args, 8, &tmp_len);
3260 if (!silc_public_key_payload_decode(tmp, tmp_len, &founder_key)) {
3261 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3262 SILC_STATUS_ERR_AUTH_FAILED,
3267 /* If key was not sent and the channel mode has already founder
3268 then the key was not to be changed. */
3269 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)
3273 /* Set the founder authentication */
3274 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
3276 silc_server_command_send_status_reply(
3277 cmd, SILC_COMMAND_CMODE,
3278 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3282 /* Verify the payload before setting the mode */
3283 if (!silc_auth_verify_data(tmp, tmp_len, SILC_AUTH_PUBLIC_KEY,
3284 founder_key, 0, server->sha1hash,
3285 client->id, SILC_ID_CLIENT)) {
3286 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3287 SILC_STATUS_ERR_AUTH_FAILED,
3292 /* Save the public key */
3293 if (channel->founder_key)
3294 silc_pkcs_public_key_free(channel->founder_key);
3295 if (silc_argument_get_arg_type(cmd->args, 8, NULL))
3296 channel->founder_key = founder_key;
3298 channel->founder_key = silc_pkcs_public_key_copy(founder_key);
3299 if (!channel->founder_key) {
3300 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3301 SILC_STATUS_ERR_AUTH_FAILED,
3306 fkey = silc_public_key_payload_encode(channel->founder_key);
3308 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3309 SILC_STATUS_ERR_AUTH_FAILED,
3311 silc_pkcs_public_key_free(channel->founder_key);
3312 channel->founder_key = NULL;
3317 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3318 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3319 if (channel->founder_key)
3320 silc_pkcs_public_key_free(channel->founder_key);
3321 channel->founder_key = NULL;
3327 if (mode_mask & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
3328 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3331 chpkdata = silc_argument_get_arg_type(cmd->args, 9, &chpklen);
3333 if (!chpkdata && channel->mode & SILC_CHANNEL_MODE_CHANNEL_AUTH)
3338 /* Process the channel public key(s) */
3339 st = silc_server_set_channel_pk_list(server, NULL, channel,
3341 if (st != SILC_STATUS_OK) {
3342 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE, st, 0);
3347 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3348 if (channel->mode & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
3349 if (channel->channel_pubkeys)
3350 silc_hash_table_free(channel->channel_pubkeys);
3351 channel->channel_pubkeys = NULL;
3358 /* Finally, set the mode */
3359 old_mask = channel->mode = mode_mask;
3361 /* Send CMODE_CHANGE notify. */
3362 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3363 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT)
3364 SILC_PUT32_MSB(channel->user_limit, ulimit);
3365 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
3366 SILC_NOTIFY_TYPE_CMODE_CHANGE, 8,
3367 cidp->data, silc_buffer_len(cidp),
3369 cipher, cipher ? strlen(cipher) : 0,
3370 hmac, hmac ? strlen(hmac) : 0,
3371 passphrase, passphrase ?
3372 strlen(passphrase) : 0,
3373 fkey ? fkey->data : NULL,
3374 fkey ? silc_buffer_len(fkey) : 0,
3375 chpkdata ? chpkdata : NULL,
3376 chpkdata ? chpklen : 0,
3377 mode_mask & SILC_CHANNEL_MODE_ULIMIT ?
3379 mode_mask & SILC_CHANNEL_MODE_ULIMIT ?
3380 sizeof(ulimit) : 0);
3382 /* Set CMODE notify type to network */
3383 if (chpkdata && chpklen)
3384 silc_buffer_set(&chpk, chpkdata, chpklen);
3385 silc_server_send_notify_cmode(server, SILC_PRIMARY_ROUTE(server),
3386 SILC_BROADCAST(server), channel,
3387 mode_mask, client->id, SILC_ID_CLIENT,
3388 cipher, hmac, passphrase, founder_key,
3389 chpkdata ? &chpk : NULL);
3392 chpklist = silc_server_get_channel_pk_list(server, channel, FALSE, FALSE);
3394 /* Send command reply to sender */
3395 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3396 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_CMODE,
3397 SILC_STATUS_OK, 0, ident, 5,
3398 2, tmp_id, tmp_len2,
3400 4, fkey ? fkey->data : NULL,
3401 fkey ? silc_buffer_len(fkey) : 0,
3402 5, chpklist ? chpklist->data :
3403 NULL, chpklist ? silc_buffer_len(chpklist)
3406 SILC_CHANNEL_MODE_ULIMIT ?
3409 SILC_CHANNEL_MODE_ULIMIT ?
3410 sizeof(ulimit) : 0));
3411 silc_buffer_free(cidp);
3414 channel->mode = old_mask;
3415 silc_buffer_free(chpklist);
3416 silc_buffer_free(fkey);
3417 silc_server_command_free(cmd);
3420 /* Server side of CUMODE command. Changes client's mode on a channel. */
3422 SILC_SERVER_CMD_FUNC(cumode)
3424 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3425 SilcServer server = cmd->server;
3426 SilcClientEntry client = silc_packet_get_context(cmd->sock);
3428 SilcChannelEntry channel;
3429 SilcClientEntry target_client;
3430 SilcChannelClientEntry chl;
3432 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
3433 SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
3435 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3436 SilcPublicKey founder_key = NULL;
3437 SilcBuffer fkey = NULL;
3442 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
3444 /* Get Channel ID */
3445 if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
3446 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3447 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3451 /* Get channel entry */
3452 channel = silc_idlist_find_channel_by_id(server->local_list,
3453 SILC_ID_GET_ID(id), NULL);
3455 channel = silc_idlist_find_channel_by_id(server->global_list,
3456 SILC_ID_GET_ID(id), NULL);
3458 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3459 silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3460 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
3461 0, 2, tmp_ch_id, tmp_ch_len);
3466 /* Check whether sender is on the channel */
3467 if (!silc_server_client_on_channel(client, channel, &chl)) {
3468 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3469 silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3470 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
3471 2, tmp_ch_id, tmp_ch_len);
3474 sender_mask = chl->mode;
3476 /* Get the target client's channel mode mask */
3477 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3479 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3480 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3484 SILC_GET32_MSB(target_mask, tmp_mask);
3486 /* Get target Client ID */
3487 if (!silc_argument_get_decoded(cmd->args, 3, SILC_ARGUMENT_ID, &id2, NULL)) {
3488 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3489 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
3493 /* Get target client's entry */
3494 target_client = silc_idlist_find_client_by_id(server->local_list,
3495 SILC_ID_GET_ID(id2),
3498 target_client = silc_idlist_find_client_by_id(server->global_list,
3499 SILC_ID_GET_ID(id2),
3502 if (target_client != client &&
3503 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
3504 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
3505 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3506 silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3507 SILC_STATUS_ERR_NOT_YOU, 0,
3508 2, tmp_ch_id, tmp_ch_len);
3512 /* Check whether target client is on the channel */
3513 if (target_client != client) {
3514 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
3515 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3516 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3517 silc_server_command_send_status_data2(
3518 cmd, SILC_COMMAND_CUMODE,
3519 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL, 0,
3521 3, tmp_ch_id, tmp_ch_len);
3530 /* If the target client is founder, no one else can change their mode
3532 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
3533 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3534 silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3535 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
3536 0, 2, tmp_ch_id, tmp_ch_len);
3540 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
3541 if (target_client != client) {
3542 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3543 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
3548 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
3549 /* The client tries to claim the founder rights. */
3550 unsigned char *tmp_auth;
3551 SilcUInt32 tmp_auth_len;
3552 SilcChannelClientEntry chl2;
3553 SilcHashTableList htl;
3555 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
3556 !channel->founder_key) {
3557 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3558 SILC_STATUS_ERR_AUTH_FAILED, 0);
3562 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
3564 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3565 SILC_STATUS_ERR_AUTH_FAILED, 0);
3569 /* Verify the authentication payload */
3570 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len, SILC_AUTH_PUBLIC_KEY,
3571 channel->founder_key, 0, server->sha1hash,
3572 client->id, SILC_ID_CLIENT)) {
3573 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3574 SILC_STATUS_ERR_AUTH_FAILED, 0);
3579 founder_key = channel->founder_key;
3580 fkey = silc_public_key_payload_encode(founder_key);
3582 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3583 SILC_STATUS_ERR_AUTH_FAILED, 0);
3587 /* There cannot be anyone else as founder on the channel now. This
3588 client is definitely the founder due to this authentication. This
3589 is done only on router, not on server, since server cannot know
3590 whether router will accept this mode change or not. XXX This
3591 probably shouldn't be done anymore at all, may cause problems in
3592 router-router connections too (maybe just AUTH_FAILED error should
3593 be returned). -Pekka */
3594 if (server->server_type == SILC_ROUTER) {
3595 silc_hash_table_list(channel->user_list, &htl);
3596 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
3597 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
3598 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3599 silc_server_force_cumode_change(server, NULL, channel, chl2,
3603 silc_hash_table_list_reset(&htl);
3606 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
3609 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3610 if (target_client == client) {
3611 /* Remove channel founder rights from itself */
3612 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3615 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3616 SILC_STATUS_ERR_NOT_YOU, 0);
3622 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
3623 /* Promote to operator */
3624 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3625 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3626 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3627 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3628 silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3629 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
3630 0, 2, tmp_ch_id, tmp_ch_len);
3634 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
3638 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
3639 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3640 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3641 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3642 silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3643 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
3644 0, 2, tmp_ch_id, tmp_ch_len);
3648 /* Demote to normal user */
3649 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
3654 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
3655 if (target_client != client) {
3656 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3657 SILC_STATUS_ERR_NOT_YOU, 0);
3661 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
3662 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
3666 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
3667 if (target_client != client) {
3668 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3669 SILC_STATUS_ERR_NOT_YOU, 0);
3673 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
3678 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
3679 if (target_client != client) {
3680 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3681 SILC_STATUS_ERR_NOT_YOU, 0);
3685 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)) {
3686 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
3690 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
3691 if (target_client != client) {
3692 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3693 SILC_STATUS_ERR_NOT_YOU, 0);
3697 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
3702 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
3703 if (target_client != client) {
3704 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3705 SILC_STATUS_ERR_NOT_YOU, 0);
3709 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)) {
3710 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
3714 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
3715 if (target_client != client) {
3716 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3717 SILC_STATUS_ERR_NOT_YOU, 0);
3721 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
3726 if (target_mask & SILC_CHANNEL_UMODE_QUIET) {
3727 if (!(chl->mode & SILC_CHANNEL_UMODE_QUIET)) {
3728 if (client == target_client) {
3729 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3730 SILC_STATUS_ERR_PERM_DENIED, 0);
3733 chl->mode |= SILC_CHANNEL_UMODE_QUIET;
3737 if (chl->mode & SILC_CHANNEL_UMODE_QUIET) {
3738 if (client == target_client) {
3739 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3740 SILC_STATUS_ERR_PERM_DENIED, 0);
3743 chl->mode &= ~SILC_CHANNEL_UMODE_QUIET;
3748 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3749 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3750 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3752 /* Send notify to channel, notify only if mode was actually changed. */
3754 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
3755 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
3756 idp->data, silc_buffer_len(idp),
3759 fkey ? fkey->data : NULL,
3760 fkey ? silc_buffer_len(fkey) : 0);
3762 /* Set CUMODE notify type to network */
3763 silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
3764 SILC_BROADCAST(server), channel,
3765 target_mask, client->id, SILC_ID_CLIENT,
3766 target_client->id, founder_key);
3769 /* Send command reply to sender */
3770 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_CUMODE,
3771 SILC_STATUS_OK, 0, ident, 3,
3773 3, tmp_ch_id, tmp_ch_len,
3774 4, tmp_id, tmp_len);
3775 silc_buffer_free(idp);
3778 silc_buffer_free(fkey);
3779 silc_server_command_free(cmd);
3782 /* Server side of KICK command. Kicks client out of channel. */
3784 SILC_SERVER_CMD_FUNC(kick)
3786 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3787 SilcServer server = cmd->server;
3788 SilcClientEntry client = silc_packet_get_context(cmd->sock);
3789 SilcClientEntry target_client;
3791 SilcChannelEntry channel;
3792 SilcChannelClientEntry chl;
3794 SilcUInt32 tmp_len, target_idp_len, clen;
3795 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3796 unsigned char *tmp, *comment, *target_idp;
3801 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
3803 /* Get Channel ID */
3804 if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
3805 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3806 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3810 /* Get channel entry */
3811 channel = silc_idlist_find_channel_by_id(server->local_list,
3812 SILC_ID_GET_ID(id), NULL);
3814 channel = silc_idlist_find_channel_by_id(server->local_list,
3815 SILC_ID_GET_ID(id), NULL);
3817 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3818 silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3819 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
3820 0, 2, tmp, tmp_len);
3825 /* Check whether sender is on the channel */
3826 if (!silc_server_client_on_channel(client, channel, &chl)) {
3827 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3828 silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3829 SILC_STATUS_ERR_NOT_ON_CHANNEL,
3830 0, 2, tmp, tmp_len);
3834 /* Check that the kicker is channel operator or channel founder */
3835 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
3836 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
3837 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3838 silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3839 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
3840 0, 2, tmp, tmp_len);
3844 /* Get target Client ID */
3845 if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id2, NULL)) {
3846 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3847 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
3851 /* Get target client's entry */
3852 target_client = silc_idlist_find_client_by_id(server->local_list,
3853 SILC_ID_GET_ID(id2),
3856 target_client = silc_idlist_find_client_by_id(server->global_list,
3857 SILC_ID_GET_ID(id2),
3860 /* Check whether target client is on the channel */
3861 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
3862 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3863 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
3864 silc_server_command_send_status_data2(cmd, SILC_COMMAND_KICK,
3865 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL,
3866 0, 2, target_idp, target_idp_len,
3871 /* Check that the target client is not channel founder. Channel founder
3872 cannot be kicked from the channel. */
3873 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3874 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3875 silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3876 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
3877 0, 2, tmp, tmp_len);
3882 comment = silc_argument_get_arg_type(cmd->args, 3, &clen);
3886 /* Send the reply back to the client */
3887 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3888 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
3889 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_KICK,
3890 SILC_STATUS_OK, 0, ident, 2,
3892 3, target_idp, target_idp_len);
3894 /* Send KICKED notify to local clients on the channel */
3895 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3896 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
3897 SILC_NOTIFY_TYPE_KICKED, 3,
3898 target_idp, target_idp_len,
3899 comment, comment ? strlen(comment) : 0,
3900 idp->data, silc_buffer_len(idp));
3901 silc_buffer_free(idp);
3903 /* Send KICKED notify to primary route */
3904 silc_server_send_notify_kicked(server, SILC_PRIMARY_ROUTE(server),
3905 SILC_BROADCAST(server), channel,
3906 target_client->id, client->id, comment);
3908 /* Remove the client from channel's invite list */
3909 if (channel->invite_list && silc_hash_table_count(channel->invite_list)) {
3911 silc_argument_payload_encode_one(NULL, target_idp, target_idp_len, 3);
3912 SilcArgumentPayload args =
3913 silc_argument_payload_parse(ab->data, silc_buffer_len(ab), 1);
3915 silc_server_inviteban_process(server, channel->invite_list, 1, args);
3916 silc_buffer_free(ab);
3917 silc_argument_payload_free(args);
3920 /* Remove the client from the channel. If the channel does not exist
3921 after removing the client then the client kicked itself off the channel
3922 and we don't have to send anything after that. */
3923 if (!silc_server_remove_from_one_channel(server, NULL, channel,
3924 target_client, FALSE))
3927 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3928 /* Re-generate channel key */
3929 if (!silc_server_create_channel_key(server, channel, 0))
3932 /* Send the channel key to the channel. The key of course is not sent
3933 to the client who was kicked off the channel. */
3934 silc_server_send_channel_key(server, target_client->connection, channel,
3935 server->server_type == SILC_ROUTER ?
3936 FALSE : !server->standalone);
3940 silc_server_command_free(cmd);
3943 /* Server side of OPER command. Client uses this comand to obtain server
3944 operator privileges to this server/router. */
3946 SILC_SERVER_CMD_FUNC(oper)
3948 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3949 SilcServer server = cmd->server;
3950 SilcClientEntry client = silc_packet_get_context(cmd->sock);
3951 unsigned char *username = NULL, *auth;
3953 SilcServerConfigAdmin *admin;
3954 SilcIDListData idata = (SilcIDListData)client;
3955 SilcBool result = FALSE;
3956 SilcPublicKey cached_key;
3957 const char *hostname, *ip;
3959 if (client->data.conn_type != SILC_CONN_CLIENT || !client)
3962 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
3964 silc_socket_stream_get_info(silc_packet_stream_get_stream(cmd->sock),
3965 NULL, &hostname, &ip, NULL);
3967 /* Get the username */
3968 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3970 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3971 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3976 /* Check username */
3977 username = silc_identifier_check(username, strlen(username),
3978 SILC_STRING_UTF8, 128, &tmp_len);
3980 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3981 SILC_STATUS_ERR_BAD_USERNAME,
3986 /* Get the admin configuration */
3987 admin = silc_server_config_find_admin(server, (char *)ip,
3988 username, client->nickname);
3990 admin = silc_server_config_find_admin(server, (char *)hostname,
3991 username, client->nickname);
3993 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3994 SILC_STATUS_ERR_AUTH_FAILED,
3996 SILC_LOG_INFO(("OPER authentication failed for username '%s' by "
3997 "nickname '%s' from %s", username,
3998 client->nickname, hostname));
4003 /* Get the authentication payload */
4004 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4006 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4007 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4012 /* Verify the authentication data. If both passphrase and public key
4013 is set then try both of them. */
4014 if (admin->passphrase)
4015 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4016 admin->passphrase, admin->passphrase_len,
4017 idata->hash, client->id, SILC_ID_CLIENT);
4018 if (!result && admin->publickeys) {
4020 silc_server_get_public_key(server,
4021 SILC_SKR_USAGE_SERVICE_AUTHORIZATION, admin);
4024 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4025 cached_key, 0, idata->hash,
4026 client->id, SILC_ID_CLIENT);
4029 /* Authentication failed */
4030 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4031 SILC_STATUS_ERR_AUTH_FAILED,
4036 /* Client is now server operator */
4037 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4039 /* Update statistics */
4040 if (SILC_IS_LOCAL(client))
4041 server->stat.my_server_ops++;
4042 if (server->server_type == SILC_ROUTER)
4043 server->stat.server_ops++;
4045 /* Send UMODE change to primary router */
4046 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
4047 SILC_BROADCAST(server), client->id,
4050 /* Check if anyone is watching this nickname */
4051 if (server->server_type == SILC_ROUTER)
4052 silc_server_check_watcher_list(server, client, NULL,
4053 SILC_NOTIFY_TYPE_UMODE_CHANGE);
4055 /* Send reply to the sender */
4056 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4060 silc_free(username);
4061 silc_server_command_free(cmd);
4064 SILC_TASK_CALLBACK(silc_server_command_detach_cb)
4066 SilcServer server = app_context;
4067 QuitInternal q = (QuitInternal)context;
4068 SilcClientID *client_id = (SilcClientID *)q->sock;
4069 SilcClientEntry client;
4070 SilcPacketStream sock;
4072 client = silc_idlist_find_client_by_id(server->local_list, client_id,
4074 if (client && client->connection) {
4075 sock = client->connection;
4077 /* Close the connection on our side */
4078 client->router = NULL;
4079 client->connection = NULL;
4080 silc_server_close_connection(server, sock);
4083 silc_free(client_id);
4087 SILC_TASK_CALLBACK(silc_server_command_detach_timeout)
4089 SilcServer server = app_context;
4090 QuitInternal q = (QuitInternal)context;
4091 SilcClientID *client_id = (SilcClientID *)q->sock;
4092 SilcClientEntry client;
4094 client = silc_idlist_find_client_by_id(server->local_list, client_id,
4096 if (client && client->mode & SILC_UMODE_DETACHED) {
4097 SILC_LOG_DEBUG(("Detach timeout"));
4098 silc_server_free_client_data(server, NULL, client, TRUE,
4102 silc_free(client_id);
4106 /* Server side of DETACH command. Detached the client from the network
4107 by closing the connection but preserving the session. */
4109 SILC_SERVER_CMD_FUNC(detach)
4111 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4112 SilcServer server = cmd->server;
4113 SilcClientEntry client = silc_packet_get_context(cmd->sock);
4116 if (server->config->detach_disabled) {
4117 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
4118 SILC_STATUS_ERR_OPERATION_ALLOWED,
4123 if (client->data.conn_type != SILC_CONN_CLIENT || !client)
4126 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
4128 /* Remove operator privileges, since the client may resume in some
4129 other server which to it does not have operator privileges. */
4130 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
4131 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
4133 /* Send the user mode notify to notify that client is detached */
4134 client->mode |= SILC_UMODE_DETACHED;
4135 client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
4136 client->data.status &= ~SILC_IDLIST_STATUS_NOATTR;
4137 client->last_command = 0;
4138 client->fast_command = 0;
4139 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
4140 SILC_BROADCAST(server), client->id,
4142 server->stat.my_detached++;
4144 /* Check if anyone is watching this nickname */
4145 if (server->server_type == SILC_ROUTER)
4146 silc_server_check_watcher_list(server, client, NULL,
4147 SILC_NOTIFY_TYPE_UMODE_CHANGE);
4149 q = silc_calloc(1, sizeof(*q));
4150 q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
4151 silc_schedule_task_add_timeout(server->schedule,
4152 silc_server_command_detach_cb,
4155 if (server->config->detach_timeout) {
4156 q = silc_calloc(1, sizeof(*q));
4157 q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
4158 silc_schedule_task_add_timeout(server->schedule,
4159 silc_server_command_detach_timeout,
4160 q, server->config->detach_timeout * 60, 0);
4163 /* Send reply to the sender */
4164 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
4168 silc_server_command_free(cmd);
4171 /* Server side of WATCH command. */
4173 SILC_SERVER_CMD_FUNC(watch)
4175 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4176 SilcServer server = cmd->server;
4177 char *add_nick, *del_nick;
4178 SilcUInt32 add_nick_len, del_nick_len, tmp_len, pk_len;
4179 unsigned char hash[SILC_HASH_MAXLEN], *tmp, *pk, *nick;
4180 SilcClientEntry client;
4182 SilcUInt16 old_ident;
4184 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WATCH, cmd, 1, 3);
4186 if (server->server_type != SILC_ROUTER && !server->standalone) {
4187 if (!cmd->pending) {
4188 /* Send the command to router */
4191 /* If backup receives this from primary, handle it locally */
4192 if (server->server_type == SILC_BACKUP_ROUTER &&
4193 cmd->sock == SILC_PRIMARY_ROUTE(server))
4196 SILC_LOG_DEBUG(("Forwarding WATCH to router"));
4199 cmd->server->stat.commands_sent++;
4201 old_ident = silc_command_get_ident(cmd->payload);
4202 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4203 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4205 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
4206 SILC_PACKET_COMMAND, cmd->packet->flags,
4207 tmpbuf->data, silc_buffer_len(tmpbuf));
4209 /* Reprocess this packet after received reply from router */
4210 silc_server_command_pending(server, SILC_COMMAND_WATCH,
4211 silc_command_get_ident(cmd->payload),
4212 silc_server_command_watch,
4213 silc_server_command_dup(cmd));
4214 cmd->pending = TRUE;
4215 silc_command_set_ident(cmd->payload, old_ident);
4216 silc_buffer_free(tmpbuf);
4219 SilcServerCommandReplyContext reply = context2;
4225 silc_command_get_status(reply->payload, &status, NULL);
4227 /* Backup router handles the WATCH command also. */
4228 if (server->server_type != SILC_BACKUP_ROUTER ||
4229 SILC_STATUS_IS_ERROR(status)) {
4230 /* Received reply from router, just send same data to the client. */
4231 SILC_LOG_DEBUG(("Received reply to WATCH from router"));
4232 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, status,
4239 /* We are router and keep the watch list for local cell */
4242 /* Get the client ID */
4243 if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
4244 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4245 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4250 /* Get the client entry which must be in local list */
4251 client = silc_idlist_find_client_by_id(server->local_list,
4252 SILC_ID_GET_ID(id), TRUE, NULL);
4254 /* Backup checks global list also */
4255 if (server->server_type == SILC_BACKUP_ROUTER)
4256 client = silc_idlist_find_client_by_id(server->global_list,
4257 SILC_ID_GET_ID(id), TRUE, NULL);
4259 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4260 silc_server_command_send_status_data(cmd, SILC_COMMAND_WATCH,
4261 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
4262 0, 2, tmp, tmp_len);
4267 /* Take public key for watching by public key */
4268 pk = silc_argument_get_arg_type(cmd->args, 4, &pk_len);
4271 add_nick = silc_argument_get_arg_type(cmd->args, 2, &add_nick_len);
4272 del_nick = silc_argument_get_arg_type(cmd->args, 3, &del_nick_len);
4273 if (!add_nick && !del_nick && !pk) {
4274 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4275 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4280 if (add_nick && add_nick_len > 128) {
4282 add_nick[add_nick_len - 1] = '\0';
4284 if (del_nick && del_nick_len > 128) {
4286 del_nick[del_nick_len - 1] = '\0';
4289 /* Add new nickname to be watched in our cell */
4291 nick = silc_identifier_check(add_nick, add_nick_len, SILC_STRING_UTF8, 128,
4294 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4295 SILC_STATUS_ERR_BAD_NICKNAME, 0);
4299 /* Hash the nick, we have the hash saved, not nicks because we can
4300 do one to one mapping to the nick from Client ID hash this way. */
4301 silc_hash_make(server->md5hash, nick, add_nick_len, hash);
4303 /* Check whether this client is already watching this nickname */
4304 if (silc_hash_table_find_by_context(server->watcher_list, hash,
4306 /* Nickname is alredy being watched for this client */
4307 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4308 SILC_STATUS_ERR_NICKNAME_IN_USE,
4314 /* Get the nickname from the watcher list and use the same key in
4315 new entries as well. If key doesn't exist then create it. */
4316 if (!silc_hash_table_find(server->watcher_list, hash, (void *)&tmp, NULL))
4317 tmp = silc_memdup(hash, CLIENTID_HASH_LEN);
4319 /* Add the client to the watcher list with the specified nickname hash. */
4320 silc_hash_table_add(server->watcher_list, tmp, client);
4324 /* Delete nickname from watch list */
4326 nick = silc_identifier_check(del_nick, del_nick_len, SILC_STRING_UTF8, 128,
4329 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4330 SILC_STATUS_ERR_BAD_NICKNAME, 0);
4334 /* Hash the nick, we have the hash saved, not nicks because we can
4335 do one to one mapping to the nick from Client ID hash this way. */
4336 silc_hash_make(server->md5hash, nick, del_nick_len, hash);
4338 /* Check that this client is watching for this nickname */
4339 if (!silc_hash_table_find_by_context(server->watcher_list, hash,
4340 client, (void *)&tmp)) {
4341 /* Nickname is alredy being watched for this client */
4342 silc_server_command_send_status_data(cmd, SILC_COMMAND_WATCH,
4343 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
4344 2, nick, del_nick_len);
4349 /* Delete the nickname from the watcher list. */
4350 silc_hash_table_del_by_context(server->watcher_list, hash, client);
4352 /* Now check whether there still exists entries with this key, if not
4353 then free the key to not leak memory. */
4354 if (!silc_hash_table_find(server->watcher_list, hash, NULL, NULL))
4359 /* Add/del public key */
4362 SilcArgumentPayload pkargs;
4364 SilcPublicKey public_key, pkkey;
4367 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4368 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4373 /* Get the argument from the Argument List Payload */
4374 SILC_GET16_MSB(pkargc, pk);
4375 pkargs = silc_argument_payload_parse(pk + 2, pk_len - 2, pkargc);
4377 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4378 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4383 pk = silc_argument_get_next_arg(pkargs, &type, &pk_len);
4385 if (!silc_public_key_payload_decode(pk, pk_len, &public_key)) {
4386 pk = silc_argument_get_next_arg(pkargs, &type, &pk_len);
4393 /* Add public key to watch list */
4395 /* Check whether this client is already watching this public key */
4396 if (silc_hash_table_find_by_context(server->watcher_list_pk,
4397 public_key, client, NULL)) {
4398 silc_pkcs_public_key_free(public_key);
4399 silc_server_command_send_status_reply(
4400 cmd, SILC_COMMAND_WATCH,
4401 SILC_STATUS_ERR_NICKNAME_IN_USE, 0);
4405 /* Get the public key from the watcher list and use the same key in
4406 new entries as well. If key doesn't exist then create it. */
4408 if (!silc_hash_table_find(server->watcher_list_pk, public_key,
4409 (void *)&pkkey, NULL))
4412 silc_pkcs_public_key_free(public_key);
4414 /* Add the client to the watcher list with the specified public
4416 silc_hash_table_add(server->watcher_list_pk, pkkey, client);
4418 } else if (type == 0x01) {
4419 /* Delete public key from watch list */
4421 /* Check that this client is watching this public key */
4422 if (silc_hash_table_find_by_context(server->watcher_list_pk,
4425 silc_pkcs_public_key_free(public_key);
4426 silc_server_command_send_status_reply(
4427 cmd, SILC_COMMAND_WATCH,
4428 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4432 /* Delete the public key from the watcher list. */
4433 silc_hash_table_del_by_context(server->watcher_list_pk,
4434 public_key, client);
4436 /* Now check whether there still exists entries with this key, if
4437 not then free the key to not leak memory. */
4438 if (!silc_hash_table_find(server->watcher_list_pk, hash, NULL, NULL))
4439 silc_pkcs_public_key_free(pkkey);
4440 silc_pkcs_public_key_free(public_key);
4443 pk = silc_argument_get_next_arg(pkargs, &type, &pk_len);
4448 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4451 /* Distribute the watch list to backup routers too */
4452 if (server->backup) {
4456 cmd->server->stat.commands_sent++;
4458 old_ident = silc_command_get_ident(cmd->payload);
4459 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4460 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4461 silc_server_backup_send(server, silc_packet_get_context(cmd->sock),
4462 SILC_PACKET_COMMAND,
4463 cmd->packet->flags, tmpbuf->data,
4464 silc_buffer_len(tmpbuf),
4466 silc_command_set_ident(cmd->payload, old_ident);
4467 silc_buffer_free(tmpbuf);
4471 silc_server_command_free(cmd);
4474 /* Server side of SILCOPER command. Client uses this comand to obtain router
4475 operator privileges to this router. */
4477 SILC_SERVER_CMD_FUNC(silcoper)
4479 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4480 SilcServer server = cmd->server;
4481 SilcClientEntry client = silc_packet_get_context(cmd->sock);
4482 unsigned char *username = NULL, *auth;
4484 SilcServerConfigAdmin *admin;
4485 SilcIDListData idata = (SilcIDListData)client;
4486 SilcBool result = FALSE;
4487 SilcPublicKey cached_key;
4488 const char *hostname, *ip;
4490 if (client->data.conn_type != SILC_CONN_CLIENT || !client)
4493 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4495 silc_socket_stream_get_info(silc_packet_stream_get_stream(cmd->sock),
4496 NULL, &hostname, &ip, NULL);
4498 if (server->server_type != SILC_ROUTER) {
4499 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4500 SILC_STATUS_ERR_AUTH_FAILED, 0);
4504 /* Get the username */
4505 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4507 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4508 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4513 /* Check username */
4514 username = silc_identifier_check(username, tmp_len, SILC_STRING_UTF8, 128,
4517 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4518 SILC_STATUS_ERR_BAD_USERNAME,
4523 /* Get the admin configuration */
4524 admin = silc_server_config_find_admin(server, (char *)ip,
4525 username, client->nickname);
4527 admin = silc_server_config_find_admin(server, (char *)hostname,
4528 username, client->nickname);
4530 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4531 SILC_STATUS_ERR_AUTH_FAILED, 0);
4532 SILC_LOG_INFO(("SILCOPER authentication failed for username '%s' by "
4533 "nickname '%s' from %s", username,
4534 client->nickname, hostname));
4539 /* Get the authentication payload */
4540 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4542 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4543 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4548 /* Verify the authentication data. If both passphrase and public key
4549 is set then try both of them. */
4550 if (admin->passphrase)
4551 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4552 admin->passphrase, admin->passphrase_len,
4553 idata->hash, client->id, SILC_ID_CLIENT);
4554 if (!result && admin->publickeys) {
4556 silc_server_get_public_key(server,
4557 SILC_SKR_USAGE_SERVICE_AUTHORIZATION, admin);
4560 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4561 cached_key, 0, idata->hash,
4562 client->id, SILC_ID_CLIENT);
4565 /* Authentication failed */
4566 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4567 SILC_STATUS_ERR_AUTH_FAILED, 0);
4571 /* Client is now router operator */
4572 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4574 /* Update statistics */
4575 if (SILC_IS_LOCAL(client))
4576 server->stat.my_router_ops++;
4577 if (server->server_type == SILC_ROUTER)
4578 server->stat.router_ops++;
4580 /* Send UMODE change to primary router */
4581 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
4582 SILC_BROADCAST(server), client->id,
4585 /* Check if anyone is watching this nickname */
4586 if (server->server_type == SILC_ROUTER)
4587 silc_server_check_watcher_list(server, client, NULL,
4588 SILC_NOTIFY_TYPE_UMODE_CHANGE);
4590 /* Send reply to the sender */
4591 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4595 silc_free(username);
4596 silc_server_command_free(cmd);
4599 /* Server side of command BAN. This is used to manage the ban list of the
4600 channel. To add clients and remove clients from the ban list. */
4602 SILC_SERVER_CMD_FUNC(ban)
4604 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4605 SilcServer server = cmd->server;
4606 SilcClientEntry client = silc_packet_get_context(cmd->sock);
4607 SilcBuffer list, tmp2;
4608 SilcChannelEntry channel;
4609 SilcChannelClientEntry chl;
4611 unsigned char *tmp_id, *tmp, *atype = NULL;
4612 SilcUInt32 id_len, len, len2;
4613 SilcArgumentPayload args;
4614 SilcHashTableList htl;
4616 SilcUInt16 argc = 0, ident = silc_command_get_ident(cmd->payload);
4617 SilcBufferStruct blist;
4619 if (client->data.conn_type != SILC_CONN_CLIENT || !client)
4622 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4624 /* Get Channel ID */
4625 if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
4626 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4627 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4631 /* Get channel entry. The server must know about the channel since the
4632 client is expected to be on the channel. */
4633 channel = silc_idlist_find_channel_by_id(server->local_list,
4634 SILC_ID_GET_ID(id), NULL);
4636 channel = silc_idlist_find_channel_by_id(server->global_list,
4637 SILC_ID_GET_ID(id), NULL);
4639 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4640 silc_server_command_send_status_data(
4641 cmd, SILC_COMMAND_BAN,
4642 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
4643 0, 2, tmp_id, id_len);
4648 /* Check whether this client is on the channel */
4649 if (!silc_server_client_on_channel(client, channel, &chl)) {
4650 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4651 silc_server_command_send_status_data(cmd, SILC_COMMAND_BAN,
4652 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
4657 /* The client must be at least channel operator. */
4658 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4659 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4660 silc_server_command_send_status_data(cmd, SILC_COMMAND_BAN,
4661 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0,
4666 /* Get the ban information */
4667 tmp = silc_argument_get_arg_type(cmd->args, 3, &len2);
4668 if (tmp && len2 > 2) {
4669 /* Parse the arguments to see they are constructed correctly */
4670 SILC_GET16_MSB(argc, tmp);
4671 args = silc_argument_payload_parse(tmp + 2, len2 - 2, argc);
4673 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4674 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4679 /* Get the type of action */
4680 atype = silc_argument_get_arg_type(cmd->args, 2, &len);
4681 if (atype && len == 1) {
4682 if (atype[0] == 0x00) {
4683 /* Allocate hash table for ban list if it doesn't exist yet */
4684 if (!channel->ban_list)
4686 silc_hash_table_alloc(0, silc_hash_ptr,
4688 silc_server_inviteban_destruct, channel,
4691 /* Check for resource limit */
4692 if (silc_hash_table_count(channel->ban_list) > 64) {
4693 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4694 SILC_STATUS_ERR_RESOURCE_LIMIT,
4700 /* Now add or delete the information. */
4701 if (!silc_server_inviteban_process(server, channel->ban_list,
4702 (SilcUInt8)atype[0], args)) {
4703 silc_server_command_send_status_reply(
4704 cmd, SILC_COMMAND_BAN,
4705 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4710 silc_argument_payload_free(args);
4713 /* Encode ban list */
4715 if (channel->ban_list && silc_hash_table_count(channel->ban_list)) {
4716 list = silc_buffer_alloc_size(2);
4717 silc_buffer_format(list,
4718 SILC_STR_UI_SHORT(silc_hash_table_count(
4719 channel->ban_list)),
4721 silc_hash_table_list(channel->ban_list, &htl);
4722 while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2))
4723 list = silc_argument_payload_encode_one(list, tmp2->data,
4724 silc_buffer_len(tmp2),
4725 SILC_PTR_TO_32(type));
4726 silc_hash_table_list_reset(&htl);
4729 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4731 /* Send BAN notify type to local servers (but not clients) and to
4733 if (atype && tmp && len2) {
4734 silc_buffer_set(&blist, tmp, len2);
4736 /* Send to local servers if we are router */
4737 if (server->server_type == SILC_ROUTER)
4738 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, FALSE,
4739 SILC_NOTIFY_TYPE_BAN, 3,
4742 tmp ? blist.data : NULL,
4743 tmp ? silc_buffer_len(&blist) : 0);
4745 /* Send to network. */
4746 silc_server_send_notify_ban(server, SILC_PRIMARY_ROUTE(server),
4747 SILC_BROADCAST(server), channel, atype,
4751 /* Send the reply back to the client */
4752 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_BAN,
4753 SILC_STATUS_OK, 0, ident, 2,
4755 3, list ? list->data : NULL,
4756 list ? silc_buffer_len(list) : 0);
4757 silc_buffer_free(list);
4760 silc_server_command_free(cmd);
4763 /* Server side command of LEAVE. Removes client from a channel. */
4765 SILC_SERVER_CMD_FUNC(leave)
4767 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4768 SilcServer server = cmd->server;
4769 SilcPacketStream sock = cmd->sock;
4770 SilcClientEntry id_entry = silc_packet_get_context(cmd->sock);
4772 SilcChannelEntry channel;
4776 if (id_entry->data.conn_type != SILC_CONN_CLIENT || !id_entry)
4779 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4781 /* Get Channel ID */
4782 if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
4783 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4784 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4788 /* Get channel entry */
4789 channel = silc_idlist_find_channel_by_id(server->local_list,
4790 SILC_ID_GET_ID(id), NULL);
4792 channel = silc_idlist_find_channel_by_id(server->global_list,
4793 SILC_ID_GET_ID(id), NULL);
4795 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4796 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4797 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
4803 /* Check whether this client is on the channel */
4804 if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
4805 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4806 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4807 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
4812 /* Notify routers that they should remove this client from their list
4813 of clients on the channel. Send LEAVE notify type. */
4814 silc_server_send_notify_leave(server, SILC_PRIMARY_ROUTE(server),
4815 SILC_BROADCAST(server), channel, id_entry->id);
4817 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4818 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4819 SILC_STATUS_OK, 0, 2, tmp, len);
4821 /* Remove client from channel */
4822 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4824 /* If the channel does not exist anymore we won't send anything */
4827 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4828 /* Re-generate channel key */
4829 if (!silc_server_create_channel_key(server, channel, 0))
4832 /* Send the channel key */
4833 silc_server_send_channel_key(server, NULL, channel,
4834 server->server_type == SILC_ROUTER ?
4835 FALSE : !server->standalone);
4839 silc_server_command_free(cmd);
4842 /* Server side of command USERS. Resolves clients and their USERS currently
4843 joined on the requested channel. The list of Client ID's and their modes
4844 on the channel is sent back. */
4846 SILC_SERVER_CMD_FUNC(users)
4848 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4849 SilcServer server = cmd->server;
4850 SilcIDListData idata = silc_packet_get_context(cmd->sock);
4851 SilcChannelEntry channel;
4854 unsigned char *channel_id;
4855 SilcUInt32 channel_id_len;
4856 SilcBuffer client_id_list;
4857 SilcBuffer client_mode_list;
4858 unsigned char lc[4];
4859 SilcUInt32 list_count = 0;
4860 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4861 char *channel_name, *channel_namec = NULL;
4863 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
4865 /* Get Channel ID */
4866 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4868 /* Get channel name */
4869 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
4871 if (!channel_id && !channel_name) {
4872 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4873 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4877 /* Check channel name */
4879 channel_namec = silc_channel_name_check(channel_name, strlen(channel_name),
4880 SILC_STRING_UTF8, 256, NULL);
4881 if (!channel_namec) {
4882 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4883 SILC_STATUS_ERR_BAD_CHANNEL, 0);
4888 /* Check Channel ID */
4890 if (!silc_id_payload_parse_id(channel_id, channel_id_len, &id)) {
4891 silc_server_command_send_status_data(cmd, SILC_COMMAND_USERS,
4892 SILC_STATUS_ERR_BAD_CHANNEL_ID, 0,
4893 2, channel_id, channel_id_len);
4898 /* If we are server and we don't know about this channel we will send
4899 the command to our router. If we know about the channel then we also
4900 have the list of users already. */
4902 channel = silc_idlist_find_channel_by_id(server->local_list,
4903 SILC_ID_GET_ID(id), NULL);
4905 channel = silc_idlist_find_channel_by_name(server->local_list,
4906 channel_namec, NULL);
4908 if (!channel || (!server->standalone && (channel->disabled ||
4909 !channel->users_resolved))) {
4910 if (server->server_type != SILC_ROUTER && !server->standalone &&
4915 cmd->server->stat.commands_sent++;
4917 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4918 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4920 /* Send USERS command */
4921 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
4922 SILC_PACKET_COMMAND, cmd->packet->flags,
4923 tmpbuf->data, silc_buffer_len(tmpbuf));
4925 /* Reprocess this packet after received reply */
4926 silc_server_command_pending(server, SILC_COMMAND_USERS,
4927 silc_command_get_ident(cmd->payload),
4928 silc_server_command_users,
4929 silc_server_command_dup(cmd));
4930 cmd->pending = TRUE;
4931 silc_command_set_ident(cmd->payload, ident);
4932 silc_buffer_free(tmpbuf);
4936 /* Check the global list as well. */
4938 channel = silc_idlist_find_channel_by_id(server->global_list,
4939 SILC_ID_GET_ID(id), NULL);
4941 channel = silc_idlist_find_channel_by_name(server->global_list,
4942 channel_namec, NULL);
4944 /* Channel really does not exist */
4946 silc_server_command_send_status_data(
4947 cmd, SILC_COMMAND_USERS,
4948 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID, 0,
4949 2, channel_id, channel_id_len);
4951 silc_server_command_send_status_data(
4952 cmd, SILC_COMMAND_USERS,
4953 SILC_STATUS_ERR_NO_SUCH_CHANNEL, 0,
4954 2, channel_name, strlen(channel_name));
4959 /* If the channel is private or secret do not send anything, unless the
4960 user requesting this command is on the channel or is server */
4961 if (idata->conn_type == SILC_CONN_CLIENT) {
4962 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
4963 && !silc_server_client_on_channel((SilcClientEntry)idata, channel,
4965 silc_server_command_send_status_data(cmd, SILC_COMMAND_USERS,
4966 SILC_STATUS_ERR_NO_SUCH_CHANNEL, 0,
4967 2, channel->channel_name,
4968 strlen(channel->channel_name));
4973 /* Get the users list */
4974 if (!silc_server_get_users_on_channel(server, channel, &client_id_list,
4975 &client_mode_list, &list_count)) {
4977 client_id_list = NULL;
4978 client_mode_list = NULL;
4982 SILC_PUT32_MSB(list_count, lc);
4985 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
4986 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_USERS,
4987 SILC_STATUS_OK, 0, ident, 4,
4988 2, idp->data, silc_buffer_len(idp),
4991 client_id_list->data : NULL,
4993 silc_buffer_len(client_id_list) : 0,
4994 5, client_mode_list ?
4995 client_mode_list->data : NULL,
4997 silc_buffer_len(client_mode_list) : 0);
4998 silc_buffer_free(idp);
5000 silc_buffer_free(client_id_list);
5001 if (client_mode_list)
5002 silc_buffer_free(client_mode_list);
5005 silc_free(channel_namec);
5006 silc_server_command_free(cmd);
5009 /* Server side of command GETKEY. This fetches the client's public key
5010 from the server where to the client is connected. */
5012 SILC_SERVER_CMD_FUNC(getkey)
5014 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5015 SilcServer server = cmd->server;
5016 SilcClientEntry client;
5017 SilcServerEntry server_entry;
5018 SilcClientID client_id;
5019 SilcServerID server_id;
5020 SilcIDPayload idp = NULL;
5021 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5024 SilcBuffer pk = NULL;
5026 SilcPublicKey public_key;
5028 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5030 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5031 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5035 idp = silc_id_payload_parse(tmp, tmp_len);
5037 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5038 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5043 id_type = silc_id_payload_get_type(idp);
5044 if (id_type == SILC_ID_CLIENT) {
5045 silc_id_payload_get_id(idp, &client_id, sizeof(client_id));
5047 /* If the client is not found from local list there is no chance it
5048 would be locally connected client so send the command further. */
5049 client = silc_idlist_find_client_by_id(server->local_list,
5050 &client_id, TRUE, NULL);
5052 client = silc_idlist_find_client_by_id(server->global_list,
5053 &client_id, TRUE, NULL);
5055 if ((!client && !cmd->pending && !server->standalone) ||
5056 (client && !client->connection && !cmd->pending &&
5057 !(client->mode & SILC_UMODE_DETACHED)) ||
5058 (client && !client->data.public_key && !cmd->pending)) {
5060 SilcUInt16 old_ident;
5061 SilcPacketStream dest_sock;
5063 dest_sock = silc_server_get_client_route(server, NULL, 0,
5064 &client_id, NULL, NULL);
5069 cmd->server->stat.commands_sent++;
5071 old_ident = silc_command_get_ident(cmd->payload);
5072 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5073 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5075 silc_server_packet_send(server, dest_sock,
5076 SILC_PACKET_COMMAND, cmd->packet->flags,
5077 tmpbuf->data, silc_buffer_len(tmpbuf));
5079 /* Reprocess this packet after received reply from router */
5080 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5081 silc_command_get_ident(cmd->payload),
5082 silc_server_command_getkey,
5083 silc_server_command_dup(cmd));
5084 cmd->pending = TRUE;
5085 silc_command_set_ident(cmd->payload, old_ident);
5086 silc_buffer_free(tmpbuf);
5091 silc_server_command_send_status_data(cmd, SILC_COMMAND_GETKEY,
5092 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5093 0, 2, tmp, tmp_len);
5097 /* The client is locally connected, just get the public key and
5098 send it back. If they key does not exist then do not send it,
5099 send just OK reply */
5100 public_key = client->data.public_key;
5102 pk = silc_public_key_payload_encode(public_key);
5103 } else if (id_type == SILC_ID_SERVER) {
5104 silc_id_payload_get_id(idp, &server_id, sizeof(server_id));
5106 /* If the server is not found from local list there is no chance it
5107 would be locally connected server so send the command further. */
5108 server_entry = silc_idlist_find_server_by_id(server->local_list,
5109 &server_id, TRUE, NULL);
5111 server_entry = silc_idlist_find_server_by_id(server->global_list,
5112 &server_id, TRUE, NULL);
5114 if (server_entry != server->id_entry &&
5115 ((!server_entry && !cmd->pending && !server->standalone) ||
5116 (server_entry && !server_entry->connection && !cmd->pending &&
5117 !server->standalone) ||
5118 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5119 !server->standalone))) {
5121 SilcUInt16 old_ident;
5124 cmd->server->stat.commands_sent++;
5126 old_ident = silc_command_get_ident(cmd->payload);
5127 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5128 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5130 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5131 SILC_PACKET_COMMAND, cmd->packet->flags,
5132 tmpbuf->data, silc_buffer_len(tmpbuf));
5134 /* Reprocess this packet after received reply from router */
5135 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5136 silc_command_get_ident(cmd->payload),
5137 silc_server_command_getkey,
5138 silc_server_command_dup(cmd));
5139 cmd->pending = TRUE;
5140 silc_command_set_ident(cmd->payload, old_ident);
5141 silc_buffer_free(tmpbuf);
5145 if (!server_entry) {
5146 silc_server_command_send_status_data(cmd, SILC_COMMAND_GETKEY,
5147 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
5148 0, 2, tmp, tmp_len);
5152 /* If they key does not exist then do not send it, send just OK reply */
5153 public_key = (!server_entry->data.public_key ?
5154 (server_entry == server->id_entry ? server->public_key :
5155 NULL) : server_entry->data.public_key);
5157 pk = silc_public_key_payload_encode(public_key);
5162 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5163 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_GETKEY,
5164 SILC_STATUS_OK, 0, ident, 2,
5166 3, pk ? pk->data : NULL,
5167 pk ? silc_buffer_len(pk) : 0);
5171 silc_id_payload_free(idp);
5172 silc_buffer_free(pk);
5173 silc_server_command_free(cmd);
5176 /* Server side of command SERVICE. */
5177 /* XXX currently this just sends empty reply back */
5179 SILC_SERVER_CMD_FUNC(service)
5181 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5182 SilcServer server = cmd->server;
5183 SilcUInt32 tmp_len, auth_len;
5184 unsigned char *service_name, *auth;
5185 SilcBool send_list = FALSE;
5186 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5188 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SERVICE, cmd, 0, 256);
5190 /* Get requested service */
5191 service_name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5192 if (service_name && tmp_len) {
5193 /* Verify service name */
5194 if (!silc_identifier_verify(service_name, tmp_len,
5195 SILC_STRING_UTF8, 256)) {
5196 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SERVICE,
5197 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5203 /* Get authentication payload if present */
5204 auth = silc_argument_get_arg_type(cmd->args, 2, &auth_len);
5212 /* Send our service list back */
5213 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_SERVICE,
5214 SILC_STATUS_OK, 0, ident, 0);
5217 silc_server_command_free(cmd);
5221 /* Private range commands, specific to this implementation */
5223 /* Server side command of CONNECT. Connects us to the specified remote
5224 server or router. */
5226 SILC_SERVER_CMD_FUNC(connect)
5228 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5229 SilcServer server = cmd->server;
5230 SilcClientEntry client = silc_packet_get_context(cmd->sock);
5231 unsigned char *tmp, *host;
5233 SilcUInt32 port = SILC_PORT;
5235 if (client->data.conn_type != SILC_CONN_CLIENT || !client)
5238 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
5240 /* Check whether client has the permissions. */
5241 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5242 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5243 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5244 SILC_STATUS_ERR_NO_SERVER_PRIV, 0);
5248 if (server->server_type == SILC_ROUTER && !server->backup_router &&
5249 client->mode & SILC_UMODE_SERVER_OPERATOR) {
5250 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5251 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
5255 /* Get the remote server */
5256 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5258 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5259 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5265 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5267 SILC_GET32_MSB(port, tmp);
5269 /* Create the connection. It is done with timeout and is async. */
5270 silc_server_create_connection(server, FALSE, FALSE, host, port, NULL, NULL);
5272 /* Send reply to the sender */
5273 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5277 silc_server_command_free(cmd);
5280 /* Server side command of CLOSE. Closes connection to a specified server. */
5282 SILC_SERVER_CMD_FUNC(close)
5284 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5285 SilcServer server = cmd->server;
5286 SilcClientEntry client = silc_packet_get_context(cmd->sock);
5287 SilcServerEntry server_entry;
5288 SilcPacketStream sock;
5291 unsigned char *name;
5292 SilcUInt32 port = SILC_PORT;
5294 if (client->data.conn_type != SILC_CONN_CLIENT || !client)
5297 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
5299 /* Check whether client has the permissions. */
5300 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5301 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5302 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5303 SILC_STATUS_ERR_NO_SERVER_PRIV,
5308 /* Get the remote server */
5309 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5311 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5312 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5318 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5320 SILC_GET32_MSB(port, tmp);
5322 server_entry = silc_idlist_find_server_by_conn(server->local_list,
5323 name, port, TRUE, NULL);
5325 server_entry = silc_idlist_find_server_by_conn(server->global_list,
5326 name, port, TRUE, NULL);
5327 if (!server_entry) {
5328 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5329 SILC_STATUS_ERR_NO_SERVER_ID, 0);
5333 if (server_entry == server->id_entry) {
5334 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5335 SILC_STATUS_ERR_NO_SERVER_ID, 0);
5339 /* Send reply to the sender */
5340 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5343 /* Close the connection to the server */
5344 sock = server_entry->connection;
5346 if (server_entry->server_type == SILC_BACKUP_ROUTER) {
5347 server->backup_closed = TRUE;
5348 silc_server_backup_del(server, server_entry);
5351 server->backup_noswitch = TRUE;
5352 if (server->router == server_entry) {
5353 server->id_entry->router = NULL;
5354 server->router = NULL;
5355 server->standalone = TRUE;
5357 silc_server_disconnect_remote(server, sock,
5358 SILC_STATUS_ERR_BANNED_FROM_SERVER,
5359 "Closed by administrator");
5360 silc_server_free_sock_user_data(server, sock, NULL);
5361 server->backup_noswitch = FALSE;
5364 silc_server_command_free(cmd);
5367 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
5368 active connections. */
5370 SILC_SERVER_CMD_FUNC(shutdown)
5372 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5373 SilcServer server = cmd->server;
5374 SilcClientEntry client = silc_packet_get_context(cmd->sock);
5376 if (client->data.conn_type != SILC_CONN_CLIENT || !client)
5379 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
5381 /* Check whether client has the permission. */
5382 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5383 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5384 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5385 SILC_STATUS_ERR_NO_SERVER_PRIV,
5390 /* Send reply to the sender */
5391 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5394 /* Then, gracefully, or not, bring the server down. */
5395 silc_server_stop(server);
5399 silc_server_command_free(cmd);