5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2009 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.
20 #include "serverincludes.h"
21 #include "server_internal.h"
23 static int silc_server_is_registered(SilcServer server,
24 SilcPacketStream sock,
25 SilcServerCommandContext cmd,
28 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
33 silc_server_command_send_status_data(SilcServerCommandContext cmd,
38 const unsigned char *arg,
41 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
42 SilcServerCommandReplyContext cmdr,
44 SILC_TASK_CALLBACK(silc_server_command_process_timeout);
46 /* Server command list. */
47 SilcServerCommand silc_command_list[] =
49 SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
50 SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
51 SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
52 SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
53 SILC_SERVER_CMD(list, LIST, SILC_CF_LAG_STRICT | SILC_CF_REG),
54 SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
55 SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
56 SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
57 SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG_STRICT | SILC_CF_REG | SILC_CF_OPER),
58 SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
59 SILC_SERVER_CMD(stats, STATS, SILC_CF_LAG | SILC_CF_REG),
60 SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
61 SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
62 SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG_STRICT | SILC_CF_REG),
63 SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
64 SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
65 SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG_STRICT | SILC_CF_REG),
66 SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
67 SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
68 SILC_SERVER_CMD(ban, BAN, SILC_CF_LAG_STRICT | SILC_CF_REG),
69 SILC_SERVER_CMD(detach, DETACH, SILC_CF_LAG_STRICT | SILC_CF_REG),
70 SILC_SERVER_CMD(watch, WATCH, SILC_CF_LAG | SILC_CF_REG),
71 SILC_SERVER_CMD(silcoper, SILCOPER,
72 SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
73 SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
74 SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
75 SILC_SERVER_CMD(getkey, GETKEY, SILC_CF_LAG | SILC_CF_REG),
76 SILC_SERVER_CMD(service, SERVICE, SILC_CF_LAG_STRICT | SILC_CF_REG),
78 SILC_SERVER_CMD(connect, PRIV_CONNECT,
79 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
80 SILC_SERVER_CMD(close, PRIV_CLOSE,
81 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
82 SILC_SERVER_CMD(shutdown, PRIV_SHUTDOWN, SILC_CF_LAG | SILC_CF_REG |
88 /* Returns TRUE if the connection is registered. Unregistered connections
89 usually cannot send commands hence the check. */
91 static int silc_server_is_registered(SilcServer server,
92 SilcPacketStream sock,
93 SilcServerCommandContext cmd,
96 SilcIDListData idata = silc_packet_get_context(sock);
101 if (idata->status & SILC_IDLIST_STATUS_REGISTERED)
104 silc_server_command_send_status_reply(cmd, command,
105 SILC_STATUS_ERR_NOT_REGISTERED, 0);
109 /* Performs several checks to the command. It first checks whether this
110 command was called as pending command callback. If it was then it checks
111 whether error occurred in the command reply where the pending command
114 It also checks that the requested command includes correct amount
116 #define SILC_SERVER_COMMAND_CHECK(command, context, min, max) \
120 if (silc_server_command_pending_error_check(cmd, context2, command)) { \
121 SILC_LOG_DEBUG(("Error occurred in command reply, command not called")); \
122 silc_server_command_free(cmd); \
127 !silc_server_is_registered(cmd->server, cmd->sock, cmd, command)) { \
128 SILC_LOG_DEBUG(("Not registered, command not called")); \
129 silc_server_command_free(cmd); \
133 _argc = silc_argument_get_arg_num(cmd->args); \
135 SILC_LOG_DEBUG(("Not enough parameters in command")); \
136 silc_server_command_send_status_reply(cmd, command, \
137 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, \
139 silc_server_command_free(cmd); \
143 SILC_LOG_DEBUG(("Too many parameters in command")); \
144 silc_server_command_send_status_reply(cmd, command, \
145 SILC_STATUS_ERR_TOO_MANY_PARAMS, \
147 silc_server_command_free(cmd); \
152 /* Internal context to hold data when executed command with timeout. */
154 SilcServerCommandContext ctx;
155 SilcServerCommand *cmd;
156 } *SilcServerCommandTimeout;
158 /* Timeout callback to process commands with timeout for client. Client's
159 commands are always executed with timeout. */
161 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
163 SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
164 SilcClientEntry client = silc_packet_get_context(timeout->ctx->sock);
167 SILC_LOG_DEBUG(("Client entry is invalid"));
168 silc_server_command_free(timeout->ctx);
173 /* Update access time */
174 client->last_command = time(NULL);
176 if (!(timeout->cmd->flags & SILC_CF_REG)) {
177 SILC_LOG_DEBUG(("Calling %s command",
178 silc_get_command_name(timeout->cmd->cmd)));
179 timeout->cmd->cb(timeout->ctx, NULL);
180 } else if (silc_server_is_registered(timeout->ctx->server,
183 timeout->cmd->cmd)) {
184 SILC_LOG_DEBUG(("Calling %s command",
185 silc_get_command_name(timeout->cmd->cmd)));
186 timeout->cmd->cb(timeout->ctx, NULL);
188 SILC_LOG_DEBUG(("Client is not registered"));
189 silc_server_command_free(timeout->ctx);
195 /* Processes received command packet. */
197 void silc_server_command_process(SilcServer server,
198 SilcPacketStream sock,
201 SilcIDListData idata = silc_packet_get_context(sock);
202 SilcServerCommandContext ctx;
203 SilcServerCommand *cmd;
209 /* Allocate command context. This must be free'd by the
210 command routine receiving it. */
211 ctx = silc_server_command_alloc();
212 ctx->server = server;
214 ctx->packet = packet; /* Save original packet */
215 silc_packet_stream_ref(sock);
217 /* Parse the command payload in the packet */
218 ctx->payload = silc_command_payload_parse(packet->buffer.data,
219 silc_buffer_len(&packet->buffer));
221 SILC_LOG_ERROR(("Bad command payload"));
222 silc_packet_free(packet);
223 silc_packet_stream_unref(ctx->sock);
227 ctx->args = silc_command_get_args(ctx->payload);
229 /* Get the command */
230 command = silc_command_get(ctx->payload);
231 for (cmd = silc_command_list; cmd->cb; cmd++)
232 if (cmd->cmd == command)
235 if (!cmd || !cmd->cb) {
236 SILC_LOG_DEBUG(("Unknown command %d", command));
237 silc_server_command_send_status_reply(ctx, command,
238 SILC_STATUS_ERR_UNKNOWN_COMMAND, 0);
239 silc_packet_free(packet);
240 silc_packet_stream_unref(ctx->sock);
245 /* Execute client's commands always with timeout. Normally they are
246 executed with zero (0) timeout but if client is sending command more
247 frequently than once in 2 seconds, then the timeout may be 0 to 2
249 if (idata->conn_type == SILC_CONN_CLIENT) {
250 SilcClientEntry client = silc_packet_get_context(sock);
251 SilcServerCommandTimeout timeout;
254 timeout = silc_calloc(1, sizeof(*timeout));
258 if (client->last_command && (time(NULL) - client->last_command) < 2) {
259 client->fast_command++;
262 if (client->fast_command - 2 <= 0)
263 client->fast_command = 0;
265 client->fast_command -= 2;
269 if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
270 (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
271 silc_schedule_task_add_timeout(
273 silc_server_command_process_timeout, timeout,
274 (client->fast_command < 3 ? 0 :
275 2 - (time(NULL) - client->last_command)),
276 (client->fast_command < 3 ? 200000 : 0));
278 silc_schedule_task_add_timeout(server->schedule,
279 silc_server_command_process_timeout,
284 /* Execute for server */
286 if (!(cmd->flags & SILC_CF_REG)) {
287 SILC_LOG_DEBUG(("Calling %s command", silc_get_command_name(cmd->cmd)));
289 } else if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) {
290 SILC_LOG_DEBUG(("Calling %s command", silc_get_command_name(cmd->cmd)));
293 SILC_LOG_DEBUG(("Server is not registered"));
294 silc_server_command_free(ctx);
298 /* Allocate Command Context */
300 SilcServerCommandContext silc_server_command_alloc()
302 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
307 /* Free's the command context allocated before executing the command */
309 void silc_server_command_free(SilcServerCommandContext ctx)
312 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
314 if (ctx->users < 1) {
316 silc_command_payload_free(ctx->payload);
318 silc_packet_free(ctx->packet);
320 silc_packet_stream_unref(ctx->sock);
325 /* Duplicate Command Context by adding reference counter. The context won't
326 be free'd untill it hits zero. */
328 SilcServerCommandContext
329 silc_server_command_dup(SilcServerCommandContext ctx)
332 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
337 /* Timeout for pending command. If reply to pending command never arrives
338 this is called to free resources. */
340 SILC_TASK_CALLBACK(silc_server_command_pending_timeout)
342 SilcServer server = app_context;
343 SilcServerCommandPending *reply = context;
344 SilcServerCommandReplyContext cmdr;
348 SILC_LOG_DEBUG(("Timeout pending command %p", reply));
350 /* Allocate temporary and bogus command reply context */
351 cmdr = silc_calloc(1, sizeof(*cmdr));
352 cmdr->server = server;
353 cmdr->ident = reply->ident;
355 /* Check for pending commands and mark to be exeucted */
357 silc_server_command_pending_check(server, reply->reply_cmd,
358 reply->ident, &cmdr->callbacks_count);
360 /* Create bogus command reply with an error inside */
362 silc_command_reply_payload_encode_va(reply->reply_cmd ? reply->reply_cmd :
363 SILC_COMMAND_RESERVED,
364 SILC_STATUS_ERR_TIMEDOUT, 0,
366 cmdr->payload = silc_command_payload_parse(tmpreply->data,
367 silc_buffer_len(tmpreply));
368 silc_buffer_free(tmpreply);
370 /* Call all callbacks. Same as SILC_SERVER_PENDING_EXEC macro. */
371 for (i = 0; i < cmdr->callbacks_count; i++)
372 if (cmdr->callbacks[i].callback)
373 (*cmdr->callbacks[i].callback)(cmdr->callbacks[i].context, cmdr);
375 silc_server_command_pending_del(server, reply->reply_cmd, reply->ident);
376 silc_server_command_reply_free(cmdr);
379 /* Add new pending command to be executed when reply to a command has been
380 received. The `reply_cmd' is the command that will call the `callback'
381 with `context' when reply has been received. It can be SILC_COMMAND_NONE
382 to match any command with the `ident'. If `ident' is non-zero
383 the `callback' will be executed when received reply with command
384 identifier `ident'. If there already exists pending command for the
385 specified command, ident, callback and context this function has no
388 SilcBool silc_server_command_pending(SilcServer server,
389 SilcCommand reply_cmd,
391 SilcCommandCb callback,
394 return silc_server_command_pending_timed(server, reply_cmd, ident, callback,
398 /* Same as silc_server_command_pending with specific timeout for pending
399 commands. If the `timeout' is zero default timeout is used. */
401 SilcBool silc_server_command_pending_timed(SilcServer server,
402 SilcCommand reply_cmd,
404 SilcCommandCb callback,
408 SilcServerCommandPending *reply;
410 /* Check whether identical pending already exists for same command,
411 ident, callback and callback context. If it does then it would be
412 error to register it again. */
413 silc_dlist_start(server->pending_commands);
414 while ((reply = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
415 if (reply->reply_cmd == reply_cmd && reply->ident == ident &&
416 reply->callback == callback && reply->context == context)
420 reply = silc_calloc(1, sizeof(*reply));
421 reply->reply_cmd = reply_cmd;
422 reply->ident = ident;
423 reply->context = context;
424 reply->callback = callback;
426 silc_schedule_task_add_timeout(server->schedule,
427 silc_server_command_pending_timeout, reply,
428 timeout ? timeout : 12, 0);
429 silc_dlist_add(server->pending_commands, reply);
434 /* Deletes pending command by reply command type. */
436 void silc_server_command_pending_del(SilcServer server,
437 SilcCommand reply_cmd,
440 SilcServerCommandPending *r;
442 silc_dlist_start(server->pending_commands);
443 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
444 if ((r->reply_cmd == reply_cmd || (r->reply_cmd == SILC_COMMAND_NONE &&
446 && r->ident == ident) {
447 silc_dlist_del(server->pending_commands, r);
449 silc_schedule_task_del(server->schedule, r->timeout);
455 /* Checks for pending commands and marks callbacks to be called from
456 the command reply function. Returns TRUE if there were pending command. */
458 SilcServerCommandPendingCallbacks
459 silc_server_command_pending_check(SilcServer server,
462 SilcUInt32 *callbacks_count)
464 SilcServerCommandPending *r;
465 SilcServerCommandPendingCallbacks callbacks = NULL;
468 silc_dlist_start(server->pending_commands);
469 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
470 if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE)
471 && r->ident == ident) {
472 callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
473 callbacks[i].context = r->context;
474 callbacks[i].callback = r->callback;
475 r->reply_check = TRUE;
480 *callbacks_count = i;
484 /* Sends simple status message as command reply packet */
487 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
495 cmd->server->stat.commands_sent++;
497 SILC_LOG_DEBUG(("Sending command status %d", status));
500 silc_command_reply_payload_encode_va(command, status, error,
501 silc_command_get_ident(cmd->payload),
503 silc_server_packet_send(cmd->server, cmd->sock,
504 SILC_PACKET_COMMAND_REPLY, 0,
505 buffer->data, silc_buffer_len(buffer));
506 silc_buffer_free(buffer);
509 /* Sends command status reply with one extra argument. The argument
510 type must be sent as argument. */
513 silc_server_command_send_status_data(SilcServerCommandContext cmd,
518 const unsigned char *arg,
524 cmd->server->stat.commands_sent++;
526 SILC_LOG_DEBUG(("Sending command status %d", status));
529 silc_command_reply_payload_encode_va(command, status, 0,
530 silc_command_get_ident(cmd->payload),
531 1, arg_type, arg, arg_len);
532 silc_server_packet_send(cmd->server, cmd->sock,
533 SILC_PACKET_COMMAND_REPLY, 0,
534 buffer->data, silc_buffer_len(buffer));
535 silc_buffer_free(buffer);
539 silc_server_command_send_status_data2(SilcServerCommandContext cmd,
543 SilcUInt32 arg_type1,
544 const unsigned char *arg1,
546 SilcUInt32 arg_type2,
547 const unsigned char *arg2,
553 cmd->server->stat.commands_sent++;
555 SILC_LOG_DEBUG(("Sending command status %d", status));
558 silc_command_reply_payload_encode_va(command, status, 0,
559 silc_command_get_ident(cmd->payload),
560 2, arg_type1, arg1, arg_len1,
561 arg_type2, arg2, arg_len2);
562 silc_server_packet_send(cmd->server, cmd->sock,
563 SILC_PACKET_COMMAND_REPLY, 0,
564 buffer->data, silc_buffer_len(buffer));
565 silc_buffer_free(buffer);
568 /* This function can be called to check whether in the command reply
569 an error occurred. This function has no effect if this is called
570 when the command function was not called as pending command callback.
571 This returns TRUE if error had occurred. */
574 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
575 SilcServerCommandReplyContext cmdr,
578 if (!cmd->pending || !cmdr)
581 if (!silc_command_get_status(cmdr->payload, NULL, NULL)) {
585 cmd->server->stat.commands_sent++;
587 /* Send the same command reply payload */
588 silc_command_set_command(cmdr->payload, silc_command_get(cmd->payload));
589 silc_command_set_ident(cmdr->payload,
590 silc_command_get_ident(cmd->payload));
591 buffer = silc_command_payload_encode_payload(cmdr->payload);
592 silc_server_packet_send(cmd->server, cmd->sock,
593 SILC_PACKET_COMMAND_REPLY, 0,
594 buffer->data, silc_buffer_len(buffer));
595 silc_buffer_free(buffer);
602 /* Server side of command WHOIS. */
604 SILC_SERVER_CMD_FUNC(whois)
606 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
607 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 256);
608 silc_server_query_command(cmd->server, SILC_COMMAND_WHOIS, cmd, NULL);
609 silc_server_command_free(cmd);
612 /* Server side of command WHOWAS. */
614 SILC_SERVER_CMD_FUNC(whowas)
616 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
617 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
618 silc_server_query_command(cmd->server, SILC_COMMAND_WHOWAS, cmd, NULL);
619 silc_server_command_free(cmd);
622 /* Server side of command IDENTIFY. */
624 SILC_SERVER_CMD_FUNC(identify)
626 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
627 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 256);
628 silc_server_query_command(cmd->server, SILC_COMMAND_IDENTIFY, cmd, NULL);
629 silc_server_command_free(cmd);
632 /* Server side of command NICK. Sets nickname for user. Setting
633 nickname causes generation of a new client ID for the client. The
634 new client ID is sent to the client after changing the nickname. */
636 SILC_SERVER_CMD_FUNC(nick)
638 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
639 SilcClientEntry client = silc_packet_get_context(cmd->sock);
640 SilcServer server = cmd->server;
641 SilcBuffer nidp, oidp = NULL;
642 SilcClientID *new_id;
644 unsigned char *nick, *nickc = NULL;
645 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
647 if (client->data.conn_type != SILC_CONN_CLIENT || !client)
650 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
653 nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
655 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
656 SILC_STATUS_ERR_BAD_NICKNAME, 0);
660 /* Truncate over long nicks */
661 if (nick_len > 128) {
663 nick[nick_len - 1] = '\0';
666 /* Check for valid nickname string. This is cached, original is saved
667 in the client context. */
668 nickc = silc_identifier_check(nick, nick_len, SILC_STRING_UTF8, 128, NULL);
670 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
671 SILC_STATUS_ERR_BAD_NICKNAME, 0);
675 /* Check for same nickname */
676 if (strlen(client->nickname) == nick_len &&
677 !memcmp(client->nickname, nick, nick_len)) {
678 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
683 /* Create new Client ID */
684 if (!silc_id_create_client_id(cmd->server, cmd->server->id,
686 cmd->server->md5hash,
687 nickc, strlen(nickc), &new_id)) {
688 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
689 SILC_STATUS_ERR_BAD_NICKNAME, 0);
694 /* Send notify about nickname change to our router. We send the new
695 ID and ask to replace it with the old one. If we are router the
696 packet is broadcasted. Send NICK_CHANGE notify. */
697 silc_server_send_notify_nick_change(server, SILC_PRIMARY_ROUTE(server),
698 SILC_BROADCAST(server), client->id,
701 /* Check if anyone is watching the old nickname */
702 if (server->server_type == SILC_ROUTER)
703 silc_server_check_watcher_list(server, client, nick,
704 SILC_NOTIFY_TYPE_NICK_CHANGE);
706 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
708 /* Update client entry */
709 silc_idcache_update_by_context(server->local_list->clients, client,
710 new_id, nickc, TRUE);
712 silc_free(client->nickname);
713 client->nickname = strdup(nick);
715 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
717 /* Send NICK_CHANGE notify to the client's channels */
718 silc_server_send_notify_on_channels(server, NULL, client,
719 SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
720 oidp->data, silc_buffer_len(oidp),
721 nidp->data, silc_buffer_len(nidp),
723 strlen(client->nickname));
725 /* Check if anyone is watching the new nickname */
726 if (server->server_type == SILC_ROUTER)
727 silc_server_check_watcher_list(server, client, NULL,
728 SILC_NOTIFY_TYPE_NICK_CHANGE);
731 /* Send the new Client ID as reply command back to client */
732 silc_server_send_command_reply(cmd->server, cmd->sock,
734 SILC_STATUS_OK, 0, ident, 2,
735 2, nidp->data, silc_buffer_len(nidp),
737 silc_buffer_free(nidp);
739 silc_buffer_free(oidp);
742 silc_server_command_free(cmd);
745 /* Sends the LIST command reply */
748 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
749 SilcChannelEntry *lch,
750 SilcUInt32 lch_count,
751 SilcChannelEntry *gch,
752 SilcUInt32 gch_count)
756 SilcChannelEntry entry;
758 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
760 unsigned char usercount[4];
762 int valid_lcount = 0, valid_rcount = 0;
764 for (i = 0; i < lch_count; i++) {
765 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
770 for (i = 0; i < gch_count; i++) {
771 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
777 if (!lch_count && !gch_count) {
778 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
783 status = SILC_STATUS_OK;
784 if ((lch_count + gch_count) > 1)
785 status = SILC_STATUS_LIST_START;
788 for (i = 0, k = 0; i < lch_count; i++) {
794 status = SILC_STATUS_LIST_ITEM;
795 if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
796 status = SILC_STATUS_LIST_END;
798 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
800 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
802 memset(usercount, 0, sizeof(usercount));
804 topic = entry->topic;
805 users = silc_hash_table_count(entry->user_list);
806 SILC_PUT32_MSB(users, usercount);
810 silc_server_send_command_reply(cmd->server, cmd->sock, SILC_COMMAND_LIST,
812 2, idp->data, silc_buffer_len(idp),
813 3, entry->channel_name,
814 strlen(entry->channel_name),
815 4, topic, topic ? strlen(topic) : 0,
817 silc_buffer_free(idp);
822 for (i = 0, k = 0; i < gch_count; i++) {
828 status = SILC_STATUS_LIST_ITEM;
829 if (valid_rcount > 1 && k == valid_rcount - 1)
830 status = SILC_STATUS_LIST_END;
832 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
834 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
836 memset(usercount, 0, sizeof(usercount));
838 topic = entry->topic;
839 users = entry->user_count;
840 SILC_PUT32_MSB(users, usercount);
844 silc_server_send_command_reply(cmd->server, cmd->sock, SILC_COMMAND_LIST,
846 2, idp->data, silc_buffer_len(idp),
847 3, entry->channel_name,
848 strlen(entry->channel_name),
849 4, topic, topic ? strlen(topic) : 0,
851 silc_buffer_free(idp);
856 /* Server side of LIST command. This lists the channel of the requested
857 server. Secret channels are not listed. */
859 SILC_SERVER_CMD_FUNC(list)
861 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
862 SilcServer server = cmd->server;
864 SilcChannelID *channel_id = NULL;
865 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
866 SilcUInt32 lch_count = 0, gch_count = 0;
868 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
870 /* If we are normal server, send the command to router, since we
871 want to know all channels in the network. */
872 if (!cmd->pending && server->server_type != SILC_ROUTER &&
873 !server->standalone) {
875 SilcUInt16 old_ident;
878 cmd->server->stat.commands_sent++;
880 old_ident = silc_command_get_ident(cmd->payload);
881 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
882 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
883 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
884 SILC_PACKET_COMMAND, cmd->packet->flags,
885 tmpbuf->data, silc_buffer_len(tmpbuf));
887 /* Reprocess this packet after received reply from router */
888 silc_server_command_pending(server, SILC_COMMAND_LIST,
889 silc_command_get_ident(cmd->payload),
890 silc_server_command_list,
891 silc_server_command_dup(cmd));
893 silc_command_set_ident(cmd->payload, old_ident);
894 silc_buffer_free(tmpbuf);
899 if (silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL))
900 channel_id = SILC_ID_GET_ID(id);
902 /* Get the channels from local list */
903 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
906 /* Get the channels from global list */
907 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
911 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
912 gchannels, gch_count);
914 silc_free(lchannels);
915 silc_free(gchannels);
918 silc_server_command_free(cmd);
921 /* Server side of TOPIC command. Sets topic for channel and/or returns
922 current topic to client. */
924 SILC_SERVER_CMD_FUNC(topic)
926 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
927 SilcServer server = cmd->server;
928 SilcClientEntry client = silc_packet_get_context(cmd->sock);
930 SilcChannelEntry channel;
931 SilcChannelClientEntry chl;
934 SilcUInt32 argc, tmp_len;
935 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
937 if (client->data.conn_type != SILC_CONN_CLIENT || !client)
940 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
942 argc = silc_argument_get_arg_num(cmd->args);
945 if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
946 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
947 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
951 /* Check whether the channel exists */
952 channel = silc_idlist_find_channel_by_id(server->local_list,
953 SILC_ID_GET_ID(id), NULL);
955 channel = silc_idlist_find_channel_by_id(server->global_list,
956 SILC_ID_GET_ID(id), NULL);
958 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
959 silc_server_command_send_status_data(cmd, SILC_COMMAND_TOPIC,
960 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
968 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
970 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
971 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
977 tmp[tmp_len - 1] = '\0';
980 if (!silc_utf8_valid(tmp, tmp_len)) {
981 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
982 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
987 /* See whether the client is on channel and has rights to change topic */
988 if (!silc_server_client_on_channel(client, channel, &chl)) {
989 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
990 silc_server_command_send_status_data(cmd, SILC_COMMAND_TOPIC,
991 SILC_STATUS_ERR_NOT_ON_CHANNEL,
996 if (channel->mode & SILC_CHANNEL_MODE_TOPIC &&
997 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
998 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
999 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1000 silc_server_command_send_status_data(cmd, SILC_COMMAND_TOPIC,
1001 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
1002 0, 2, tmp, tmp_len);
1006 if (!channel->topic || strcmp(channel->topic, tmp)) {
1007 /* Set the topic for channel */
1008 silc_free(channel->topic);
1009 channel->topic = strdup(tmp);
1011 /* Send TOPIC_SET notify type to the network */
1012 silc_server_send_notify_topic_set(server, SILC_PRIMARY_ROUTE(server),
1013 SILC_BROADCAST(server), channel,
1014 client->id, SILC_ID_CLIENT,
1017 /* Send notify about topic change to all clients on the channel */
1018 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1019 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
1020 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
1021 idp->data, silc_buffer_len(idp),
1023 strlen(channel->topic));
1024 silc_buffer_free(idp);
1028 /* Send the topic to client as reply packet */
1029 idp = silc_id_payload_encode(SILC_ID_GET_ID(id), SILC_ID_CHANNEL);
1030 silc_server_send_command_reply(cmd->server, cmd->sock, SILC_COMMAND_TOPIC,
1031 SILC_STATUS_OK, 0, ident, 2,
1032 2, idp->data, silc_buffer_len(idp),
1035 strlen(channel->topic) : 0);
1036 silc_buffer_free(idp);
1039 silc_server_command_free(cmd);
1042 /* Server side of INVITE command. Invites some client to join some channel.
1043 This command is also used to manage the invite list of the channel. */
1045 SILC_SERVER_CMD_FUNC(invite)
1047 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1048 SilcServer server = cmd->server;
1049 SilcPacketStream sock = cmd->sock, dest_sock;
1050 SilcChannelClientEntry chl;
1051 SilcClientEntry sender, dest;
1052 SilcChannelEntry channel;
1054 SilcIDListData idata;
1055 SilcArgumentPayload args;
1056 SilcHashTableList htl;
1057 SilcBuffer list, tmp2;
1058 SilcBufferStruct alist;
1059 unsigned char *tmp, *atype = NULL;
1060 SilcUInt32 len, len2, ttype;
1062 SilcUInt16 argc = 0, ident = silc_command_get_ident(cmd->payload);
1064 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
1066 /* Get Channel ID */
1067 if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
1068 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1069 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
1073 /* Get the channel entry */
1074 channel = silc_idlist_find_channel_by_id(server->local_list,
1075 SILC_ID_GET_ID(id), NULL);
1077 channel = silc_idlist_find_channel_by_id(server->global_list,
1078 SILC_ID_GET_ID(id), NULL);
1080 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1081 silc_server_command_send_status_data(cmd, SILC_COMMAND_INVITE,
1082 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
1088 /* Check whether the sender of this command is on the channel. */
1089 sender = silc_packet_get_context(sock);
1090 if (!sender || !silc_server_client_on_channel(sender, channel, &chl)) {
1091 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1092 silc_server_command_send_status_data(cmd, SILC_COMMAND_INVITE,
1093 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
1098 /* Check whether the channel is invite-only channel. If yes then the
1099 sender of this command must be at least channel operator. */
1100 if (channel->mode & SILC_CHANNEL_MODE_INVITE &&
1101 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
1102 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
1103 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1104 silc_server_command_send_status_data(cmd, SILC_COMMAND_INVITE,
1105 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
1110 /* Get destination client ID */
1111 if (silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id2, NULL)) {
1114 /* Get the client entry */
1115 dest = silc_server_query_client(server, SILC_ID_GET_ID(id2),
1118 if (server->server_type != SILC_SERVER || !resolve || cmd->pending) {
1119 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1120 silc_server_command_send_status_data(
1121 cmd, SILC_COMMAND_INVITE,
1122 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0,
1127 /* The client info is being resolved. Reprocess this packet after
1128 receiving the reply to the query. */
1129 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1131 silc_server_command_invite,
1132 silc_server_command_dup(cmd));
1133 cmd->pending = TRUE;
1137 /* Check whether the requested client is already on the channel. */
1138 if (silc_server_client_on_channel(dest, channel, NULL)) {
1139 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1140 atype = silc_argument_get_arg_type(cmd->args, 1, &len2);
1141 silc_server_command_send_status_data2(cmd, SILC_COMMAND_INVITE,
1142 SILC_STATUS_ERR_USER_ON_CHANNEL,
1148 /* Get route to the client */
1149 dest_sock = silc_server_get_client_route(server, NULL, 0,
1150 SILC_ID_GET_ID(id2),
1153 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1154 silc_server_command_send_status_data(cmd, SILC_COMMAND_INVITE,
1155 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1160 /* Add the client to the invite list */
1162 /* Allocate hash table for invite list if it doesn't exist yet */
1163 if (!channel->invite_list)
1164 channel->invite_list =
1165 silc_hash_table_alloc(0, silc_hash_ptr,
1167 silc_server_inviteban_destruct, channel, TRUE);
1169 /* Check if the ID is in the list already */
1170 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1171 silc_hash_table_list(channel->invite_list, &htl);
1172 while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) {
1173 if (SILC_PTR_TO_32(type) == 3 && !memcmp(tmp2->data, tmp, len)) {
1178 silc_hash_table_list_reset(&htl);
1180 /* Add new Client ID to invite list */
1182 list = silc_buffer_alloc_size(len);
1183 silc_buffer_put(list, tmp, len);
1184 silc_hash_table_add(channel->invite_list, (void *)3, list);
1187 if (!(dest->mode & SILC_UMODE_BLOCK_INVITE)) {
1188 /* Send notify to the client that is invited to the channel */
1189 SilcBuffer idp, idp2;
1190 idp = silc_id_payload_encode(SILC_ID_GET_ID(id), SILC_ID_CHANNEL);
1191 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1192 silc_server_send_notify_dest(server, dest_sock, FALSE,
1193 SILC_ID_GET_ID(id2), SILC_ID_CLIENT,
1194 SILC_NOTIFY_TYPE_INVITE, 3,
1195 idp->data, silc_buffer_len(idp),
1196 channel->channel_name,
1197 strlen(channel->channel_name),
1198 idp2->data, silc_buffer_len(idp2));
1199 silc_buffer_free(idp);
1200 silc_buffer_free(idp2);
1204 /* Get the invite information */
1205 tmp = silc_argument_get_arg_type(cmd->args, 4, &len2);
1206 if (tmp && len2 > 2) {
1207 /* Parse the arguments to see they are constructed correctly */
1208 SILC_GET16_MSB(argc, tmp);
1209 args = silc_argument_payload_parse(tmp + 2, len2 - 2, argc);
1211 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1212 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1217 /* Get the type of action */
1218 atype = silc_argument_get_arg_type(cmd->args, 3, &len);
1219 if (atype && len == 1) {
1220 if (atype[0] == 0x00) {
1221 /* Allocate hash table for invite list if it doesn't exist yet */
1222 if (!channel->invite_list)
1223 channel->invite_list =
1224 silc_hash_table_alloc(0, silc_hash_ptr,
1226 silc_server_inviteban_destruct, channel,
1229 /* Check for resource limit */
1230 if (silc_hash_table_count(channel->invite_list) > 64) {
1231 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1232 SILC_STATUS_ERR_RESOURCE_LIMIT,
1238 /* Now add or delete the information. */
1239 if (!silc_server_inviteban_process(server, channel->invite_list,
1240 (SilcUInt8)atype[0], args)) {
1241 silc_server_command_send_status_reply(
1242 cmd, SILC_COMMAND_INVITE,
1243 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1248 silc_argument_payload_free(args);
1251 /* Encode invite list */
1253 if (channel->invite_list && silc_hash_table_count(channel->invite_list)) {
1254 list = silc_buffer_alloc_size(2);
1255 silc_buffer_format(list,
1256 SILC_STR_UI_SHORT(silc_hash_table_count(
1257 channel->invite_list)),
1259 silc_hash_table_list(channel->invite_list, &htl);
1260 while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2))
1261 list = silc_argument_payload_encode_one(list, tmp2->data,
1262 silc_buffer_len(tmp2),
1263 SILC_PTR_TO_32(type));
1264 silc_hash_table_list_reset(&htl);
1267 /* The notify is sent to local servers (not clients), and to network. */
1268 if (atype && tmp && len2) {
1269 silc_buffer_set(&alist, tmp, len2);
1271 /* Send to local servers if we are router */
1272 if (server->server_type == SILC_ROUTER) {
1273 SilcBuffer idp, idp2;
1274 idp = silc_id_payload_encode(SILC_ID_GET_ID(id), SILC_ID_CHANNEL);
1275 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1276 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, FALSE,
1277 SILC_NOTIFY_TYPE_INVITE, 5,
1278 idp->data, silc_buffer_len(idp),
1279 channel->channel_name,
1280 strlen(channel->channel_name),
1281 idp2->data, silc_buffer_len(idp2),
1283 tmp ? alist.data : NULL,
1284 tmp ? silc_buffer_len(&alist) : 0);
1285 silc_buffer_free(idp);
1286 silc_buffer_free(idp2);
1289 /* Send to network */
1290 silc_server_send_notify_invite(server, SILC_PRIMARY_ROUTE(server),
1291 SILC_BROADCAST(server), channel,
1293 tmp ? &alist : NULL);
1296 /* Send invite list back only if the list was modified, or no arguments
1299 argc = silc_argument_get_arg_num(cmd->args);
1302 if (silc_argument_get_arg_type(cmd->args, 3, &len))
1305 /* Send command reply */
1306 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1307 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_INVITE,
1308 SILC_STATUS_OK, 0, ident, 2,
1312 ttype && list ? silc_buffer_len(list) : 0);
1313 silc_buffer_free(list);
1316 silc_server_command_free(cmd);
1320 SilcPacketStream sock;
1324 /* Quits connection to client. This gets called if client won't
1325 close the connection even when it has issued QUIT command. */
1327 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
1329 SilcServer server = app_context;
1330 QuitInternal q = (QuitInternal)context;
1331 SilcClientEntry client = silc_packet_get_context(q->sock);
1334 /* Free all client specific data, such as client entry and entires
1335 on channels this client may be on. */
1336 silc_server_free_sock_user_data(server, q->sock, q->signoff);
1337 silc_server_close_connection(server, q->sock);
1340 silc_packet_stream_unref(q->sock);
1341 silc_free(q->signoff);
1345 /* Quits SILC session. This is the normal way to disconnect client. */
1347 SILC_SERVER_CMD_FUNC(quit)
1349 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1350 SilcServer server = cmd->server;
1351 SilcPacketStream sock = cmd->sock;
1352 SilcClientEntry client = silc_packet_get_context(sock);
1354 unsigned char *tmp = NULL;
1357 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
1359 if (client->data.conn_type != SILC_CONN_CLIENT)
1363 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1367 q = silc_calloc(1, sizeof(*q));
1369 q->signoff = tmp ? strdup(tmp) : NULL;
1370 silc_packet_stream_ref(q->sock);
1372 /* We quit the connection with little timeout */
1373 silc_schedule_task_add_timeout(server->schedule,
1374 silc_server_command_quit_cb, (void *)q,
1378 silc_server_command_free(cmd);
1381 /* Server side of command KILL. This command is used by router operator
1382 to remove an client from the SILC Network temporarily. */
1384 SILC_SERVER_CMD_FUNC(kill)
1386 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1387 SilcServer server = cmd->server;
1388 SilcClientEntry client = silc_packet_get_context(cmd->sock);
1389 SilcClientEntry remote_client;
1391 unsigned char *tmp, *comment, *auth;
1392 SilcUInt32 tmp_len, tmp_len2, auth_len;
1394 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 3);
1396 if (client->data.conn_type != SILC_CONN_CLIENT || !client)
1399 /* Get authentication payload if present */
1400 auth = silc_argument_get_arg_type(cmd->args, 3, &auth_len);
1403 /* Router operator killing */
1405 /* KILL command works only on router */
1406 if (server->server_type != SILC_ROUTER) {
1407 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1408 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
1412 /* Check whether client has the permissions. */
1413 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
1414 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1415 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
1420 /* Get the client ID */
1421 if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
1422 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1423 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
1427 /* Get the client entry */
1428 remote_client = silc_idlist_find_client_by_id(server->local_list,
1431 if (!remote_client) {
1432 remote_client = silc_idlist_find_client_by_id(server->global_list,
1435 if (!remote_client) {
1436 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1437 silc_server_command_send_status_data(cmd, SILC_COMMAND_KILL,
1438 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1439 0, 2, tmp, tmp_len);
1445 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
1446 if (comment && tmp_len2 > 128) {
1448 comment[tmp_len2 - 1] = '\0';
1451 /* If authentication data is provided then verify that killing is
1453 if (auth && auth_len) {
1454 SilcPacketStream sock;
1456 if (!SILC_IS_LOCAL(remote_client) || !remote_client->data.public_key) {
1457 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1458 SILC_STATUS_ERR_OPERATION_ALLOWED,
1463 /* Verify the signature */
1464 if (!silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
1465 remote_client->data.public_key, 0,
1466 server->sha1hash, remote_client->id,
1468 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1469 SILC_STATUS_ERR_AUTH_FAILED, 0);
1473 /* Send reply to the sender */
1474 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1475 silc_server_command_send_status_data(cmd, SILC_COMMAND_KILL,
1479 /* Do normal signoff for the destination client */
1480 sock = remote_client->connection;
1483 silc_packet_stream_ref(sock);
1485 silc_server_remove_from_channels(server, NULL, remote_client,
1486 TRUE, (char *)"Killed", TRUE, TRUE);
1487 silc_server_free_sock_user_data(server, sock, comment ? comment :
1488 (unsigned char *)"Killed");
1490 silc_packet_set_context(sock, NULL);
1491 silc_server_close_connection(server, sock);
1492 silc_packet_stream_unref(sock);
1495 /* Router operator killing */
1497 /* Send reply to the sender */
1498 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1499 silc_server_command_send_status_data(cmd, SILC_COMMAND_KILL,
1503 /* Check if anyone is watching this nickname */
1504 if (server->server_type == SILC_ROUTER)
1505 silc_server_check_watcher_list(server, client, NULL,
1506 SILC_NOTIFY_TYPE_KILLED);
1508 /* Now do the killing */
1509 silc_server_kill_client(server, remote_client, comment, client->id,
1514 silc_server_command_free(cmd);
1517 /* Server side of command INFO. This sends information about us to
1518 the client. If client requested specific server we will send the
1519 command to that server. */
1521 SILC_SERVER_CMD_FUNC(info)
1523 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1524 SilcServer server = cmd->server;
1528 char *dest_server = NULL, *server_info = NULL, *server_name;
1529 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1530 SilcServerEntry entry = NULL;
1533 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
1535 /* Get server name */
1536 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1538 /* Check server name. */
1539 dest_server = silc_identifier_check(dest_server, strlen(dest_server),
1540 SILC_STRING_UTF8, 256, &tmp_len);
1542 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1543 SILC_STATUS_ERR_BAD_SERVER, 0);
1549 if (silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL)) {
1550 /* Check whether we have this server cached */
1551 entry = silc_idlist_find_server_by_id(server->local_list,
1552 SILC_ID_GET_ID(id), TRUE, NULL);
1554 entry = silc_idlist_find_server_by_id(server->global_list,
1555 SILC_ID_GET_ID(id), TRUE, NULL);
1556 if (!entry && server->server_type != SILC_SERVER) {
1557 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1558 silc_server_command_send_status_data(cmd, SILC_COMMAND_INFO,
1559 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
1560 0, 2, tmp, tmp_len);
1566 if ((!dest_server && !entry) || (entry && entry == server->id_entry) ||
1567 (dest_server && !cmd->pending &&
1568 !memcmp(dest_server, server->server_name, strlen(dest_server)))) {
1569 /* Send our reply */
1570 char info_string[256];
1572 memset(info_string, 0, sizeof(info_string));
1573 silc_snprintf(info_string, sizeof(info_string),
1574 "location: %s server: %s admin: %s <%s> version: %s",
1575 server->config->server_info->location,
1576 server->config->server_info->server_type,
1577 server->config->server_info->admin,
1578 server->config->server_info->email,
1581 server_info = info_string;
1582 entry = server->id_entry;
1584 /* Check whether we have this server cached */
1585 if (!entry && dest_server) {
1586 entry = silc_idlist_find_server_by_name(server->global_list,
1587 dest_server, TRUE, NULL);
1589 entry = silc_idlist_find_server_by_name(server->local_list,
1590 dest_server, TRUE, NULL);
1594 if (!cmd->pending &&
1595 server->server_type != SILC_SERVER && entry && !entry->server_info) {
1596 /* Send to the server */
1598 SilcUInt16 old_ident;
1601 cmd->server->stat.commands_sent++;
1603 old_ident = silc_command_get_ident(cmd->payload);
1604 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1605 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1607 silc_server_packet_send(server, entry->connection,
1608 SILC_PACKET_COMMAND, cmd->packet->flags,
1609 tmpbuf->data, silc_buffer_len(tmpbuf));
1611 /* Reprocess this packet after received reply from router */
1612 silc_server_command_pending(server, SILC_COMMAND_INFO,
1613 silc_command_get_ident(cmd->payload),
1614 silc_server_command_info,
1615 silc_server_command_dup(cmd));
1616 cmd->pending = TRUE;
1617 silc_command_set_ident(cmd->payload, old_ident);
1618 silc_buffer_free(tmpbuf);
1622 if (!entry && !cmd->pending && !server->standalone) {
1623 /* Send to the primary router */
1625 SilcUInt16 old_ident;
1628 cmd->server->stat.commands_sent++;
1630 old_ident = silc_command_get_ident(cmd->payload);
1631 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1632 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1634 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
1635 SILC_PACKET_COMMAND, cmd->packet->flags,
1636 tmpbuf->data, silc_buffer_len(tmpbuf));
1638 /* Reprocess this packet after received reply from router */
1639 silc_server_command_pending(server, SILC_COMMAND_INFO,
1640 silc_command_get_ident(cmd->payload),
1641 silc_server_command_info,
1642 silc_server_command_dup(cmd));
1643 cmd->pending = TRUE;
1644 silc_command_set_ident(cmd->payload, old_ident);
1645 silc_buffer_free(tmpbuf);
1652 silc_free(dest_server);
1653 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1654 silc_server_command_send_status_data(cmd, SILC_COMMAND_INFO,
1655 SILC_STATUS_ERR_NO_SUCH_SERVER, 0,
1657 strlen(dest_server));
1663 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1665 server_info = entry->server_info;
1666 server_name = entry->server_name;
1668 /* Send the reply */
1669 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_INFO,
1670 SILC_STATUS_OK, 0, ident, 3,
1671 2, idp->data, silc_buffer_len(idp),
1673 strlen(server_name),
1676 strlen(server_info) : 0);
1677 silc_buffer_free(idp);
1680 silc_free(dest_server);
1681 silc_server_command_free(cmd);
1684 /* Server side of command PING. This just replies to the ping. */
1686 SILC_SERVER_CMD_FUNC(ping)
1688 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1689 SilcServer server = cmd->server;
1694 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PING, cmd, 1, 1);
1697 if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
1698 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1699 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1704 if (SILC_ID_SERVER_COMPARE(SILC_ID_GET_ID(id), server->id)) {
1705 /* Send our reply */
1706 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1709 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1710 silc_server_command_send_status_data(cmd, SILC_COMMAND_PING,
1711 SILC_STATUS_ERR_NO_SUCH_SERVER_ID, 0,
1717 silc_server_command_free(cmd);
1720 /* Server side of command STATS. */
1722 SILC_SERVER_CMD_FUNC(stats)
1724 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1725 SilcServer server = cmd->server;
1729 SilcBuffer packet, stats;
1730 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1733 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1);
1736 if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
1737 silc_server_command_send_status_reply(cmd, SILC_COMMAND_STATS,
1738 SILC_STATUS_ERR_NO_SERVER_ID, 0);
1742 SILC_LOG_DEBUG(("id %s", silc_id_render(SILC_ID_GET_ID(id),
1745 /* The ID must be ours */
1746 if (!SILC_ID_SERVER_COMPARE(server->id, SILC_ID_GET_ID(id))) {
1747 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1748 silc_server_command_send_status_data(cmd, SILC_COMMAND_STATS,
1749 SILC_STATUS_ERR_NO_SUCH_SERVER_ID, 0,
1754 /* If we are router then just send everything we got. If we are normal
1755 server then we'll send this to our router to get all the latest
1756 statistical information. */
1757 if (!cmd->pending && server->server_type != SILC_ROUTER &&
1758 !server->standalone) {
1762 cmd->server->stat.commands_sent++;
1764 /* Send request to our router */
1765 idp = silc_id_payload_encode(server->router->id,
1767 packet = silc_command_payload_encode_va(SILC_COMMAND_STATS,
1768 ++server->cmd_ident, 1,
1770 silc_buffer_len(idp));
1771 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
1772 SILC_PACKET_COMMAND, 0, packet->data,
1773 silc_buffer_len(packet));
1775 /* Reprocess this packet after received reply from router */
1776 silc_server_command_pending(server, SILC_COMMAND_STATS,
1778 silc_server_command_stats,
1779 silc_server_command_dup(cmd));
1780 cmd->pending = TRUE;
1781 silc_buffer_free(packet);
1782 silc_buffer_free(idp);
1786 /* Send our reply to sender */
1787 uptime = time(NULL) - server->starttime;
1789 stats = silc_buffer_alloc_size(60);
1790 silc_buffer_format(stats,
1791 SILC_STR_UI_INT(server->starttime),
1792 SILC_STR_UI_INT(uptime),
1793 SILC_STR_UI_INT(server->stat.my_clients),
1794 SILC_STR_UI_INT(server->stat.my_channels),
1795 SILC_STR_UI_INT(server->stat.my_server_ops),
1796 SILC_STR_UI_INT(server->stat.my_router_ops),
1797 SILC_STR_UI_INT(server->stat.cell_clients),
1798 SILC_STR_UI_INT(server->stat.cell_channels),
1799 SILC_STR_UI_INT(server->stat.cell_servers),
1800 SILC_STR_UI_INT(server->stat.clients),
1801 SILC_STR_UI_INT(server->stat.channels),
1802 SILC_STR_UI_INT(server->stat.servers),
1803 SILC_STR_UI_INT(server->stat.routers),
1804 SILC_STR_UI_INT(server->stat.server_ops),
1805 SILC_STR_UI_INT(server->stat.router_ops),
1808 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1809 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_STATS,
1810 SILC_STATUS_OK, 0, ident, 2,
1812 3, stats->data, silc_buffer_len(stats));
1813 silc_buffer_free(stats);
1816 silc_server_command_free(cmd);
1819 /* Internal routine to join channel. The channel sent to this function
1820 has been either created or resolved from ID lists. This joins the sent
1821 client to the channel. */
1823 static void silc_server_command_join_channel(SilcServer server,
1824 SilcServerCommandContext cmd,
1825 SilcChannelEntry channel,
1826 SilcClientID *client_id,
1828 SilcBool create_key,
1830 const unsigned char *auth,
1831 SilcUInt32 auth_len,
1832 const unsigned char *cauth,
1833 SilcUInt32 cauth_len)
1835 SilcPacketStream sock = cmd->sock;
1836 SilcIDListData idata = silc_packet_get_context(sock);
1838 SilcUInt32 tmp_len, user_count;
1839 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4], ulimit[4];
1840 SilcClientEntry client;
1841 SilcChannelClientEntry chl;
1842 SilcBuffer reply, chidp, clidp, keyp = NULL;
1843 SilcBuffer user_list, mode_list, invite_list, ban_list;
1844 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1845 char check[512], check2[512];
1847 SilcBool founder = FALSE;
1849 SilcBuffer fkey = NULL, chpklist = NULL;
1850 const char *cipher, *hostname, *ip;
1852 SILC_LOG_DEBUG(("Joining client to channel"));
1857 silc_socket_stream_get_info(silc_packet_stream_get_stream(sock),
1858 NULL, &hostname, &ip, NULL);
1860 /* Get the client entry */
1861 if (idata->conn_type == SILC_CONN_CLIENT) {
1862 client = (SilcClientEntry)idata;
1866 client = silc_server_query_client(server, client_id, FALSE,
1869 if (!resolve || cmd->pending) {
1870 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1871 silc_server_command_send_status_data(
1872 cmd, SILC_COMMAND_JOIN,
1873 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0,
1878 /* The client info is being resolved. Reprocess this packet after
1879 receiving the reply to the query. */
1880 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1882 silc_server_command_join,
1883 silc_server_command_dup(cmd));
1884 cmd->pending = TRUE;
1888 if (!client->data.public_key &&
1889 (auth || cauth || channel->ban_list ||
1890 (channel->mode & SILC_CHANNEL_MODE_INVITE))) {
1891 if (cmd->pending == 2)
1894 /* We must retrieve the client's public key by sending
1895 GETKEY command. Reprocess this packet after receiving the key */
1896 clidp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
1897 silc_server_send_command(server, cmd->sock,
1898 SILC_COMMAND_GETKEY, ++server->cmd_ident,
1899 1, 1, clidp->data, silc_buffer_len(clidp));
1900 silc_buffer_free(clidp);
1901 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
1903 silc_server_command_join,
1904 silc_server_command_dup(cmd));
1909 cmd->pending = FALSE;
1913 * Check founder auth payload if provided. If client can gain founder
1914 * privileges it can override various conditions on joining the channel,
1915 * and can have directly the founder mode set on the channel.
1917 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1918 SilcIDListData idata = (SilcIDListData)client;
1919 SilcChannelClientEntry chl2;
1920 SilcHashTableList htl;
1922 if (channel->founder_key && idata->public_key &&
1923 silc_pkcs_public_key_compare(channel->founder_key,
1924 idata->public_key)) {
1925 /* Check whether the client is to become founder */
1926 if (silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
1927 channel->founder_key, 0, server->sha1hash,
1928 client->id, SILC_ID_CLIENT)) {
1930 /* There cannot be anyone else as founder on the channel now. This
1931 client is definitely the founder due to this authentication */
1932 silc_hash_table_list(channel->user_list, &htl);
1933 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
1934 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
1935 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
1936 silc_server_force_cumode_change(server, NULL, channel, chl2,
1940 silc_hash_table_list_reset(&htl);
1942 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
1949 * Check channel modes
1953 memset(check, 0, sizeof(check));
1954 memset(check2, 0, sizeof(check2));
1955 silc_strncat(check, sizeof(check),
1956 client->nickname, strlen(client->nickname));
1957 silc_strncat(check, sizeof(check), "!", 1);
1958 silc_strncat(check, sizeof(check),
1959 client->username, strlen(client->username));
1960 if (!strchr(client->username, '@')) {
1961 silc_strncat(check, sizeof(check), "@", 1);
1962 silc_strncat(check, sizeof(check),
1963 hostname, strlen(hostname));
1966 silc_strncat(check2, sizeof(check2),
1967 client->nickname, strlen(client->nickname));
1968 if (!strchr(client->nickname, '@')) {
1969 silc_strncat(check2, sizeof(check2), "@", 1);
1970 silc_strncat(check2, sizeof(check2),
1971 SILC_IS_LOCAL(client) ? server->server_name :
1972 client->router->server_name,
1973 SILC_IS_LOCAL(client) ? strlen(server->server_name) :
1974 strlen(client->router->server_name));
1976 silc_strncat(check2, sizeof(check2), "!", 1);
1977 silc_strncat(check2, sizeof(check2),
1978 client->username, strlen(client->username));
1979 if (!strchr(client->username, '@')) {
1980 silc_strncat(check2, sizeof(check2), "@", 1);
1981 silc_strncat(check2, sizeof(check2),
1982 hostname, strlen(hostname));
1985 /* Check invite list if channel is invite-only channel */
1986 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1987 if (!channel->invite_list ||
1988 !silc_hash_table_count(channel->invite_list) ||
1989 (!silc_server_inviteban_match(server, channel->invite_list,
1991 !silc_server_inviteban_match(server, channel->invite_list,
1992 2, client->data.public_key) &&
1993 !silc_server_inviteban_match(server, channel->invite_list,
1994 1, client->nickname) &&
1995 !silc_server_inviteban_match(server, channel->invite_list,
1997 !silc_server_inviteban_match(server, channel->invite_list,
1999 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2000 silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
2001 SILC_STATUS_ERR_NOT_INVITED, 0,
2003 silc_buffer_len(chidp));
2004 silc_buffer_free(chidp);
2009 /* Check ban list if it exists. If the client's nickname, server,
2010 username and/or hostname is in the ban list the access to the
2011 channel is denied. */
2012 if (channel->ban_list && silc_hash_table_count(channel->ban_list)) {
2013 if (silc_server_inviteban_match(server, channel->ban_list,
2015 silc_server_inviteban_match(server, channel->ban_list,
2016 2, client->data.public_key) ||
2017 silc_server_inviteban_match(server, channel->ban_list,
2018 1, client->nickname) ||
2019 silc_server_inviteban_match(server, channel->ban_list,
2021 silc_server_inviteban_match(server, channel->ban_list,
2023 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2024 silc_server_command_send_status_data(
2025 cmd, SILC_COMMAND_JOIN,
2026 SILC_STATUS_ERR_BANNED_FROM_CHANNEL, 0,
2028 silc_buffer_len(chidp));
2029 silc_buffer_free(chidp);
2034 /* Check user count limit if set. */
2035 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
2036 if (silc_hash_table_count(channel->user_list) + 1 >
2037 channel->user_limit) {
2038 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2039 silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
2040 SILC_STATUS_ERR_CHANNEL_IS_FULL,
2042 silc_buffer_len(chidp));
2043 silc_buffer_free(chidp);
2049 /* Check the channel passphrase if set. */
2050 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2051 /* Get passphrase */
2052 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2054 passphrase = silc_memdup(tmp, tmp_len);
2056 if (!passphrase || !channel->passphrase ||
2057 strlen(channel->passphrase) != strlen(passphrase) ||
2058 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
2059 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2060 silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
2061 SILC_STATUS_ERR_BAD_PASSWORD, 0,
2063 silc_buffer_len(chidp));
2064 silc_buffer_free(chidp);
2069 /* Verify channel authentication with channel public keys if set. */
2070 if (channel->mode & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
2071 if (!silc_server_verify_channel_auth(server, channel, client->id,
2072 cauth, cauth_len)) {
2073 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2074 SILC_STATUS_ERR_PERM_DENIED, 0);
2080 * Client is allowed to join to the channel. Make it happen.
2083 /* Check whether the client already is on the channel */
2084 if (silc_server_client_on_channel(client, channel, NULL)) {
2085 clidp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
2086 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2087 silc_server_command_send_status_data2(cmd, SILC_COMMAND_JOIN,
2088 SILC_STATUS_ERR_USER_ON_CHANNEL, 0,
2090 silc_buffer_len(clidp),
2092 silc_buffer_len(chidp));
2093 silc_buffer_free(clidp);
2094 silc_buffer_free(chidp);
2098 /* Generate new channel key as protocol dictates */
2100 if (!silc_server_create_channel_key(server, channel, 0))
2103 /* Send the channel key. This is broadcasted to the channel but is not
2104 sent to the client who is joining to the channel. */
2105 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
2106 silc_server_send_channel_key(server, NULL, channel,
2107 server->server_type == SILC_ROUTER ?
2108 FALSE : !server->standalone);
2111 /* Join the client to the channel by adding it to channel's user list.
2112 Add also the channel to client entry's channels list for fast cross-
2114 chl = silc_calloc(1, sizeof(*chl));
2116 chl->client = client;
2117 chl->channel = channel;
2118 silc_hash_table_add(channel->user_list, client, chl);
2119 silc_hash_table_add(client->channels, channel, chl);
2120 channel->user_count++;
2121 channel->disabled = FALSE;
2123 /* Get users on the channel */
2124 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
2127 /* Encode Client ID Payload of the original client who wants to join */
2128 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2130 /* Encode command reply packet */
2131 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2132 SILC_PUT32_MSB(channel->mode, mode);
2133 SILC_PUT32_MSB(created, tmp2);
2134 SILC_PUT32_MSB(user_count, tmp3);
2135 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2136 SILC_PUT32_MSB(channel->user_limit, ulimit);
2138 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
2139 unsigned char cid[32];
2141 silc_id_id2str(channel->id, SILC_ID_CHANNEL, cid, sizeof(cid), &cid_len);
2142 cipher = silc_cipher_get_name(channel->send_key);
2143 keyp = silc_channel_key_payload_encode(cid_len, cid,
2144 strlen(cipher), cipher,
2145 channel->key_len / 8, channel->key);
2148 if (channel->founder_key)
2149 fkey = silc_public_key_payload_encode(channel->founder_key);
2151 /* Encode invite list */
2153 if (channel->invite_list && silc_hash_table_count(channel->invite_list)) {
2154 SilcHashTableList htl;
2156 invite_list = silc_buffer_alloc_size(2);
2157 silc_buffer_format(invite_list,
2158 SILC_STR_UI_SHORT(silc_hash_table_count(
2159 channel->invite_list)),
2162 silc_hash_table_list(channel->invite_list, &htl);
2163 while (silc_hash_table_get(&htl, (void *)&plen, (void *)&reply))
2164 invite_list = silc_argument_payload_encode_one(invite_list,
2166 silc_buffer_len(reply),
2167 SILC_PTR_TO_32(plen));
2168 silc_hash_table_list_reset(&htl);
2171 /* Encode ban list */
2173 if (channel->ban_list && silc_hash_table_count(channel->ban_list)) {
2174 SilcHashTableList htl;
2176 ban_list = silc_buffer_alloc_size(2);
2177 silc_buffer_format(ban_list,
2178 SILC_STR_UI_SHORT(silc_hash_table_count(
2179 channel->ban_list)),
2182 silc_hash_table_list(channel->ban_list, &htl);
2183 while (silc_hash_table_get(&htl, (void *)&plen, (void *)&reply))
2184 ban_list = silc_argument_payload_encode_one(ban_list,
2186 silc_buffer_len(reply),
2187 SILC_PTR_TO_32(plen));
2188 silc_hash_table_list_reset(&htl);
2191 if (channel->channel_pubkeys)
2192 chpklist = silc_server_get_channel_pk_list(server, channel, FALSE, FALSE);
2195 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2196 SILC_STATUS_OK, 0, ident, 16,
2197 2, channel->channel_name,
2198 strlen(channel->channel_name),
2200 silc_buffer_len(chidp),
2202 silc_buffer_len(clidp),
2205 7, keyp ? keyp->data : NULL,
2206 keyp ? silc_buffer_len(keyp) : 0,
2207 8, ban_list ? ban_list->data : NULL,
2209 silc_buffer_len(ban_list): 0,
2210 9, invite_list ? invite_list->data :
2213 silc_buffer_len(invite_list) : 0,
2216 strlen(channel->topic) : 0,
2217 11, silc_hmac_get_name(channel->hmac),
2218 strlen(silc_hmac_get_name(channel->
2221 13, user_list->data,
2222 silc_buffer_len(user_list),
2223 14, mode_list->data,
2224 silc_buffer_len(mode_list),
2225 15, fkey ? fkey->data : NULL,
2226 fkey ? silc_buffer_len(fkey) : 0,
2227 16, chpklist ? chpklist->data : NULL,
2228 chpklist ? silc_buffer_len(chpklist) : 0,
2229 17, (channel->mode &
2230 SILC_CHANNEL_MODE_ULIMIT ?
2233 SILC_CHANNEL_MODE_ULIMIT ?
2234 sizeof(ulimit) : 0));
2236 /* Send command reply */
2237 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
2238 reply->data, silc_buffer_len(reply));
2241 cmd->server->stat.commands_sent++;
2243 /* Send JOIN notify to locally connected clients on the channel. If
2244 we are normal server then router will send or have sent JOIN notify
2245 already. However since we've added the client already to our channel
2246 we'll ignore it (in packet_receive.c) so we must send it here. If
2247 we are router then this will send it to local clients and local
2249 SILC_LOG_DEBUG(("Send JOIN notify to channel"));
2250 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
2251 SILC_NOTIFY_TYPE_JOIN, 2,
2252 clidp->data, silc_buffer_len(clidp),
2253 chidp->data, silc_buffer_len(chidp));
2255 /* Update statistics */
2256 server->stat.my_chanclients++;
2257 if (server->server_type == SILC_ROUTER) {
2258 server->stat.cell_chanclients++;
2259 server->stat.chanclients++;
2262 if (!cmd->pending) {
2263 /* Send JOIN notify packet to our primary router */
2264 silc_server_send_notify_join(server, SILC_PRIMARY_ROUTE(server),
2265 SILC_BROADCAST(server), channel, client->id);
2268 /* Distribute the channel key to all backup routers. */
2269 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
2270 keyp->data, silc_buffer_len(keyp), FALSE, TRUE);
2272 /* If client became founder by providing correct founder auth data
2273 notify the mode change to the channel. */
2275 SILC_PUT32_MSB(chl->mode, mode);
2276 SILC_LOG_DEBUG(("Send CUMODE_CHANGE notify to channel"));
2277 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
2278 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
2280 silc_buffer_len(clidp),
2281 mode, 4, clidp->data,
2282 silc_buffer_len(clidp),
2283 fkey ? fkey->data : NULL,
2284 fkey ? silc_buffer_len(fkey) : 0);
2288 /* Set CUMODE notify type to network */
2290 silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
2291 SILC_BROADCAST(server), channel,
2292 chl->mode, client->id, SILC_ID_CLIENT,
2293 client->id, channel->founder_key);
2295 silc_buffer_free(reply);
2296 silc_buffer_free(clidp);
2297 silc_buffer_free(chidp);
2298 silc_buffer_free(keyp);
2299 silc_buffer_free(user_list);
2300 silc_buffer_free(mode_list);
2301 silc_buffer_free(fkey);
2302 silc_buffer_free(chpklist);
2303 silc_buffer_free(invite_list);
2304 silc_buffer_free(ban_list);
2308 memset(passphrase, 0, strlen(passphrase));
2309 silc_free(passphrase);
2312 /* Server side of command JOIN. Joins client into requested channel. If
2313 the channel does not exist it will be created. */
2315 void silc_server_command_join_connected(SilcServer server,
2316 SilcServerEntry server_entry,
2319 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2321 if (!server_entry) {
2323 unsigned char *tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2326 SILC_LOG_DEBUG(("Connecting to router failed"));
2327 silc_parse_userfqdn(tmp, NULL, 0, serv, sizeof(serv));
2330 silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
2331 SILC_STATUS_ERR_NO_SUCH_SERVER, 0,
2332 2, serv, strlen(serv));
2334 silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
2335 SILC_STATUS_ERR_NO_SUCH_CHANNEL, 0,
2338 silc_server_command_free(cmd);
2342 /* Reprocess command */
2343 SILC_LOG_DEBUG(("Reprocess JOIN after connecting to router"));
2344 silc_server_command_join(cmd, NULL);
2347 SILC_SERVER_CMD_FUNC(join)
2349 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2350 SilcServer server = cmd->server;
2351 SilcIDListData idata = silc_packet_get_context(cmd->sock);
2352 unsigned char *auth, *cauth;
2353 SilcUInt32 tmp_len, auth_len, cauth_len;
2354 char *tmp, *channel_name, *channel_namec = NULL, *cipher, *hmac;
2355 char parsed[256 + 1], serv[256 + 1];
2356 SilcChannelEntry channel;
2357 SilcUInt32 umode = 0;
2358 SilcBool created = FALSE, create_key = TRUE;
2361 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 7);
2363 /* Get channel name */
2364 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2366 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2367 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2372 /* Truncate over long channel names */
2373 if (tmp_len > 256) {
2375 tmp[tmp_len - 1] = '\0';
2378 /* Parse server name from the channel name */
2379 silc_parse_userfqdn(tmp, parsed, sizeof(parsed), serv,
2381 channel_name = parsed;
2383 if (server->config->dynamic_server) {
2384 /* If server name is not specified but local channels is FALSE then the
2385 channel will be global, based on our router name. */
2386 if (!serv[0] && !server->config->local_channels) {
2387 if (!server->standalone) {
2388 silc_snprintf(serv, sizeof(serv), "%s", server->router->server_name);
2390 SilcServerConfigRouter *router;
2391 router = silc_server_config_get_primary_router(server);
2393 /* Create connection to primary router */
2394 SILC_LOG_DEBUG(("Create dynamic connection to primary router %s:%d",
2395 router->host, router->port));
2396 silc_server_create_connection(server, FALSE, TRUE,
2397 router->host, router->port,
2398 silc_server_command_join_connected,
2405 /* If server name is ours, ignore it. */
2406 if (serv[0] && silc_utf8_strcasecmp(serv, server->server_name))
2407 memset(serv, 0, sizeof(serv));
2409 /* Create connection */
2410 if (serv[0] && server->standalone) {
2411 SilcServerConfigRouter *router;
2412 router = silc_server_config_get_primary_router(server);
2414 /* Create connection to primary router */
2415 SILC_LOG_DEBUG(("Create dynamic connection to primary router %s:%d",
2416 router->host, router->port));
2417 silc_server_create_connection(server, FALSE, TRUE,
2418 router->host, router->port,
2419 silc_server_command_join_connected, cmd);
2425 /* Check for valid channel name. This is cached, the original is saved
2426 in the channel context. */
2427 channel_namec = silc_channel_name_check(channel_name, strlen(channel_name),
2428 SILC_STRING_UTF8, 256, NULL);
2429 if (!channel_namec) {
2430 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2431 SILC_STATUS_ERR_BAD_CHANNEL, 0);
2435 /* Get Client ID of the client who is joining to the channel */
2436 if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL)) {
2437 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2438 SILC_STATUS_ERR_NO_CLIENT_ID,
2442 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2444 /* Get cipher, hmac name and auth payload */
2445 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2446 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2447 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
2448 cauth = silc_argument_get_arg_type(cmd->args, 7, &cauth_len);
2450 /* See if the channel exists */
2451 channel = silc_idlist_find_channel_by_name(server->local_list,
2452 channel_namec, NULL);
2454 if (idata->conn_type == SILC_CONN_CLIENT) {
2455 SilcClientEntry entry = (SilcClientEntry)idata;
2457 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2458 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2463 #ifndef SILC_DIST_INPLACE
2464 /* Limit how many channels client can join */
2465 if (!cmd->pending && entry->channels &&
2466 silc_hash_table_count(entry->channels) >=
2467 server->config->param.chlimit) {
2468 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2469 SILC_STATUS_ERR_RESOURCE_LIMIT,
2473 #endif /* SILC_DIST_INPLACE */
2476 (channel->disabled && server->server_type != SILC_ROUTER)) {
2477 /* Channel not found or not valid */
2479 /* If we are standalone server we don't have a router, we just create
2480 the channel by ourselves (unless it existed). */
2481 if (server->standalone) {
2483 channel = silc_server_create_new_channel(server, server->id, cipher,
2484 hmac, channel_name, TRUE);
2487 silc_server_command_send_status_data(
2488 cmd, SILC_COMMAND_JOIN,
2489 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
2490 0, 2, cipher, strlen(cipher));
2492 silc_server_command_send_status_data(
2493 cmd, SILC_COMMAND_JOIN,
2494 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
2495 0, 2, hmac, strlen(hmac));
2497 silc_server_command_send_status_reply(
2498 cmd, SILC_COMMAND_JOIN,
2499 SILC_STATUS_ERR_RESOURCE_LIMIT,
2505 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2511 /* The channel does not exist on our server. If we are normal server
2512 we will send JOIN command to our router which will handle the
2513 joining procedure (either creates the channel if it doesn't exist
2514 or joins the client to it). */
2515 if (server->server_type != SILC_ROUTER) {
2517 SilcUInt16 old_ident;
2519 /* If this is pending command callback then we've resolved
2520 it and it didn't work, return since we've notified the
2521 client already in the command reply callback. */
2526 cmd->server->stat.commands_sent++;
2528 old_ident = silc_command_get_ident(cmd->payload);
2529 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2530 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2532 /* Send JOIN command to our router */
2533 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
2534 SILC_PACKET_COMMAND, cmd->packet->flags,
2535 tmpbuf->data, silc_buffer_len(tmpbuf));
2537 /* Reprocess this packet after received reply from router */
2538 silc_server_command_pending(server, SILC_COMMAND_JOIN,
2539 silc_command_get_ident(cmd->payload),
2540 silc_server_command_join,
2541 silc_server_command_dup(cmd));
2542 cmd->pending = TRUE;
2543 silc_command_set_ident(cmd->payload, old_ident);
2544 silc_buffer_free(tmpbuf);
2548 /* We are router and the channel does not seem exist so we will check
2549 our global list as well for the channel. */
2550 channel = silc_idlist_find_channel_by_name(server->global_list,
2551 channel_namec, NULL);
2553 /* Channel really does not exist, create it */
2554 channel = silc_server_create_new_channel(server, server->id, cipher,
2555 hmac, channel_name, TRUE);
2558 silc_server_command_send_status_data(
2559 cmd, SILC_COMMAND_JOIN,
2560 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
2561 0, 2, cipher, strlen(cipher));
2563 silc_server_command_send_status_data(
2564 cmd, SILC_COMMAND_JOIN,
2565 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
2566 0, 2, hmac, strlen(hmac));
2568 silc_server_command_send_status_reply(
2569 cmd, SILC_COMMAND_JOIN,
2570 SILC_STATUS_ERR_RESOURCE_LIMIT,
2576 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2584 /* Channel not found */
2586 /* If the command came from router and we are normal server then
2587 something went wrong with the joining as the channel was not found.
2588 We can't do anything else but ignore this. */
2589 if (idata->conn_type == SILC_CONN_ROUTER ||
2590 server->server_type != SILC_ROUTER)
2593 /* We are router and the channel does not seem exist so we will check
2594 our global list as well for the channel. */
2595 channel = silc_idlist_find_channel_by_name(server->global_list,
2596 channel_namec, NULL);
2598 /* Channel really does not exist, create it */
2599 channel = silc_server_create_new_channel(server, server->id, cipher,
2600 hmac, channel_name, TRUE);
2603 silc_server_command_send_status_data(
2604 cmd, SILC_COMMAND_JOIN,
2605 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
2606 0, 2, cipher, strlen(cipher));
2608 silc_server_command_send_status_data(
2609 cmd, SILC_COMMAND_JOIN,
2610 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
2611 0, 2, hmac, strlen(hmac));
2613 silc_server_command_send_status_reply(
2614 cmd, SILC_COMMAND_JOIN,
2615 SILC_STATUS_ERR_RESOURCE_LIMIT,
2621 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2628 /* Check whether the channel was created by our router */
2629 if (cmd->pending && context2) {
2630 SilcServerCommandReplyContext reply = context2;
2632 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
2633 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
2634 SILC_GET32_MSB(created, tmp);
2635 if (silc_argument_get_arg_type(reply->args, 7, NULL))
2636 create_key = FALSE; /* Router returned the key already */
2638 if (silc_command_get_status(reply->payload, NULL, NULL) &&
2639 channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2640 /* Save channel passphrase, if user provided it successfully */
2643 pa = silc_argument_get_arg_type(cmd->args, 3, &pa_len);
2645 silc_free(channel->passphrase);
2646 channel->passphrase = silc_memdup(pa, pa_len);
2651 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
2652 !channel->disabled && !silc_hash_table_count(channel->user_list))
2656 /* If the channel does not have global users and is also empty the client
2657 will be the channel founder and operator. */
2658 if (!channel->disabled &&
2659 !channel->global_users && !silc_hash_table_count(channel->user_list))
2660 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2662 /* Join to the channel */
2663 silc_server_command_join_channel(server, cmd, channel, SILC_ID_GET_ID(id),
2664 created, create_key, umode,
2665 auth, auth_len, cauth, cauth_len);
2668 silc_free(channel_namec);
2669 silc_server_command_free(cmd);
2672 /* Server side of command MOTD. Sends server's current "message of the
2673 day" to the client. */
2675 SILC_SERVER_CMD_FUNC(motd)
2677 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2678 SilcServer server = cmd->server;
2680 char *motd, *dest_server = NULL;
2681 SilcUInt32 motd_len;
2682 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2684 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
2686 /* Get server name */
2687 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2689 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2690 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2695 /* Check server name */
2696 dest_server = silc_identifier_check(dest_server, strlen(dest_server),
2697 SILC_STRING_UTF8, 256, NULL);
2699 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2700 SILC_STATUS_ERR_BAD_SERVER,
2705 if (!memcmp(dest_server, server->server_name, strlen(dest_server))) {
2708 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
2710 if (server->config && server->config->server_info &&
2711 server->config->server_info->motd_file) {
2713 motd = silc_file_readfile(server->config->server_info->motd_file,
2717 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_MOTD,
2718 SILC_STATUS_OK, 0, ident, 1,
2719 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, 2,
2726 2, idp->data, silc_buffer_len(idp),
2730 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_MOTD,
2731 SILC_STATUS_OK, 0, ident, 1,
2732 2, idp->data, silc_buffer_len(idp));
2734 silc_buffer_free(idp);
2736 SilcServerEntry entry;
2738 /* Check whether we have this server cached */
2739 entry = silc_idlist_find_server_by_name(server->global_list,
2740 dest_server, TRUE, NULL);
2742 entry = silc_idlist_find_server_by_name(server->local_list,
2743 dest_server, TRUE, NULL);
2746 if (server->server_type != SILC_SERVER && !cmd->pending &&
2747 entry && !entry->motd) {
2748 /* Send to the server */
2750 SilcUInt16 old_ident;
2753 cmd->server->stat.commands_sent++;
2755 old_ident = silc_command_get_ident(cmd->payload);
2756 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2757 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2759 silc_server_packet_send(server, entry->connection,
2760 SILC_PACKET_COMMAND, cmd->packet->flags,
2761 tmpbuf->data, silc_buffer_len(tmpbuf));
2763 /* Reprocess this packet after received reply from router */
2764 silc_server_command_pending(server, SILC_COMMAND_MOTD,
2765 silc_command_get_ident(cmd->payload),
2766 silc_server_command_motd,
2767 silc_server_command_dup(cmd));
2768 cmd->pending = TRUE;
2769 silc_command_set_ident(cmd->payload, old_ident);
2770 silc_buffer_free(tmpbuf);
2774 /* Send to primary router only if we don't know the server
2775 * the client requested or if the server is not locally connected */
2776 if ((!entry || !(entry->data.status & SILC_IDLIST_STATUS_LOCAL))
2777 && !cmd->pending && !server->standalone) {
2778 /* Send to the primary router */
2780 SilcUInt16 old_ident;
2783 cmd->server->stat.commands_sent++;
2785 old_ident = silc_command_get_ident(cmd->payload);
2786 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2787 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2789 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
2790 SILC_PACKET_COMMAND, cmd->packet->flags,
2791 tmpbuf->data, silc_buffer_len(tmpbuf));
2793 /* Reprocess this packet after received reply from router */
2794 silc_server_command_pending(server, SILC_COMMAND_MOTD,
2795 silc_command_get_ident(cmd->payload),
2796 silc_server_command_motd,
2797 silc_server_command_dup(cmd));
2798 cmd->pending = TRUE;
2799 silc_command_set_ident(cmd->payload, old_ident);
2800 silc_buffer_free(tmpbuf);
2805 silc_free(dest_server);
2806 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2807 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2808 SILC_STATUS_ERR_NO_SUCH_SERVER, 0,
2810 strlen(dest_server));
2815 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2816 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_MOTD,
2817 SILC_STATUS_OK, 0, ident, 2,
2818 2, idp->data, silc_buffer_len(idp),
2821 strlen(entry->motd) : 0);
2822 silc_buffer_free(idp);
2826 silc_free(dest_server);
2827 silc_server_command_free(cmd);
2830 /* Server side of command UMODE. Client can use this command to set/unset
2831 user mode. Client actually cannot set itself to be as server/router
2832 operator so this can be used only to unset the modes. */
2834 SILC_SERVER_CMD_FUNC(umode)
2836 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2837 SilcServer server = cmd->server;
2838 SilcClientEntry client = silc_packet_get_context(cmd->sock);
2839 unsigned char *tmp_mask, m[4];
2840 SilcUInt32 mask = 0, tmp_len;
2841 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2842 SilcBool set_mask = FALSE;
2844 if (client->data.conn_type != SILC_CONN_CLIENT || !client)
2847 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2);
2849 /* Get the client's mode mask */
2850 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2851 if (tmp_mask && tmp_len == 4) {
2852 SILC_GET32_MSB(mask, tmp_mask);
2857 /* Check that mode changing is allowed. */
2858 if (!silc_server_check_umode_rights(server, client, mask)) {
2859 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2860 SILC_STATUS_ERR_PERM_DENIED, 0);
2864 /* Anonymous mode cannot be set by client */
2865 if (mask & SILC_UMODE_ANONYMOUS &&
2866 !(client->mode & SILC_UMODE_ANONYMOUS)) {
2867 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2868 SILC_STATUS_ERR_PERM_DENIED, 0);
2872 /* Update statistics */
2873 if (mask & SILC_UMODE_GONE) {
2874 if (!(client->mode & SILC_UMODE_GONE))
2875 server->stat.my_aways++;
2877 if (client->mode & SILC_UMODE_GONE)
2878 server->stat.my_aways--;
2881 /* If the client has anonymous mode set, preserve it. */
2882 if (client->mode & SILC_UMODE_ANONYMOUS)
2883 mask |= SILC_UMODE_ANONYMOUS;
2885 /* Change the mode */
2886 client->mode = mask;
2888 /* Send UMODE change to primary router */
2889 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
2890 SILC_BROADCAST(server), client->id,
2893 /* Check if anyone is watching this nickname */
2894 if (server->server_type == SILC_ROUTER)
2895 silc_server_check_watcher_list(server, client, NULL,
2896 SILC_NOTIFY_TYPE_UMODE_CHANGE);
2899 /* Send command reply to sender */
2900 SILC_PUT32_MSB(client->mode, m);
2901 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_UMODE,
2902 SILC_STATUS_OK, 0, ident, 1,
2906 silc_server_command_free(cmd);
2909 /* Server side command of CMODE. Changes channel mode */
2911 SILC_SERVER_CMD_FUNC(cmode)
2913 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2914 SilcServer server = cmd->server;
2915 SilcClientEntry client = silc_packet_get_context(cmd->sock);
2916 SilcIDListData idata = (SilcIDListData)client;
2918 SilcChannelEntry channel;
2919 SilcChannelClientEntry chl;
2921 unsigned char *tmp, *tmp_id, *tmp_mask, *chpkdata = NULL;
2922 char *cipher = NULL, *hmac = NULL, *passphrase = NULL, ulimit[4];
2923 SilcUInt32 mode_mask = 0, old_mask = 0, tmp_len, tmp_len2, chpklen;
2924 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2925 SilcBool set_mask = FALSE, set_chpk = FALSE;
2926 SilcPublicKey founder_key = NULL;
2927 SilcBuffer fkey = NULL, chpklist = NULL;
2928 SilcBufferStruct chpk;
2931 silc_server_command_free(cmd);
2935 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 9);
2937 /* Get Channel ID */
2938 if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
2939 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2940 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2941 silc_server_command_free(cmd);
2945 /* Get channel entry */
2946 channel = silc_idlist_find_channel_by_id(server->local_list,
2947 SILC_ID_GET_ID(id), NULL);
2949 channel = silc_idlist_find_channel_by_id(server->global_list,
2950 SILC_ID_GET_ID(id), NULL);
2952 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2953 silc_server_command_send_status_data(cmd, SILC_COMMAND_CMODE,
2954 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
2955 0, 2, tmp_id, tmp_len2);
2956 silc_server_command_free(cmd);
2960 old_mask = channel->mode;
2962 /* Get the channel mode mask */
2963 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2964 if (tmp_mask && tmp_len == 4) {
2965 SILC_GET32_MSB(mode_mask, tmp_mask);
2969 /* Check whether this client is on the channel */
2970 if (!silc_server_client_on_channel(client, channel, &chl)) {
2971 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2972 silc_server_command_send_status_data(cmd, SILC_COMMAND_CMODE,
2973 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
2974 2, tmp_id, tmp_len2);
2978 /* Check that client has rights to change any requested channel modes */
2979 if (set_mask && !silc_server_check_cmode_rights(server, channel, chl,
2981 SILC_LOG_DEBUG(("Client does not have rights to change mode"));
2982 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2983 silc_server_command_send_status_data(
2984 cmd, SILC_COMMAND_CMODE,
2985 (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) ?
2986 SILC_STATUS_ERR_NO_CHANNEL_PRIV :
2987 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV), 0,
2988 2, tmp_id, tmp_len2);
2992 /* If mode mask was not sent as argument then merely return the current
2993 mode mask, founder key and channel public key list to the sender. */
2996 SILC_PUT32_MSB(channel->mode, m);
2997 if (channel->founder_key)
2998 fkey = silc_public_key_payload_encode(channel->founder_key);
2999 if (channel->channel_pubkeys)
3000 chpklist = silc_server_get_channel_pk_list(server, channel,
3002 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3003 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_CMODE,
3004 SILC_STATUS_OK, 0, ident, 4,
3005 2, tmp_id, tmp_len2,
3007 4, fkey ? fkey->data : NULL,
3008 fkey ? silc_buffer_len(fkey) : 0,
3009 5, chpklist ? chpklist->data : NULL,
3010 chpklist ? silc_buffer_len(chpklist) : 0);
3015 * Check the modes. Modes that requires nothing special operation are
3019 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3020 /* Channel uses private keys to protect traffic. Client(s) has set the
3021 key locally they want to use, server does not know that key. */
3022 /* Nothing interesting to do here */
3024 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3025 /* The mode is removed and we need to generate and distribute
3026 new channel key. Clients are not using private channel keys
3027 anymore after this. */
3029 /* if we don't remove the flag from the mode
3030 * silc_server_create_channel_key won't create a new key */
3031 channel->mode &= ~SILC_CHANNEL_MODE_PRIVKEY;
3033 /* Re-generate channel key */
3034 if (!silc_server_create_channel_key(server, channel, 0))
3037 /* Send the channel key. This sends it to our local clients and if
3038 we are normal server to our router as well. */
3039 silc_server_send_channel_key(server, NULL, channel,
3040 server->server_type == SILC_ROUTER ?
3041 FALSE : !server->standalone);
3043 cipher = (char *)silc_cipher_get_name(channel->send_key);
3044 hmac = (char *)silc_hmac_get_name(channel->hmac);
3048 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3049 /* User limit is set on channel */
3050 SilcUInt32 user_limit;
3052 /* Get user limit */
3053 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3055 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3056 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3057 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3061 SILC_GET32_MSB(user_limit, tmp);
3062 channel->user_limit = user_limit;
3065 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3066 /* User limit mode is unset. Remove user limit */
3067 channel->user_limit = 0;
3070 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3071 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3072 /* Passphrase has been set to channel */
3074 /* Get the passphrase */
3075 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3077 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3078 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3082 /* Save the passphrase */
3083 passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
3086 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3087 /* Passphrase mode is unset. remove the passphrase */
3088 silc_free(channel->passphrase);
3089 channel->passphrase = NULL;
3093 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3094 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3095 /* Cipher to use protect the traffic */
3096 SilcCipher send_key, receive_key, olds, oldr;
3099 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3101 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3102 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3106 /* Delete old cipher and allocate the new one */
3107 if (!silc_cipher_alloc(cipher, &send_key)) {
3108 silc_server_command_send_status_data(
3109 cmd, SILC_COMMAND_CMODE,
3110 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
3111 2, cipher, strlen(cipher));
3114 if (!silc_cipher_alloc(cipher, &receive_key)) {
3115 silc_server_command_send_status_data(
3116 cmd, SILC_COMMAND_CMODE,
3117 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
3118 2, cipher, strlen(cipher));
3122 olds = channel->send_key;
3123 oldr = channel->receive_key;
3124 channel->send_key = send_key;
3125 channel->receive_key = receive_key;
3127 /* Re-generate channel key */
3128 if (!silc_server_create_channel_key(server, channel, 0)) {
3129 /* We don't have new key, revert to old one */
3130 channel->send_key = olds;
3131 channel->receive_key = oldr;
3135 /* Remove old channel key for good */
3136 silc_cipher_free(olds);
3137 silc_cipher_free(oldr);
3139 /* Send the channel key. This sends it to our local clients and if
3140 we are normal server to our router as well. */
3141 silc_server_send_channel_key(server, NULL, channel,
3142 server->server_type == SILC_ROUTER ?
3143 FALSE : !server->standalone);
3146 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3147 /* Cipher mode is unset. Remove the cipher and revert back to
3149 SilcCipher send_key, receive_key, olds, oldr;
3150 cipher = channel->cipher;
3152 /* Delete old cipher and allocate default one */
3153 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER,
3155 silc_server_command_send_status_data(
3156 cmd, SILC_COMMAND_CMODE,
3157 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
3158 2, cipher, strlen(cipher));
3161 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER,
3163 silc_server_command_send_status_data(
3164 cmd, SILC_COMMAND_CMODE,
3165 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
3166 2, cipher, strlen(cipher));
3170 olds = channel->send_key;
3171 oldr = channel->receive_key;
3172 channel->send_key = send_key;
3173 channel->receive_key = receive_key;
3175 /* Re-generate channel key */
3176 if (!silc_server_create_channel_key(server, channel, 0)) {
3177 /* We don't have new key, revert to old one */
3178 channel->send_key = olds;
3179 channel->receive_key = oldr;
3183 /* Remove old channel key for good */
3184 silc_cipher_free(olds);
3185 silc_cipher_free(oldr);
3187 /* Send the channel key. This sends it to our local clients and if
3188 we are normal server to our router as well. */
3189 silc_server_send_channel_key(server, NULL, channel,
3190 server->server_type == SILC_ROUTER ?
3191 FALSE : !server->standalone);
3195 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3196 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3197 /* HMAC to use protect the traffic */
3198 unsigned char hash[SILC_HASH_MAXLEN];
3202 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3204 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3205 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3209 /* Delete old hmac and allocate the new one */
3210 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
3211 silc_server_command_send_status_data(
3212 cmd, SILC_COMMAND_CMODE,
3213 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
3214 2, hmac, strlen(hmac));
3218 silc_hmac_free(channel->hmac);
3219 channel->hmac = newhmac;
3221 /* Set the HMAC key out of current channel key. The client must do
3223 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
3224 channel->key_len / 8, hash);
3225 silc_hmac_set_key(channel->hmac, hash,
3226 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3227 memset(hash, 0, sizeof(hash));
3230 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
3231 /* Hmac mode is unset. Remove the hmac and revert back to
3234 unsigned char hash[SILC_HASH_MAXLEN];
3235 hmac = channel->hmac_name;
3237 /* Delete old hmac and allocate default one */
3238 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
3239 silc_server_command_send_status_data(
3240 cmd, SILC_COMMAND_CMODE,
3241 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
3242 2, hmac, strlen(hmac));
3246 silc_hmac_free(channel->hmac);
3247 channel->hmac = newhmac;
3249 /* Set the HMAC key out of current channel key. The client must do
3251 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
3252 channel->key_len / 8,
3254 silc_hmac_set_key(channel->hmac, hash,
3255 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3256 memset(hash, 0, sizeof(hash));
3260 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3261 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3262 /* Check if the founder public key was received */
3263 founder_key = idata->public_key;
3264 tmp = silc_argument_get_arg_type(cmd->args, 8, &tmp_len);
3266 if (!silc_public_key_payload_decode(tmp, tmp_len, &founder_key)) {
3267 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3268 SILC_STATUS_ERR_AUTH_FAILED,
3273 /* If key was not sent and the channel mode has already founder
3274 then the key was not to be changed. */
3275 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)
3279 /* Set the founder authentication */
3280 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
3282 silc_server_command_send_status_reply(
3283 cmd, SILC_COMMAND_CMODE,
3284 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3288 /* Verify the payload before setting the mode */
3289 if (!silc_auth_verify_data(tmp, tmp_len, SILC_AUTH_PUBLIC_KEY,
3290 founder_key, 0, server->sha1hash,
3291 client->id, SILC_ID_CLIENT)) {
3292 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3293 SILC_STATUS_ERR_AUTH_FAILED,
3298 /* Save the public key */
3299 if (channel->founder_key)
3300 silc_pkcs_public_key_free(channel->founder_key);
3301 if (silc_argument_get_arg_type(cmd->args, 8, NULL))
3302 channel->founder_key = founder_key;
3304 channel->founder_key = silc_pkcs_public_key_copy(founder_key);
3305 if (!channel->founder_key) {
3306 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3307 SILC_STATUS_ERR_AUTH_FAILED,
3312 fkey = silc_public_key_payload_encode(channel->founder_key);
3314 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3315 SILC_STATUS_ERR_AUTH_FAILED,
3317 silc_pkcs_public_key_free(channel->founder_key);
3318 channel->founder_key = NULL;
3323 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3324 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3325 if (channel->founder_key)
3326 silc_pkcs_public_key_free(channel->founder_key);
3327 channel->founder_key = NULL;
3333 if (mode_mask & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
3334 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3337 chpkdata = silc_argument_get_arg_type(cmd->args, 9, &chpklen);
3339 if (!chpkdata && channel->mode & SILC_CHANNEL_MODE_CHANNEL_AUTH)
3344 /* Process the channel public key(s) */
3345 st = silc_server_set_channel_pk_list(server, NULL, channel,
3347 if (st != SILC_STATUS_OK) {
3348 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE, st, 0);
3353 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3354 if (channel->mode & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
3355 if (channel->channel_pubkeys)
3356 silc_hash_table_free(channel->channel_pubkeys);
3357 channel->channel_pubkeys = NULL;
3364 /* Finally, set the mode */
3365 old_mask = channel->mode = mode_mask;
3367 /* Send CMODE_CHANGE notify. */
3368 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3369 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT)
3370 SILC_PUT32_MSB(channel->user_limit, ulimit);
3371 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
3372 SILC_NOTIFY_TYPE_CMODE_CHANGE, 8,
3373 cidp->data, silc_buffer_len(cidp),
3375 cipher, cipher ? strlen(cipher) : 0,
3376 hmac, hmac ? strlen(hmac) : 0,
3377 passphrase, passphrase ?
3378 strlen(passphrase) : 0,
3379 fkey ? fkey->data : NULL,
3380 fkey ? silc_buffer_len(fkey) : 0,
3381 chpkdata ? chpkdata : NULL,
3382 chpkdata ? chpklen : 0,
3383 mode_mask & SILC_CHANNEL_MODE_ULIMIT ?
3385 mode_mask & SILC_CHANNEL_MODE_ULIMIT ?
3386 sizeof(ulimit) : 0);
3388 /* Set CMODE notify type to network */
3389 if (chpkdata && chpklen)
3390 silc_buffer_set(&chpk, chpkdata, chpklen);
3391 silc_server_send_notify_cmode(server, SILC_PRIMARY_ROUTE(server),
3392 SILC_BROADCAST(server), channel,
3393 mode_mask, client->id, SILC_ID_CLIENT,
3394 cipher, hmac, passphrase, founder_key,
3395 chpkdata ? &chpk : NULL);
3398 chpklist = silc_server_get_channel_pk_list(server, channel, FALSE, FALSE);
3400 /* Send command reply to sender */
3401 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3402 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_CMODE,
3403 SILC_STATUS_OK, 0, ident, 5,
3404 2, tmp_id, tmp_len2,
3406 4, fkey ? fkey->data : NULL,
3407 fkey ? silc_buffer_len(fkey) : 0,
3408 5, chpklist ? chpklist->data :
3409 NULL, chpklist ? silc_buffer_len(chpklist)
3412 SILC_CHANNEL_MODE_ULIMIT ?
3415 SILC_CHANNEL_MODE_ULIMIT ?
3416 sizeof(ulimit) : 0));
3417 silc_buffer_free(cidp);
3420 channel->mode = old_mask;
3421 silc_buffer_free(chpklist);
3422 silc_buffer_free(fkey);
3423 silc_server_command_free(cmd);
3426 /* Server side of CUMODE command. Changes client's mode on a channel. */
3428 SILC_SERVER_CMD_FUNC(cumode)
3430 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3431 SilcServer server = cmd->server;
3432 SilcClientEntry client = silc_packet_get_context(cmd->sock);
3434 SilcChannelEntry channel;
3435 SilcClientEntry target_client;
3436 SilcChannelClientEntry chl;
3438 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
3439 SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
3441 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3442 SilcPublicKey founder_key = NULL;
3443 SilcBuffer fkey = NULL;
3448 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
3450 /* Get Channel ID */
3451 if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
3452 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3453 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3457 /* Get channel entry */
3458 channel = silc_idlist_find_channel_by_id(server->local_list,
3459 SILC_ID_GET_ID(id), NULL);
3461 channel = silc_idlist_find_channel_by_id(server->global_list,
3462 SILC_ID_GET_ID(id), NULL);
3464 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3465 silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3466 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
3467 0, 2, tmp_ch_id, tmp_ch_len);
3472 /* Check whether sender is on the channel */
3473 if (!silc_server_client_on_channel(client, channel, &chl)) {
3474 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3475 silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3476 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
3477 2, tmp_ch_id, tmp_ch_len);
3480 sender_mask = chl->mode;
3482 /* Get the target client's channel mode mask */
3483 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3485 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3486 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3490 SILC_GET32_MSB(target_mask, tmp_mask);
3492 /* Get target Client ID */
3493 if (!silc_argument_get_decoded(cmd->args, 3, SILC_ARGUMENT_ID, &id2, NULL)) {
3494 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3495 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
3499 /* Get target client's entry */
3500 target_client = silc_idlist_find_client_by_id(server->local_list,
3501 SILC_ID_GET_ID(id2),
3504 target_client = silc_idlist_find_client_by_id(server->global_list,
3505 SILC_ID_GET_ID(id2),
3508 if (target_client != client &&
3509 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
3510 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
3511 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3512 silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3513 SILC_STATUS_ERR_NOT_YOU, 0,
3514 2, tmp_ch_id, tmp_ch_len);
3518 /* Check whether target client is on the channel */
3519 if (target_client != client) {
3520 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
3521 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3522 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3523 silc_server_command_send_status_data2(
3524 cmd, SILC_COMMAND_CUMODE,
3525 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL, 0,
3527 3, tmp_ch_id, tmp_ch_len);
3536 /* If the target client is founder, no one else can change their mode
3538 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
3539 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3540 silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3541 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
3542 0, 2, tmp_ch_id, tmp_ch_len);
3546 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
3547 if (target_client != client) {
3548 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3549 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
3554 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
3555 /* The client tries to claim the founder rights. */
3556 unsigned char *tmp_auth;
3557 SilcUInt32 tmp_auth_len;
3558 SilcChannelClientEntry chl2;
3559 SilcHashTableList htl;
3561 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
3562 !channel->founder_key) {
3563 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3564 SILC_STATUS_ERR_AUTH_FAILED, 0);
3568 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
3570 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3571 SILC_STATUS_ERR_AUTH_FAILED, 0);
3575 /* Verify the authentication payload */
3576 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len, SILC_AUTH_PUBLIC_KEY,
3577 channel->founder_key, 0, server->sha1hash,
3578 client->id, SILC_ID_CLIENT)) {
3579 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3580 SILC_STATUS_ERR_AUTH_FAILED, 0);
3585 founder_key = channel->founder_key;
3586 fkey = silc_public_key_payload_encode(founder_key);
3588 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3589 SILC_STATUS_ERR_AUTH_FAILED, 0);
3593 /* There cannot be anyone else as founder on the channel now. This
3594 client is definitely the founder due to this authentication. This
3595 is done only on router, not on server, since server cannot know
3596 whether router will accept this mode change or not. XXX This
3597 probably shouldn't be done anymore at all, may cause problems in
3598 router-router connections too (maybe just AUTH_FAILED error should
3599 be returned). -Pekka */
3600 if (server->server_type == SILC_ROUTER) {
3601 silc_hash_table_list(channel->user_list, &htl);
3602 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
3603 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
3604 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3605 silc_server_force_cumode_change(server, NULL, channel, chl2,
3609 silc_hash_table_list_reset(&htl);
3612 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
3615 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3616 if (target_client == client) {
3617 /* Remove channel founder rights from itself */
3618 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3621 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3622 SILC_STATUS_ERR_NOT_YOU, 0);
3628 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
3629 /* Promote to operator */
3630 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3631 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3632 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3633 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3634 silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3635 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
3636 0, 2, tmp_ch_id, tmp_ch_len);
3640 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
3644 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
3645 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3646 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3647 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3648 silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3649 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
3650 0, 2, tmp_ch_id, tmp_ch_len);
3654 /* Demote to normal user */
3655 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
3660 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
3661 if (target_client != client) {
3662 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3663 SILC_STATUS_ERR_NOT_YOU, 0);
3667 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
3668 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
3672 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
3673 if (target_client != client) {
3674 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3675 SILC_STATUS_ERR_NOT_YOU, 0);
3679 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
3684 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
3685 if (target_client != client) {
3686 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3687 SILC_STATUS_ERR_NOT_YOU, 0);
3691 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)) {
3692 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
3696 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
3697 if (target_client != client) {
3698 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3699 SILC_STATUS_ERR_NOT_YOU, 0);
3703 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
3708 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
3709 if (target_client != client) {
3710 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3711 SILC_STATUS_ERR_NOT_YOU, 0);
3715 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)) {
3716 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
3720 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
3721 if (target_client != client) {
3722 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3723 SILC_STATUS_ERR_NOT_YOU, 0);
3727 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
3732 if (target_mask & SILC_CHANNEL_UMODE_QUIET) {
3733 if (!(chl->mode & SILC_CHANNEL_UMODE_QUIET)) {
3734 if (client == target_client) {
3735 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3736 SILC_STATUS_ERR_PERM_DENIED, 0);
3739 chl->mode |= SILC_CHANNEL_UMODE_QUIET;
3743 if (chl->mode & SILC_CHANNEL_UMODE_QUIET) {
3744 if (client == target_client) {
3745 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3746 SILC_STATUS_ERR_PERM_DENIED, 0);
3749 chl->mode &= ~SILC_CHANNEL_UMODE_QUIET;
3754 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3755 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3756 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3758 /* Send notify to channel, notify only if mode was actually changed. */
3760 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
3761 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
3762 idp->data, silc_buffer_len(idp),
3765 fkey ? fkey->data : NULL,
3766 fkey ? silc_buffer_len(fkey) : 0);
3768 /* Set CUMODE notify type to network */
3769 silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
3770 SILC_BROADCAST(server), channel,
3771 target_mask, client->id, SILC_ID_CLIENT,
3772 target_client->id, founder_key);
3775 /* Send command reply to sender */
3776 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_CUMODE,
3777 SILC_STATUS_OK, 0, ident, 3,
3779 3, tmp_ch_id, tmp_ch_len,
3780 4, tmp_id, tmp_len);
3781 silc_buffer_free(idp);
3784 silc_buffer_free(fkey);
3785 silc_server_command_free(cmd);
3788 /* Server side of KICK command. Kicks client out of channel. */
3790 SILC_SERVER_CMD_FUNC(kick)
3792 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3793 SilcServer server = cmd->server;
3794 SilcClientEntry client = silc_packet_get_context(cmd->sock);
3795 SilcClientEntry target_client;
3797 SilcChannelEntry channel;
3798 SilcChannelClientEntry chl;
3800 SilcUInt32 tmp_len, target_idp_len, clen;
3801 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3802 unsigned char *tmp, *comment, *target_idp;
3807 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
3809 /* Get Channel ID */
3810 if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
3811 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3812 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3816 /* Get channel entry */
3817 channel = silc_idlist_find_channel_by_id(server->local_list,
3818 SILC_ID_GET_ID(id), NULL);
3820 channel = silc_idlist_find_channel_by_id(server->local_list,
3821 SILC_ID_GET_ID(id), NULL);
3823 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3824 silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3825 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
3826 0, 2, tmp, tmp_len);
3831 /* Check whether sender is on the channel */
3832 if (!silc_server_client_on_channel(client, channel, &chl)) {
3833 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3834 silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3835 SILC_STATUS_ERR_NOT_ON_CHANNEL,
3836 0, 2, tmp, tmp_len);
3840 /* Check that the kicker is channel operator or channel founder */
3841 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
3842 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
3843 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3844 silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3845 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
3846 0, 2, tmp, tmp_len);
3850 /* Get target Client ID */
3851 if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id2, NULL)) {
3852 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3853 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
3857 /* Get target client's entry */
3858 target_client = silc_idlist_find_client_by_id(server->local_list,
3859 SILC_ID_GET_ID(id2),
3862 target_client = silc_idlist_find_client_by_id(server->global_list,
3863 SILC_ID_GET_ID(id2),
3866 /* Check whether target client is on the channel */
3867 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
3868 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3869 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
3870 silc_server_command_send_status_data2(cmd, SILC_COMMAND_KICK,
3871 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL,
3872 0, 2, target_idp, target_idp_len,
3877 /* Check that the target client is not channel founder. Channel founder
3878 cannot be kicked from the channel. */
3879 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3880 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3881 silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3882 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
3883 0, 2, tmp, tmp_len);
3888 comment = silc_argument_get_arg_type(cmd->args, 3, &clen);
3892 /* Send the reply back to the client */
3893 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3894 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
3895 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_KICK,
3896 SILC_STATUS_OK, 0, ident, 2,
3898 3, target_idp, target_idp_len);
3900 /* Send KICKED notify to local clients on the channel */
3901 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3902 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
3903 SILC_NOTIFY_TYPE_KICKED, 3,
3904 target_idp, target_idp_len,
3905 comment, comment ? strlen(comment) : 0,
3906 idp->data, silc_buffer_len(idp));
3907 silc_buffer_free(idp);
3909 /* Send KICKED notify to primary route */
3910 silc_server_send_notify_kicked(server, SILC_PRIMARY_ROUTE(server),
3911 SILC_BROADCAST(server), channel,
3912 target_client->id, client->id, comment);
3914 /* Remove the client from channel's invite list */
3915 if (channel->invite_list && silc_hash_table_count(channel->invite_list)) {
3917 silc_argument_payload_encode_one(NULL, target_idp, target_idp_len, 3);
3918 SilcArgumentPayload args =
3919 silc_argument_payload_parse(ab->data, silc_buffer_len(ab), 1);
3921 silc_server_inviteban_process(server, channel->invite_list, 1, args);
3922 silc_buffer_free(ab);
3923 silc_argument_payload_free(args);
3926 /* Remove the client from the channel. If the channel does not exist
3927 after removing the client then the client kicked itself off the channel
3928 and we don't have to send anything after that. */
3929 if (!silc_server_remove_from_one_channel(server, NULL, channel,
3930 target_client, FALSE))
3933 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3934 /* Re-generate channel key */
3935 if (!silc_server_create_channel_key(server, channel, 0))
3938 /* Send the channel key to the channel. The key of course is not sent
3939 to the client who was kicked off the channel. */
3940 silc_server_send_channel_key(server, target_client->connection, channel,
3941 server->server_type == SILC_ROUTER ?
3942 FALSE : !server->standalone);
3946 silc_server_command_free(cmd);
3949 /* Server side of OPER command. Client uses this comand to obtain server
3950 operator privileges to this server/router. */
3952 SILC_SERVER_CMD_FUNC(oper)
3954 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3955 SilcServer server = cmd->server;
3956 SilcClientEntry client = silc_packet_get_context(cmd->sock);
3957 unsigned char *username = NULL, *auth;
3959 SilcServerConfigAdmin *admin;
3960 SilcIDListData idata = (SilcIDListData)client;
3961 SilcBool result = FALSE;
3962 SilcPublicKey cached_key;
3963 const char *hostname, *ip;
3965 if (client->data.conn_type != SILC_CONN_CLIENT || !client)
3968 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
3970 silc_socket_stream_get_info(silc_packet_stream_get_stream(cmd->sock),
3971 NULL, &hostname, &ip, NULL);
3973 /* Get the username */
3974 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3976 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3977 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3982 /* Check username */
3983 username = silc_identifier_check(username, strlen(username),
3984 SILC_STRING_UTF8, 128, &tmp_len);
3986 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3987 SILC_STATUS_ERR_BAD_USERNAME,
3992 /* Get the admin configuration */
3993 admin = silc_server_config_find_admin(server, (char *)ip,
3994 username, client->nickname);
3996 admin = silc_server_config_find_admin(server, (char *)hostname,
3997 username, client->nickname);
3999 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4000 SILC_STATUS_ERR_AUTH_FAILED,
4002 SILC_LOG_INFO(("OPER authentication failed for username '%s' by "
4003 "nickname '%s' from %s", username,
4004 client->nickname, hostname));
4009 /* Get the authentication payload */
4010 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4012 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4013 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4018 /* Verify the authentication data. If both passphrase and public key
4019 is set then try both of them. */
4020 if (admin->passphrase)
4021 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4022 admin->passphrase, admin->passphrase_len,
4023 idata->hash, client->id, SILC_ID_CLIENT);
4024 if (!result && admin->publickeys) {
4026 silc_server_get_public_key(server,
4027 SILC_SKR_USAGE_SERVICE_AUTHORIZATION, admin);
4030 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4031 cached_key, 0, idata->hash,
4032 client->id, SILC_ID_CLIENT);
4035 /* Authentication failed */
4036 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4037 SILC_STATUS_ERR_AUTH_FAILED,
4042 /* Client is now server operator */
4043 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4045 /* Update statistics */
4046 if (SILC_IS_LOCAL(client))
4047 server->stat.my_server_ops++;
4048 if (server->server_type == SILC_ROUTER)
4049 server->stat.server_ops++;
4051 /* Send UMODE change to primary router */
4052 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
4053 SILC_BROADCAST(server), client->id,
4056 /* Check if anyone is watching this nickname */
4057 if (server->server_type == SILC_ROUTER)
4058 silc_server_check_watcher_list(server, client, NULL,
4059 SILC_NOTIFY_TYPE_UMODE_CHANGE);
4061 /* Send reply to the sender */
4062 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4066 silc_free(username);
4067 silc_server_command_free(cmd);
4070 SILC_TASK_CALLBACK(silc_server_command_detach_cb)
4072 SilcServer server = app_context;
4073 QuitInternal q = (QuitInternal)context;
4074 SilcPacketStream sock = q->sock;
4075 SilcClientEntry client = silc_packet_get_context(sock);
4076 SilcIDListData idata = (SilcIDListData)client;
4079 silc_packet_stream_unref(sock);
4084 SILC_LOG_DEBUG(("Detaching client %s",
4085 silc_id_render(client->id, SILC_ID_CLIENT)));
4087 /* Stop rekey for the client. */
4088 silc_server_stop_rekey(server, client);
4090 /* Abort any active protocol */
4091 idata = silc_packet_get_context(sock);
4092 if (idata && idata->sconn && idata->sconn->op) {
4093 SILC_LOG_DEBUG(("Abort active protocol"));
4094 silc_async_abort(idata->sconn->op, NULL, NULL);
4095 idata->sconn->op = NULL;
4098 silc_schedule_task_del_by_all(server->schedule, 0, silc_server_do_heartbeat,
4101 /* Close the connection on our side */
4102 client->router = NULL;
4103 client->connection = NULL;
4104 silc_server_close_connection(server, sock);
4106 /* Mark the client as locally detached. */
4107 client->local_detached = TRUE;
4109 /* Decrement the user count; we'll increment it if the user resumes on our
4111 SILC_VERIFY(&server->stat.my_clients > 0);
4112 server->stat.my_clients--;
4114 silc_packet_stream_unref(sock);
4118 SILC_TASK_CALLBACK(silc_server_command_detach_timeout)
4120 SilcServer server = app_context;
4121 QuitInternal q = (QuitInternal)context;
4122 SilcClientID *client_id = (SilcClientID *)q->sock;
4123 SilcClientEntry client;
4125 client = silc_idlist_find_client_by_id(server->local_list, client_id,
4127 if (client && client->mode & SILC_UMODE_DETACHED) {
4128 SILC_LOG_DEBUG(("Detach timeout"));
4129 silc_server_free_client_data(server, NULL, client, TRUE,
4133 silc_free(client_id);
4137 /* Server side of DETACH command. Detached the client from the network
4138 by closing the connection but preserving the session. */
4140 SILC_SERVER_CMD_FUNC(detach)
4142 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4143 SilcServer server = cmd->server;
4144 SilcClientEntry client = silc_packet_get_context(cmd->sock);
4147 if (server->config->detach_disabled) {
4148 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
4149 SILC_STATUS_ERR_OPERATION_ALLOWED,
4154 if (client->data.conn_type != SILC_CONN_CLIENT || !client)
4157 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
4159 /* Remove operator privileges, since the client may resume in some
4160 other server which to it does not have operator privileges. */
4161 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
4162 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
4164 /* Send the user mode notify to notify that client is detached */
4165 client->mode |= SILC_UMODE_DETACHED;
4166 client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
4167 client->data.status &= ~SILC_IDLIST_STATUS_NOATTR;
4168 client->last_command = 0;
4169 client->fast_command = 0;
4170 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
4171 SILC_BROADCAST(server), client->id,
4173 server->stat.my_detached++;
4175 /* Check if anyone is watching this nickname */
4176 if (server->server_type == SILC_ROUTER)
4177 silc_server_check_watcher_list(server, client, NULL,
4178 SILC_NOTIFY_TYPE_UMODE_CHANGE);
4180 q = silc_calloc(1, sizeof(*q));
4181 q->sock = cmd->sock;
4182 silc_packet_stream_ref(q->sock);
4183 silc_schedule_task_add_timeout(server->schedule,
4184 silc_server_command_detach_cb,
4187 if (server->config->detach_timeout) {
4188 q = silc_calloc(1, sizeof(*q));
4189 q->sock = (void *)silc_id_dup(client->id, SILC_ID_CLIENT);
4190 silc_schedule_task_add_timeout(server->schedule,
4191 silc_server_command_detach_timeout,
4192 q, server->config->detach_timeout * 60, 0);
4195 /* Send reply to the sender */
4196 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
4200 silc_server_command_free(cmd);
4203 /* Server side of WATCH command. */
4205 SILC_SERVER_CMD_FUNC(watch)
4207 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4208 SilcServer server = cmd->server;
4209 char *add_nick, *del_nick;
4210 SilcUInt32 add_nick_len, del_nick_len, tmp_len, pk_len;
4211 unsigned char hash[SILC_HASH_MAXLEN], *tmp, *pk, *nick;
4212 SilcClientEntry client;
4214 SilcUInt16 old_ident;
4216 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WATCH, cmd, 1, 3);
4218 if (server->server_type != SILC_ROUTER && !server->standalone) {
4219 if (!cmd->pending) {
4220 /* Send the command to router */
4223 /* If backup receives this from primary, handle it locally */
4224 if (server->server_type == SILC_BACKUP_ROUTER &&
4225 cmd->sock == SILC_PRIMARY_ROUTE(server))
4228 SILC_LOG_DEBUG(("Forwarding WATCH to router"));
4231 cmd->server->stat.commands_sent++;
4233 old_ident = silc_command_get_ident(cmd->payload);
4234 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4235 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4237 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
4238 SILC_PACKET_COMMAND, cmd->packet->flags,
4239 tmpbuf->data, silc_buffer_len(tmpbuf));
4241 /* Reprocess this packet after received reply from router */
4242 silc_server_command_pending(server, SILC_COMMAND_WATCH,
4243 silc_command_get_ident(cmd->payload),
4244 silc_server_command_watch,
4245 silc_server_command_dup(cmd));
4246 cmd->pending = TRUE;
4247 silc_command_set_ident(cmd->payload, old_ident);
4248 silc_buffer_free(tmpbuf);
4251 SilcServerCommandReplyContext reply = context2;
4257 silc_command_get_status(reply->payload, &status, NULL);
4259 /* Backup router handles the WATCH command also. */
4260 if (server->server_type != SILC_BACKUP_ROUTER ||
4261 SILC_STATUS_IS_ERROR(status)) {
4262 /* Received reply from router, just send same data to the client. */
4263 SILC_LOG_DEBUG(("Received reply to WATCH from router"));
4264 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, status,
4271 /* We are router and keep the watch list for local cell */
4274 /* Get the client ID */
4275 if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
4276 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4277 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4282 /* Get the client entry which must be in local list */
4283 client = silc_idlist_find_client_by_id(server->local_list,
4284 SILC_ID_GET_ID(id), TRUE, NULL);
4286 /* Backup checks global list also */
4287 if (server->server_type == SILC_BACKUP_ROUTER)
4288 client = silc_idlist_find_client_by_id(server->global_list,
4289 SILC_ID_GET_ID(id), TRUE, NULL);
4291 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4292 silc_server_command_send_status_data(cmd, SILC_COMMAND_WATCH,
4293 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
4294 0, 2, tmp, tmp_len);
4299 /* Take public key for watching by public key */
4300 pk = silc_argument_get_arg_type(cmd->args, 4, &pk_len);
4303 add_nick = silc_argument_get_arg_type(cmd->args, 2, &add_nick_len);
4304 del_nick = silc_argument_get_arg_type(cmd->args, 3, &del_nick_len);
4305 if (!add_nick && !del_nick && !pk) {
4306 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4307 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4312 if (add_nick && add_nick_len > 128) {
4314 add_nick[add_nick_len - 1] = '\0';
4316 if (del_nick && del_nick_len > 128) {
4318 del_nick[del_nick_len - 1] = '\0';
4321 /* Add new nickname to be watched in our cell */
4323 nick = silc_identifier_check(add_nick, add_nick_len, SILC_STRING_UTF8, 128,
4326 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4327 SILC_STATUS_ERR_BAD_NICKNAME, 0);
4331 /* Hash the nick, we have the hash saved, not nicks because we can
4332 do one to one mapping to the nick from Client ID hash this way. */
4333 silc_hash_make(server->md5hash, nick, add_nick_len, hash);
4335 /* Check whether this client is already watching this nickname */
4336 if (silc_hash_table_find_by_context(server->watcher_list, hash,
4338 /* Nickname is alredy being watched for this client */
4339 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4340 SILC_STATUS_ERR_NICKNAME_IN_USE,
4346 /* Get the nickname from the watcher list and use the same key in
4347 new entries as well. If key doesn't exist then create it. */
4348 if (!silc_hash_table_find(server->watcher_list, hash, (void *)&tmp, NULL))
4349 tmp = silc_memdup(hash, CLIENTID_HASH_LEN);
4351 /* Add the client to the watcher list with the specified nickname hash. */
4352 silc_hash_table_add(server->watcher_list, tmp, client);
4356 /* Delete nickname from watch list */
4358 nick = silc_identifier_check(del_nick, del_nick_len, SILC_STRING_UTF8, 128,
4361 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4362 SILC_STATUS_ERR_BAD_NICKNAME, 0);
4366 /* Hash the nick, we have the hash saved, not nicks because we can
4367 do one to one mapping to the nick from Client ID hash this way. */
4368 silc_hash_make(server->md5hash, nick, del_nick_len, hash);
4370 /* Check that this client is watching for this nickname */
4371 if (!silc_hash_table_find_by_context(server->watcher_list, hash,
4372 client, (void *)&tmp)) {
4373 /* Nickname is alredy being watched for this client */
4374 silc_server_command_send_status_data(cmd, SILC_COMMAND_WATCH,
4375 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
4376 2, nick, del_nick_len);
4381 /* Delete the nickname from the watcher list. */
4382 silc_hash_table_del_by_context(server->watcher_list, hash, client);
4384 /* Now check whether there still exists entries with this key, if not
4385 then free the key to not leak memory. */
4386 if (!silc_hash_table_find(server->watcher_list, hash, NULL, NULL))
4391 /* Add/del public key */
4394 SilcArgumentPayload pkargs;
4396 SilcPublicKey public_key, pkkey;
4399 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4400 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4405 /* Get the argument from the Argument List Payload */
4406 SILC_GET16_MSB(pkargc, pk);
4407 pkargs = silc_argument_payload_parse(pk + 2, pk_len - 2, pkargc);
4409 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4410 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4415 pk = silc_argument_get_next_arg(pkargs, &type, &pk_len);
4417 if (!silc_public_key_payload_decode(pk, pk_len, &public_key)) {
4418 pk = silc_argument_get_next_arg(pkargs, &type, &pk_len);
4425 /* Add public key to watch list */
4427 /* Check whether this client is already watching this public key */
4428 if (silc_hash_table_find_by_context(server->watcher_list_pk,
4429 public_key, client, NULL)) {
4430 silc_pkcs_public_key_free(public_key);
4431 silc_server_command_send_status_reply(
4432 cmd, SILC_COMMAND_WATCH,
4433 SILC_STATUS_ERR_NICKNAME_IN_USE, 0);
4437 /* Get the public key from the watcher list and use the same key in
4438 new entries as well. If key doesn't exist then create it. */
4440 if (!silc_hash_table_find(server->watcher_list_pk, public_key,
4441 (void *)&pkkey, NULL))
4444 silc_pkcs_public_key_free(public_key);
4446 /* Add the client to the watcher list with the specified public
4448 silc_hash_table_add(server->watcher_list_pk, pkkey, client);
4450 } else if (type == 0x01) {
4451 /* Delete public key from watch list */
4453 /* Check that this client is watching this public key */
4454 if (silc_hash_table_find_by_context(server->watcher_list_pk,
4457 silc_pkcs_public_key_free(public_key);
4458 silc_server_command_send_status_reply(
4459 cmd, SILC_COMMAND_WATCH,
4460 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4464 /* Delete the public key from the watcher list. */
4465 silc_hash_table_del_by_context(server->watcher_list_pk,
4466 public_key, client);
4468 /* Now check whether there still exists entries with this key, if
4469 not then free the key to not leak memory. */
4470 if (!silc_hash_table_find(server->watcher_list_pk, hash, NULL, NULL))
4471 silc_pkcs_public_key_free(pkkey);
4472 silc_pkcs_public_key_free(public_key);
4475 pk = silc_argument_get_next_arg(pkargs, &type, &pk_len);
4480 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4483 /* Distribute the watch list to backup routers too */
4484 if (server->backup) {
4488 cmd->server->stat.commands_sent++;
4490 old_ident = silc_command_get_ident(cmd->payload);
4491 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4492 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4493 silc_server_backup_send(server, silc_packet_get_context(cmd->sock),
4494 SILC_PACKET_COMMAND,
4495 cmd->packet->flags, tmpbuf->data,
4496 silc_buffer_len(tmpbuf),
4498 silc_command_set_ident(cmd->payload, old_ident);
4499 silc_buffer_free(tmpbuf);
4503 silc_server_command_free(cmd);
4506 /* Server side of SILCOPER command. Client uses this comand to obtain router
4507 operator privileges to this router. */
4509 SILC_SERVER_CMD_FUNC(silcoper)
4511 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4512 SilcServer server = cmd->server;
4513 SilcClientEntry client = silc_packet_get_context(cmd->sock);
4514 unsigned char *username = NULL, *auth;
4516 SilcServerConfigAdmin *admin;
4517 SilcIDListData idata = (SilcIDListData)client;
4518 SilcBool result = FALSE;
4519 SilcPublicKey cached_key;
4520 const char *hostname, *ip;
4522 if (client->data.conn_type != SILC_CONN_CLIENT || !client)
4525 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4527 silc_socket_stream_get_info(silc_packet_stream_get_stream(cmd->sock),
4528 NULL, &hostname, &ip, NULL);
4530 if (server->server_type != SILC_ROUTER) {
4531 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4532 SILC_STATUS_ERR_AUTH_FAILED, 0);
4536 /* Get the username */
4537 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4539 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4540 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4545 /* Check username */
4546 username = silc_identifier_check(username, tmp_len, SILC_STRING_UTF8, 128,
4549 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4550 SILC_STATUS_ERR_BAD_USERNAME,
4555 /* Get the admin configuration */
4556 admin = silc_server_config_find_admin(server, (char *)ip,
4557 username, client->nickname);
4559 admin = silc_server_config_find_admin(server, (char *)hostname,
4560 username, client->nickname);
4562 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4563 SILC_STATUS_ERR_AUTH_FAILED, 0);
4564 SILC_LOG_INFO(("SILCOPER authentication failed for username '%s' by "
4565 "nickname '%s' from %s", username,
4566 client->nickname, hostname));
4571 /* Get the authentication payload */
4572 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4574 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4575 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4580 /* Verify the authentication data. If both passphrase and public key
4581 is set then try both of them. */
4582 if (admin->passphrase)
4583 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4584 admin->passphrase, admin->passphrase_len,
4585 idata->hash, client->id, SILC_ID_CLIENT);
4586 if (!result && admin->publickeys) {
4588 silc_server_get_public_key(server,
4589 SILC_SKR_USAGE_SERVICE_AUTHORIZATION, admin);
4592 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4593 cached_key, 0, idata->hash,
4594 client->id, SILC_ID_CLIENT);
4597 /* Authentication failed */
4598 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4599 SILC_STATUS_ERR_AUTH_FAILED, 0);
4603 /* Client is now router operator */
4604 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4606 /* Update statistics */
4607 if (SILC_IS_LOCAL(client))
4608 server->stat.my_router_ops++;
4609 if (server->server_type == SILC_ROUTER)
4610 server->stat.router_ops++;
4612 /* Send UMODE change to primary router */
4613 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
4614 SILC_BROADCAST(server), client->id,
4617 /* Check if anyone is watching this nickname */
4618 if (server->server_type == SILC_ROUTER)
4619 silc_server_check_watcher_list(server, client, NULL,
4620 SILC_NOTIFY_TYPE_UMODE_CHANGE);
4622 /* Send reply to the sender */
4623 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4627 silc_free(username);
4628 silc_server_command_free(cmd);
4631 /* Server side of command BAN. This is used to manage the ban list of the
4632 channel. To add clients and remove clients from the ban list. */
4634 SILC_SERVER_CMD_FUNC(ban)
4636 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4637 SilcServer server = cmd->server;
4638 SilcClientEntry client = silc_packet_get_context(cmd->sock);
4639 SilcBuffer list, tmp2;
4640 SilcChannelEntry channel;
4641 SilcChannelClientEntry chl;
4643 unsigned char *tmp_id, *tmp, *atype = NULL;
4644 SilcUInt32 id_len, len, len2;
4645 SilcArgumentPayload args;
4646 SilcHashTableList htl;
4648 SilcUInt16 argc = 0, ident = silc_command_get_ident(cmd->payload);
4649 SilcBufferStruct blist;
4651 if (client->data.conn_type != SILC_CONN_CLIENT || !client)
4654 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4656 /* Get Channel ID */
4657 if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
4658 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4659 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4663 /* Get channel entry. The server must know about the channel since the
4664 client is expected to be on the channel. */
4665 channel = silc_idlist_find_channel_by_id(server->local_list,
4666 SILC_ID_GET_ID(id), NULL);
4668 channel = silc_idlist_find_channel_by_id(server->global_list,
4669 SILC_ID_GET_ID(id), NULL);
4671 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4672 silc_server_command_send_status_data(
4673 cmd, SILC_COMMAND_BAN,
4674 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
4675 0, 2, tmp_id, id_len);
4680 /* Check whether this client is on the channel */
4681 if (!silc_server_client_on_channel(client, channel, &chl)) {
4682 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4683 silc_server_command_send_status_data(cmd, SILC_COMMAND_BAN,
4684 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
4689 /* The client must be at least channel operator. */
4690 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4691 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4692 silc_server_command_send_status_data(cmd, SILC_COMMAND_BAN,
4693 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0,
4698 /* Get the ban information */
4699 tmp = silc_argument_get_arg_type(cmd->args, 3, &len2);
4700 if (tmp && len2 > 2) {
4701 /* Parse the arguments to see they are constructed correctly */
4702 SILC_GET16_MSB(argc, tmp);
4703 args = silc_argument_payload_parse(tmp + 2, len2 - 2, argc);
4705 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4706 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4711 /* Get the type of action */
4712 atype = silc_argument_get_arg_type(cmd->args, 2, &len);
4713 if (atype && len == 1) {
4714 if (atype[0] == 0x00) {
4715 /* Allocate hash table for ban list if it doesn't exist yet */
4716 if (!channel->ban_list)
4718 silc_hash_table_alloc(0, silc_hash_ptr,
4720 silc_server_inviteban_destruct, channel,
4723 /* Check for resource limit */
4724 if (silc_hash_table_count(channel->ban_list) > 64) {
4725 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4726 SILC_STATUS_ERR_RESOURCE_LIMIT,
4732 /* Now add or delete the information. */
4733 if (!silc_server_inviteban_process(server, channel->ban_list,
4734 (SilcUInt8)atype[0], args)) {
4735 silc_server_command_send_status_reply(
4736 cmd, SILC_COMMAND_BAN,
4737 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4742 silc_argument_payload_free(args);
4745 /* Encode ban list */
4747 if (channel->ban_list && silc_hash_table_count(channel->ban_list)) {
4748 list = silc_buffer_alloc_size(2);
4749 silc_buffer_format(list,
4750 SILC_STR_UI_SHORT(silc_hash_table_count(
4751 channel->ban_list)),
4753 silc_hash_table_list(channel->ban_list, &htl);
4754 while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2))
4755 list = silc_argument_payload_encode_one(list, tmp2->data,
4756 silc_buffer_len(tmp2),
4757 SILC_PTR_TO_32(type));
4758 silc_hash_table_list_reset(&htl);
4761 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4763 /* Send BAN notify type to local servers (but not clients) and to
4765 if (atype && tmp && len2) {
4766 silc_buffer_set(&blist, tmp, len2);
4768 /* Send to local servers if we are router */
4769 if (server->server_type == SILC_ROUTER)
4770 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, FALSE,
4771 SILC_NOTIFY_TYPE_BAN, 3,
4774 tmp ? blist.data : NULL,
4775 tmp ? silc_buffer_len(&blist) : 0);
4777 /* Send to network. */
4778 silc_server_send_notify_ban(server, SILC_PRIMARY_ROUTE(server),
4779 SILC_BROADCAST(server), channel, atype,
4783 /* Send the reply back to the client */
4784 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_BAN,
4785 SILC_STATUS_OK, 0, ident, 2,
4787 3, list ? list->data : NULL,
4788 list ? silc_buffer_len(list) : 0);
4789 silc_buffer_free(list);
4792 silc_server_command_free(cmd);
4795 /* Server side command of LEAVE. Removes client from a channel. */
4797 SILC_SERVER_CMD_FUNC(leave)
4799 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4800 SilcServer server = cmd->server;
4801 SilcPacketStream sock = cmd->sock;
4802 SilcClientEntry id_entry = silc_packet_get_context(cmd->sock);
4804 SilcChannelEntry channel;
4808 if (id_entry->data.conn_type != SILC_CONN_CLIENT || !id_entry)
4811 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4813 /* Get Channel ID */
4814 if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
4815 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4816 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4820 /* Get channel entry */
4821 channel = silc_idlist_find_channel_by_id(server->local_list,
4822 SILC_ID_GET_ID(id), NULL);
4824 channel = silc_idlist_find_channel_by_id(server->global_list,
4825 SILC_ID_GET_ID(id), NULL);
4827 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4828 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4829 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
4835 /* Check whether this client is on the channel */
4836 if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
4837 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4838 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4839 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
4844 /* Notify routers that they should remove this client from their list
4845 of clients on the channel. Send LEAVE notify type. */
4846 silc_server_send_notify_leave(server, SILC_PRIMARY_ROUTE(server),
4847 SILC_BROADCAST(server), channel, id_entry->id);
4849 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4850 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4851 SILC_STATUS_OK, 0, 2, tmp, len);
4853 /* Remove client from channel */
4854 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4856 /* If the channel does not exist anymore we won't send anything */
4859 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4860 /* Re-generate channel key */
4861 if (!silc_server_create_channel_key(server, channel, 0))
4864 /* Send the channel key */
4865 silc_server_send_channel_key(server, NULL, channel,
4866 server->server_type == SILC_ROUTER ?
4867 FALSE : !server->standalone);
4871 silc_server_command_free(cmd);
4874 /* Server side of command USERS. Resolves clients and their USERS currently
4875 joined on the requested channel. The list of Client ID's and their modes
4876 on the channel is sent back. */
4878 SILC_SERVER_CMD_FUNC(users)
4880 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4881 SilcServer server = cmd->server;
4882 SilcIDListData idata = silc_packet_get_context(cmd->sock);
4883 SilcChannelEntry channel;
4886 unsigned char *channel_id;
4887 SilcUInt32 channel_id_len;
4888 SilcBuffer client_id_list;
4889 SilcBuffer client_mode_list;
4890 unsigned char lc[4];
4891 SilcUInt32 list_count = 0;
4892 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4893 char *channel_name, *channel_namec = NULL;
4895 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
4897 /* Get Channel ID */
4898 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4900 /* Get channel name */
4901 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
4903 if (!channel_id && !channel_name) {
4904 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4905 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4909 /* Check channel name */
4911 channel_namec = silc_channel_name_check(channel_name, strlen(channel_name),
4912 SILC_STRING_UTF8, 256, NULL);
4913 if (!channel_namec) {
4914 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4915 SILC_STATUS_ERR_BAD_CHANNEL, 0);
4920 /* Check Channel ID */
4922 if (!silc_id_payload_parse_id(channel_id, channel_id_len, &id)) {
4923 silc_server_command_send_status_data(cmd, SILC_COMMAND_USERS,
4924 SILC_STATUS_ERR_BAD_CHANNEL_ID, 0,
4925 2, channel_id, channel_id_len);
4930 /* If we are server and we don't know about this channel we will send
4931 the command to our router. If we know about the channel then we also
4932 have the list of users already. */
4934 channel = silc_idlist_find_channel_by_id(server->local_list,
4935 SILC_ID_GET_ID(id), NULL);
4937 channel = silc_idlist_find_channel_by_name(server->local_list,
4938 channel_namec, NULL);
4940 if (!channel || (!server->standalone && (channel->disabled ||
4941 !channel->users_resolved))) {
4942 if (server->server_type != SILC_ROUTER && !server->standalone &&
4947 cmd->server->stat.commands_sent++;
4949 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4950 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4952 /* Send USERS command */
4953 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
4954 SILC_PACKET_COMMAND, cmd->packet->flags,
4955 tmpbuf->data, silc_buffer_len(tmpbuf));
4957 /* Reprocess this packet after received reply */
4958 silc_server_command_pending(server, SILC_COMMAND_USERS,
4959 silc_command_get_ident(cmd->payload),
4960 silc_server_command_users,
4961 silc_server_command_dup(cmd));
4962 cmd->pending = TRUE;
4963 silc_command_set_ident(cmd->payload, ident);
4964 silc_buffer_free(tmpbuf);
4968 /* Check the global list as well. */
4970 channel = silc_idlist_find_channel_by_id(server->global_list,
4971 SILC_ID_GET_ID(id), NULL);
4973 channel = silc_idlist_find_channel_by_name(server->global_list,
4974 channel_namec, NULL);
4976 /* Channel really does not exist */
4978 silc_server_command_send_status_data(
4979 cmd, SILC_COMMAND_USERS,
4980 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID, 0,
4981 2, channel_id, channel_id_len);
4983 silc_server_command_send_status_data(
4984 cmd, SILC_COMMAND_USERS,
4985 SILC_STATUS_ERR_NO_SUCH_CHANNEL, 0,
4986 2, channel_name, strlen(channel_name));
4991 /* If the channel is private or secret do not send anything, unless the
4992 user requesting this command is on the channel or is server */
4993 if (idata->conn_type == SILC_CONN_CLIENT) {
4994 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
4995 && !silc_server_client_on_channel((SilcClientEntry)idata, channel,
4997 silc_server_command_send_status_data(cmd, SILC_COMMAND_USERS,
4998 SILC_STATUS_ERR_NO_SUCH_CHANNEL, 0,
4999 2, channel->channel_name,
5000 strlen(channel->channel_name));
5005 /* Get the users list */
5006 if (!silc_server_get_users_on_channel(server, channel, &client_id_list,
5007 &client_mode_list, &list_count)) {
5009 client_id_list = NULL;
5010 client_mode_list = NULL;
5014 SILC_PUT32_MSB(list_count, lc);
5017 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5018 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_USERS,
5019 SILC_STATUS_OK, 0, ident, 4,
5020 2, idp->data, silc_buffer_len(idp),
5023 client_id_list->data : NULL,
5025 silc_buffer_len(client_id_list) : 0,
5026 5, client_mode_list ?
5027 client_mode_list->data : NULL,
5029 silc_buffer_len(client_mode_list) : 0);
5030 silc_buffer_free(idp);
5032 silc_buffer_free(client_id_list);
5033 if (client_mode_list)
5034 silc_buffer_free(client_mode_list);
5037 silc_free(channel_namec);
5038 silc_server_command_free(cmd);
5041 /* Server side of command GETKEY. This fetches the client's public key
5042 from the server where to the client is connected. */
5044 SILC_SERVER_CMD_FUNC(getkey)
5046 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5047 SilcServer server = cmd->server;
5048 SilcClientEntry client;
5049 SilcServerEntry server_entry;
5050 SilcClientID client_id;
5051 SilcServerID server_id;
5052 SilcIDPayload idp = NULL;
5053 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5056 SilcBuffer pk = NULL;
5058 SilcPublicKey public_key;
5060 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5062 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5063 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5067 idp = silc_id_payload_parse(tmp, tmp_len);
5069 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5070 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5075 id_type = silc_id_payload_get_type(idp);
5076 if (id_type == SILC_ID_CLIENT) {
5077 silc_id_payload_get_id(idp, &client_id, sizeof(client_id));
5079 /* If the client is not found from local list there is no chance it
5080 would be locally connected client so send the command further. */
5081 client = silc_idlist_find_client_by_id(server->local_list,
5082 &client_id, TRUE, NULL);
5084 client = silc_idlist_find_client_by_id(server->global_list,
5085 &client_id, TRUE, NULL);
5087 if ((!client && !cmd->pending && !server->standalone) ||
5088 (client && !client->connection && !cmd->pending &&
5089 !(client->mode & SILC_UMODE_DETACHED)) ||
5090 (client && !client->data.public_key && !cmd->pending)) {
5092 SilcUInt16 old_ident;
5093 SilcPacketStream dest_sock;
5095 dest_sock = silc_server_get_client_route(server, NULL, 0,
5096 &client_id, NULL, NULL);
5101 cmd->server->stat.commands_sent++;
5103 old_ident = silc_command_get_ident(cmd->payload);
5104 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5105 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5107 silc_server_packet_send(server, dest_sock,
5108 SILC_PACKET_COMMAND, cmd->packet->flags,
5109 tmpbuf->data, silc_buffer_len(tmpbuf));
5111 /* Reprocess this packet after received reply from router */
5112 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5113 silc_command_get_ident(cmd->payload),
5114 silc_server_command_getkey,
5115 silc_server_command_dup(cmd));
5116 cmd->pending = TRUE;
5117 silc_command_set_ident(cmd->payload, old_ident);
5118 silc_buffer_free(tmpbuf);
5123 silc_server_command_send_status_data(cmd, SILC_COMMAND_GETKEY,
5124 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5125 0, 2, tmp, tmp_len);
5129 /* The client is locally connected, just get the public key and
5130 send it back. If they key does not exist then do not send it,
5131 send just OK reply */
5132 public_key = client->data.public_key;
5134 pk = silc_public_key_payload_encode(public_key);
5135 } else if (id_type == SILC_ID_SERVER) {
5136 silc_id_payload_get_id(idp, &server_id, sizeof(server_id));
5138 /* If the server is not found from local list there is no chance it
5139 would be locally connected server so send the command further. */
5140 server_entry = silc_idlist_find_server_by_id(server->local_list,
5141 &server_id, TRUE, NULL);
5143 server_entry = silc_idlist_find_server_by_id(server->global_list,
5144 &server_id, TRUE, NULL);
5146 if (server_entry != server->id_entry &&
5147 ((!server_entry && !cmd->pending && !server->standalone) ||
5148 (server_entry && !server_entry->connection && !cmd->pending &&
5149 !server->standalone) ||
5150 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5151 !server->standalone))) {
5153 SilcUInt16 old_ident;
5156 cmd->server->stat.commands_sent++;
5158 old_ident = silc_command_get_ident(cmd->payload);
5159 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5160 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5162 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5163 SILC_PACKET_COMMAND, cmd->packet->flags,
5164 tmpbuf->data, silc_buffer_len(tmpbuf));
5166 /* Reprocess this packet after received reply from router */
5167 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5168 silc_command_get_ident(cmd->payload),
5169 silc_server_command_getkey,
5170 silc_server_command_dup(cmd));
5171 cmd->pending = TRUE;
5172 silc_command_set_ident(cmd->payload, old_ident);
5173 silc_buffer_free(tmpbuf);
5177 if (!server_entry) {
5178 silc_server_command_send_status_data(cmd, SILC_COMMAND_GETKEY,
5179 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
5180 0, 2, tmp, tmp_len);
5184 /* If they key does not exist then do not send it, send just OK reply */
5185 public_key = (!server_entry->data.public_key ?
5186 (server_entry == server->id_entry ? server->public_key :
5187 NULL) : server_entry->data.public_key);
5189 pk = silc_public_key_payload_encode(public_key);
5194 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5195 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_GETKEY,
5196 SILC_STATUS_OK, 0, ident, 2,
5198 3, pk ? pk->data : NULL,
5199 pk ? silc_buffer_len(pk) : 0);
5203 silc_id_payload_free(idp);
5204 silc_buffer_free(pk);
5205 silc_server_command_free(cmd);
5208 /* Server side of command SERVICE. */
5209 /* XXX currently this just sends empty reply back */
5211 SILC_SERVER_CMD_FUNC(service)
5213 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5214 SilcServer server = cmd->server;
5215 SilcUInt32 tmp_len, auth_len;
5216 unsigned char *service_name, *auth;
5217 SilcBool send_list = FALSE;
5218 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5220 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SERVICE, cmd, 0, 256);
5222 /* Get requested service */
5223 service_name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5224 if (service_name && tmp_len) {
5225 /* Verify service name */
5226 if (!silc_identifier_verify(service_name, tmp_len,
5227 SILC_STRING_UTF8, 256)) {
5228 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SERVICE,
5229 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5235 /* Get authentication payload if present */
5236 auth = silc_argument_get_arg_type(cmd->args, 2, &auth_len);
5244 /* Send our service list back */
5245 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_SERVICE,
5246 SILC_STATUS_OK, 0, ident, 0);
5249 silc_server_command_free(cmd);
5253 /* Private range commands, specific to this implementation */
5255 /* Server side command of CONNECT. Connects us to the specified remote
5256 server or router. */
5258 SILC_SERVER_CMD_FUNC(connect)
5260 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5261 SilcServer server = cmd->server;
5262 SilcClientEntry client = silc_packet_get_context(cmd->sock);
5263 unsigned char *tmp, *host;
5265 SilcUInt32 port = SILC_PORT;
5267 if (client->data.conn_type != SILC_CONN_CLIENT || !client)
5270 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
5272 /* Check whether client has the permissions. */
5273 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5274 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5275 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5276 SILC_STATUS_ERR_NO_SERVER_PRIV, 0);
5280 if (server->server_type == SILC_ROUTER && !server->backup_router &&
5281 client->mode & SILC_UMODE_SERVER_OPERATOR) {
5282 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5283 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
5287 /* Get the remote server */
5288 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5290 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5291 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5297 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5299 SILC_GET32_MSB(port, tmp);
5301 /* Create the connection. It is done with timeout and is async. */
5302 silc_server_create_connection(server, FALSE, FALSE, host, port, NULL, NULL);
5304 /* Send reply to the sender */
5305 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5309 silc_server_command_free(cmd);
5312 /* Server side command of CLOSE. Closes connection to a specified server. */
5314 SILC_SERVER_CMD_FUNC(close)
5316 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5317 SilcServer server = cmd->server;
5318 SilcClientEntry client = silc_packet_get_context(cmd->sock);
5319 SilcServerEntry server_entry;
5320 SilcPacketStream sock;
5323 unsigned char *name;
5324 SilcUInt32 port = SILC_PORT;
5326 if (client->data.conn_type != SILC_CONN_CLIENT || !client)
5329 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
5331 /* Check whether client has the permissions. */
5332 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5333 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5334 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5335 SILC_STATUS_ERR_NO_SERVER_PRIV,
5340 /* Get the remote server */
5341 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5343 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5344 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5350 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5352 SILC_GET32_MSB(port, tmp);
5354 server_entry = silc_idlist_find_server_by_conn(server->local_list,
5355 name, port, TRUE, NULL);
5357 server_entry = silc_idlist_find_server_by_conn(server->global_list,
5358 name, port, TRUE, NULL);
5359 if (!server_entry) {
5360 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5361 SILC_STATUS_ERR_NO_SERVER_ID, 0);
5365 if (server_entry == server->id_entry) {
5366 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5367 SILC_STATUS_ERR_NO_SERVER_ID, 0);
5371 /* Send reply to the sender */
5372 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5375 /* Close the connection to the server */
5376 sock = server_entry->connection;
5378 if (server_entry->server_type == SILC_BACKUP_ROUTER) {
5379 server->backup_closed = TRUE;
5380 silc_server_backup_del(server, server_entry);
5383 server->backup_noswitch = TRUE;
5384 if (server->router == server_entry) {
5385 server->id_entry->router = NULL;
5386 server->router = NULL;
5387 server->standalone = TRUE;
5389 silc_server_disconnect_remote(server, sock,
5390 SILC_STATUS_ERR_BANNED_FROM_SERVER,
5391 "Closed by administrator");
5392 silc_server_free_sock_user_data(server, sock, NULL);
5393 server->backup_noswitch = FALSE;
5396 silc_server_command_free(cmd);
5399 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
5400 active connections. */
5402 SILC_SERVER_CMD_FUNC(shutdown)
5404 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5405 SilcServer server = cmd->server;
5406 SilcClientEntry client = silc_packet_get_context(cmd->sock);
5408 if (client->data.conn_type != SILC_CONN_CLIENT || !client)
5411 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
5413 /* Check whether client has the permission. */
5414 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5415 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5416 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5417 SILC_STATUS_ERR_NO_SERVER_PRIV,
5422 /* Send reply to the sender */
5423 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5426 /* Then, gracefully, or not, bring the server down. */
5427 silc_server_stop(server);
5431 silc_server_command_free(cmd);