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 /* Performs several checks to the command. It first checks whether this
89 command was called as pending command callback. If it was then it checks
90 whether error occurred in the command reply where the pending command
93 It also checks that the requested command includes correct amount
95 #define SILC_SERVER_COMMAND_CHECK(command, context, min, max) \
99 if (silc_server_command_pending_error_check(cmd, context2, command)) { \
100 SILC_LOG_DEBUG(("Error occurred in command reply, command not called")); \
101 silc_server_command_free(cmd); \
105 _argc = silc_argument_get_arg_num(cmd->args); \
107 SILC_LOG_DEBUG(("Not enough parameters in command")); \
108 silc_server_command_send_status_reply(cmd, command, \
109 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, \
111 silc_server_command_free(cmd); \
115 SILC_LOG_DEBUG(("Too many parameters in command")); \
116 silc_server_command_send_status_reply(cmd, command, \
117 SILC_STATUS_ERR_TOO_MANY_PARAMS, \
119 silc_server_command_free(cmd); \
124 /* Returns TRUE if the connection is registered. Unregistered connections
125 usually cannot send commands hence the check. */
127 static int silc_server_is_registered(SilcServer server,
128 SilcPacketStream sock,
129 SilcServerCommandContext cmd,
132 SilcIDListData idata = silc_packet_get_context(sock);
137 if (idata->status & SILC_IDLIST_STATUS_REGISTERED)
140 silc_server_command_send_status_reply(cmd, command,
141 SILC_STATUS_ERR_NOT_REGISTERED, 0);
145 /* Internal context to hold data when executed command with timeout. */
147 SilcServerCommandContext ctx;
148 SilcServerCommand *cmd;
149 } *SilcServerCommandTimeout;
151 /* Timeout callback to process commands with timeout for client. Client's
152 commands are always executed with timeout. */
154 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
156 SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
157 SilcClientEntry client = silc_packet_get_context(timeout->ctx->sock);
160 SILC_LOG_DEBUG(("Client entry is invalid"));
161 silc_server_command_free(timeout->ctx);
166 /* Update access time */
167 client->last_command = time(NULL);
169 if (!(timeout->cmd->flags & SILC_CF_REG)) {
170 SILC_LOG_DEBUG(("Calling %s command",
171 silc_get_command_name(timeout->cmd->cmd)));
172 timeout->cmd->cb(timeout->ctx, NULL);
173 } else if (silc_server_is_registered(timeout->ctx->server,
176 timeout->cmd->cmd)) {
177 SILC_LOG_DEBUG(("Calling %s command",
178 silc_get_command_name(timeout->cmd->cmd)));
179 timeout->cmd->cb(timeout->ctx, NULL);
181 SILC_LOG_DEBUG(("Client is not registered"));
182 silc_server_command_free(timeout->ctx);
188 /* Processes received command packet. */
190 void silc_server_command_process(SilcServer server,
191 SilcPacketStream sock,
194 SilcIDListData idata = silc_packet_get_context(sock);
195 SilcServerCommandContext ctx;
196 SilcServerCommand *cmd;
202 /* Allocate command context. This must be free'd by the
203 command routine receiving it. */
204 ctx = silc_server_command_alloc();
205 ctx->server = server;
207 ctx->packet = packet; /* Save original packet */
208 silc_packet_stream_ref(sock);
210 /* Parse the command payload in the packet */
211 ctx->payload = silc_command_payload_parse(packet->buffer.data,
212 silc_buffer_len(&packet->buffer));
214 SILC_LOG_ERROR(("Bad command payload"));
215 silc_packet_free(packet);
216 silc_packet_stream_unref(ctx->sock);
220 ctx->args = silc_command_get_args(ctx->payload);
222 /* Get the command */
223 command = silc_command_get(ctx->payload);
224 for (cmd = silc_command_list; cmd->cb; cmd++)
225 if (cmd->cmd == command)
228 if (!cmd || !cmd->cb) {
229 SILC_LOG_DEBUG(("Unknown command %d", command));
230 silc_server_command_send_status_reply(ctx, command,
231 SILC_STATUS_ERR_UNKNOWN_COMMAND, 0);
232 silc_packet_free(packet);
233 silc_packet_stream_unref(ctx->sock);
238 /* Execute client's commands always with timeout. Normally they are
239 executed with zero (0) timeout but if client is sending command more
240 frequently than once in 2 seconds, then the timeout may be 0 to 2
242 if (idata->conn_type == SILC_CONN_CLIENT) {
243 SilcClientEntry client = silc_packet_get_context(sock);
244 SilcServerCommandTimeout timeout;
247 timeout = silc_calloc(1, sizeof(*timeout));
251 if (client->last_command && (time(NULL) - client->last_command) < 2) {
252 client->fast_command++;
255 if (client->fast_command - 2 <= 0)
256 client->fast_command = 0;
258 client->fast_command -= 2;
262 if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
263 (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
264 silc_schedule_task_add_timeout(
266 silc_server_command_process_timeout, timeout,
267 (client->fast_command < 3 ? 0 :
268 2 - (time(NULL) - client->last_command)),
269 (client->fast_command < 3 ? 200000 : 0));
271 silc_schedule_task_add_timeout(server->schedule,
272 silc_server_command_process_timeout,
277 /* Execute for server */
279 if (!(cmd->flags & SILC_CF_REG)) {
280 SILC_LOG_DEBUG(("Calling %s command", silc_get_command_name(cmd->cmd)));
282 } else if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) {
283 SILC_LOG_DEBUG(("Calling %s command", silc_get_command_name(cmd->cmd)));
286 SILC_LOG_DEBUG(("Server is not registered"));
287 silc_server_command_free(ctx);
291 /* Allocate Command Context */
293 SilcServerCommandContext silc_server_command_alloc()
295 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
300 /* Free's the command context allocated before executing the command */
302 void silc_server_command_free(SilcServerCommandContext ctx)
305 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
307 if (ctx->users < 1) {
309 silc_command_payload_free(ctx->payload);
311 silc_packet_free(ctx->packet);
313 silc_packet_stream_unref(ctx->sock);
318 /* Duplicate Command Context by adding reference counter. The context won't
319 be free'd untill it hits zero. */
321 SilcServerCommandContext
322 silc_server_command_dup(SilcServerCommandContext ctx)
325 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
330 /* Timeout for pending command. If reply to pending command never arrives
331 this is called to free resources. */
333 SILC_TASK_CALLBACK(silc_server_command_pending_timeout)
335 SilcServer server = app_context;
336 SilcServerCommandPending *reply = context;
337 SilcServerCommandReplyContext cmdr;
341 SILC_LOG_DEBUG(("Timeout pending command %p", reply));
343 /* Allocate temporary and bogus command reply context */
344 cmdr = silc_calloc(1, sizeof(*cmdr));
345 cmdr->server = server;
346 cmdr->ident = reply->ident;
348 /* Check for pending commands and mark to be exeucted */
350 silc_server_command_pending_check(server, reply->reply_cmd,
351 reply->ident, &cmdr->callbacks_count);
353 /* Create bogus command reply with an error inside */
355 silc_command_reply_payload_encode_va(reply->reply_cmd ? reply->reply_cmd :
356 SILC_COMMAND_RESERVED,
357 SILC_STATUS_ERR_TIMEDOUT, 0,
359 cmdr->payload = silc_command_payload_parse(tmpreply->data,
360 silc_buffer_len(tmpreply));
361 silc_buffer_free(tmpreply);
363 /* Call all callbacks. Same as SILC_SERVER_PENDING_EXEC macro. */
364 for (i = 0; i < cmdr->callbacks_count; i++)
365 if (cmdr->callbacks[i].callback)
366 (*cmdr->callbacks[i].callback)(cmdr->callbacks[i].context, cmdr);
368 silc_server_command_pending_del(server, reply->reply_cmd, reply->ident);
369 silc_server_command_reply_free(cmdr);
372 /* Add new pending command to be executed when reply to a command has been
373 received. The `reply_cmd' is the command that will call the `callback'
374 with `context' when reply has been received. It can be SILC_COMMAND_NONE
375 to match any command with the `ident'. If `ident' is non-zero
376 the `callback' will be executed when received reply with command
377 identifier `ident'. If there already exists pending command for the
378 specified command, ident, callback and context this function has no
381 SilcBool silc_server_command_pending(SilcServer server,
382 SilcCommand reply_cmd,
384 SilcCommandCb callback,
387 return silc_server_command_pending_timed(server, reply_cmd, ident, callback,
391 /* Same as silc_server_command_pending with specific timeout for pending
392 commands. If the `timeout' is zero default timeout is used. */
394 SilcBool silc_server_command_pending_timed(SilcServer server,
395 SilcCommand reply_cmd,
397 SilcCommandCb callback,
401 SilcServerCommandPending *reply;
403 /* Check whether identical pending already exists for same command,
404 ident, callback and callback context. If it does then it would be
405 error to register it again. */
406 silc_dlist_start(server->pending_commands);
407 while ((reply = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
408 if (reply->reply_cmd == reply_cmd && reply->ident == ident &&
409 reply->callback == callback && reply->context == context)
413 reply = silc_calloc(1, sizeof(*reply));
414 reply->reply_cmd = reply_cmd;
415 reply->ident = ident;
416 reply->context = context;
417 reply->callback = callback;
419 silc_schedule_task_add_timeout(server->schedule,
420 silc_server_command_pending_timeout, reply,
421 timeout ? timeout : 12, 0);
422 silc_dlist_add(server->pending_commands, reply);
427 /* Deletes pending command by reply command type. */
429 void silc_server_command_pending_del(SilcServer server,
430 SilcCommand reply_cmd,
433 SilcServerCommandPending *r;
435 silc_dlist_start(server->pending_commands);
436 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
437 if ((r->reply_cmd == reply_cmd || (r->reply_cmd == SILC_COMMAND_NONE &&
439 && r->ident == ident) {
440 silc_dlist_del(server->pending_commands, r);
442 silc_schedule_task_del(server->schedule, r->timeout);
448 /* Checks for pending commands and marks callbacks to be called from
449 the command reply function. Returns TRUE if there were pending command. */
451 SilcServerCommandPendingCallbacks
452 silc_server_command_pending_check(SilcServer server,
455 SilcUInt32 *callbacks_count)
457 SilcServerCommandPending *r;
458 SilcServerCommandPendingCallbacks callbacks = NULL;
461 silc_dlist_start(server->pending_commands);
462 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
463 if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE)
464 && r->ident == ident) {
465 callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
466 callbacks[i].context = r->context;
467 callbacks[i].callback = r->callback;
468 r->reply_check = TRUE;
473 *callbacks_count = i;
477 /* Sends simple status message as command reply packet */
480 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
488 cmd->server->stat.commands_sent++;
490 SILC_LOG_DEBUG(("Sending command status %d", status));
493 silc_command_reply_payload_encode_va(command, status, error,
494 silc_command_get_ident(cmd->payload),
496 silc_server_packet_send(cmd->server, cmd->sock,
497 SILC_PACKET_COMMAND_REPLY, 0,
498 buffer->data, silc_buffer_len(buffer));
499 silc_buffer_free(buffer);
502 /* Sends command status reply with one extra argument. The argument
503 type must be sent as argument. */
506 silc_server_command_send_status_data(SilcServerCommandContext cmd,
511 const unsigned char *arg,
517 cmd->server->stat.commands_sent++;
519 SILC_LOG_DEBUG(("Sending command status %d", status));
522 silc_command_reply_payload_encode_va(command, status, 0,
523 silc_command_get_ident(cmd->payload),
524 1, arg_type, arg, arg_len);
525 silc_server_packet_send(cmd->server, cmd->sock,
526 SILC_PACKET_COMMAND_REPLY, 0,
527 buffer->data, silc_buffer_len(buffer));
528 silc_buffer_free(buffer);
532 silc_server_command_send_status_data2(SilcServerCommandContext cmd,
536 SilcUInt32 arg_type1,
537 const unsigned char *arg1,
539 SilcUInt32 arg_type2,
540 const unsigned char *arg2,
546 cmd->server->stat.commands_sent++;
548 SILC_LOG_DEBUG(("Sending command status %d", status));
551 silc_command_reply_payload_encode_va(command, status, 0,
552 silc_command_get_ident(cmd->payload),
553 2, arg_type1, arg1, arg_len1,
554 arg_type2, arg2, arg_len2);
555 silc_server_packet_send(cmd->server, cmd->sock,
556 SILC_PACKET_COMMAND_REPLY, 0,
557 buffer->data, silc_buffer_len(buffer));
558 silc_buffer_free(buffer);
561 /* This function can be called to check whether in the command reply
562 an error occurred. This function has no effect if this is called
563 when the command function was not called as pending command callback.
564 This returns TRUE if error had occurred. */
567 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
568 SilcServerCommandReplyContext cmdr,
571 if (!cmd->pending || !cmdr)
574 if (!silc_command_get_status(cmdr->payload, NULL, NULL)) {
578 cmd->server->stat.commands_sent++;
580 /* Send the same command reply payload */
581 silc_command_set_command(cmdr->payload, silc_command_get(cmd->payload));
582 silc_command_set_ident(cmdr->payload,
583 silc_command_get_ident(cmd->payload));
584 buffer = silc_command_payload_encode_payload(cmdr->payload);
585 silc_server_packet_send(cmd->server, cmd->sock,
586 SILC_PACKET_COMMAND_REPLY, 0,
587 buffer->data, silc_buffer_len(buffer));
588 silc_buffer_free(buffer);
595 /* Server side of command WHOIS. */
597 SILC_SERVER_CMD_FUNC(whois)
599 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
600 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 256);
601 silc_server_query_command(cmd->server, SILC_COMMAND_WHOIS, cmd, NULL);
602 silc_server_command_free(cmd);
605 /* Server side of command WHOWAS. */
607 SILC_SERVER_CMD_FUNC(whowas)
609 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
610 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
611 silc_server_query_command(cmd->server, SILC_COMMAND_WHOWAS, cmd, NULL);
612 silc_server_command_free(cmd);
615 /* Server side of command IDENTIFY. */
617 SILC_SERVER_CMD_FUNC(identify)
619 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
620 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 256);
621 silc_server_query_command(cmd->server, SILC_COMMAND_IDENTIFY, cmd, NULL);
622 silc_server_command_free(cmd);
625 /* Server side of command NICK. Sets nickname for user. Setting
626 nickname causes generation of a new client ID for the client. The
627 new client ID is sent to the client after changing the nickname. */
629 SILC_SERVER_CMD_FUNC(nick)
631 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
632 SilcClientEntry client = silc_packet_get_context(cmd->sock);
633 SilcServer server = cmd->server;
634 SilcBuffer nidp, oidp = NULL;
635 SilcClientID *new_id;
637 unsigned char *nick, *nickc = NULL;
638 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
640 if (client->data.conn_type != SILC_CONN_CLIENT || !client)
643 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
646 nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
648 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
649 SILC_STATUS_ERR_BAD_NICKNAME, 0);
653 /* Truncate over long nicks */
654 if (nick_len > 128) {
656 nick[nick_len - 1] = '\0';
659 /* Check for valid nickname string. This is cached, original is saved
660 in the client context. */
661 nickc = silc_identifier_check(nick, nick_len, SILC_STRING_UTF8, 128, NULL);
663 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
664 SILC_STATUS_ERR_BAD_NICKNAME, 0);
668 /* Check for same nickname */
669 if (strlen(client->nickname) == nick_len &&
670 !memcmp(client->nickname, nick, nick_len)) {
671 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
676 /* Create new Client ID */
677 if (!silc_id_create_client_id(cmd->server, cmd->server->id,
679 cmd->server->md5hash,
680 nickc, strlen(nickc), &new_id)) {
681 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
682 SILC_STATUS_ERR_BAD_NICKNAME, 0);
687 /* Send notify about nickname change to our router. We send the new
688 ID and ask to replace it with the old one. If we are router the
689 packet is broadcasted. Send NICK_CHANGE notify. */
690 silc_server_send_notify_nick_change(server, SILC_PRIMARY_ROUTE(server),
691 SILC_BROADCAST(server), client->id,
694 /* Check if anyone is watching the old nickname */
695 if (server->server_type == SILC_ROUTER)
696 silc_server_check_watcher_list(server, client, nick,
697 SILC_NOTIFY_TYPE_NICK_CHANGE);
699 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
701 /* Update client entry */
702 silc_idcache_update_by_context(server->local_list->clients, client,
703 new_id, nickc, TRUE);
705 silc_free(client->nickname);
706 client->nickname = strdup(nick);
708 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
710 /* Send NICK_CHANGE notify to the client's channels */
711 silc_server_send_notify_on_channels(server, NULL, client,
712 SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
713 oidp->data, silc_buffer_len(oidp),
714 nidp->data, silc_buffer_len(nidp),
716 strlen(client->nickname));
718 /* Check if anyone is watching the new nickname */
719 if (server->server_type == SILC_ROUTER)
720 silc_server_check_watcher_list(server, client, NULL,
721 SILC_NOTIFY_TYPE_NICK_CHANGE);
724 /* Send the new Client ID as reply command back to client */
725 silc_server_send_command_reply(cmd->server, cmd->sock,
727 SILC_STATUS_OK, 0, ident, 2,
728 2, nidp->data, silc_buffer_len(nidp),
730 silc_buffer_free(nidp);
732 silc_buffer_free(oidp);
735 silc_server_command_free(cmd);
738 /* Sends the LIST command reply */
741 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
742 SilcChannelEntry *lch,
743 SilcUInt32 lch_count,
744 SilcChannelEntry *gch,
745 SilcUInt32 gch_count)
749 SilcChannelEntry entry;
751 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
753 unsigned char usercount[4];
755 int valid_lcount = 0, valid_rcount = 0;
757 for (i = 0; i < lch_count; i++) {
758 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
763 for (i = 0; i < gch_count; i++) {
764 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
770 if (!lch_count && !gch_count) {
771 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
776 status = SILC_STATUS_OK;
777 if ((lch_count + gch_count) > 1)
778 status = SILC_STATUS_LIST_START;
781 for (i = 0, k = 0; i < lch_count; i++) {
787 status = SILC_STATUS_LIST_ITEM;
788 if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
789 status = SILC_STATUS_LIST_END;
791 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
793 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
795 memset(usercount, 0, sizeof(usercount));
797 topic = entry->topic;
798 users = silc_hash_table_count(entry->user_list);
799 SILC_PUT32_MSB(users, usercount);
803 silc_server_send_command_reply(cmd->server, cmd->sock, SILC_COMMAND_LIST,
805 2, idp->data, silc_buffer_len(idp),
806 3, entry->channel_name,
807 strlen(entry->channel_name),
808 4, topic, topic ? strlen(topic) : 0,
810 silc_buffer_free(idp);
815 for (i = 0, k = 0; i < gch_count; i++) {
821 status = SILC_STATUS_LIST_ITEM;
822 if (valid_rcount > 1 && k == valid_rcount - 1)
823 status = SILC_STATUS_LIST_END;
825 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
827 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
829 memset(usercount, 0, sizeof(usercount));
831 topic = entry->topic;
832 users = entry->user_count;
833 SILC_PUT32_MSB(users, usercount);
837 silc_server_send_command_reply(cmd->server, cmd->sock, SILC_COMMAND_LIST,
839 2, idp->data, silc_buffer_len(idp),
840 3, entry->channel_name,
841 strlen(entry->channel_name),
842 4, topic, topic ? strlen(topic) : 0,
844 silc_buffer_free(idp);
849 /* Server side of LIST command. This lists the channel of the requested
850 server. Secret channels are not listed. */
852 SILC_SERVER_CMD_FUNC(list)
854 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
855 SilcServer server = cmd->server;
857 SilcChannelID *channel_id = NULL;
858 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
859 SilcUInt32 lch_count = 0, gch_count = 0;
861 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
863 /* If we are normal server, send the command to router, since we
864 want to know all channels in the network. */
865 if (!cmd->pending && server->server_type != SILC_ROUTER &&
866 !server->standalone) {
868 SilcUInt16 old_ident;
871 cmd->server->stat.commands_sent++;
873 old_ident = silc_command_get_ident(cmd->payload);
874 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
875 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
876 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
877 SILC_PACKET_COMMAND, cmd->packet->flags,
878 tmpbuf->data, silc_buffer_len(tmpbuf));
880 /* Reprocess this packet after received reply from router */
881 silc_server_command_pending(server, SILC_COMMAND_LIST,
882 silc_command_get_ident(cmd->payload),
883 silc_server_command_list,
884 silc_server_command_dup(cmd));
886 silc_command_set_ident(cmd->payload, old_ident);
887 silc_buffer_free(tmpbuf);
892 if (silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL))
893 channel_id = SILC_ID_GET_ID(id);
895 /* Get the channels from local list */
896 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
899 /* Get the channels from global list */
900 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
904 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
905 gchannels, gch_count);
907 silc_free(lchannels);
908 silc_free(gchannels);
911 silc_server_command_free(cmd);
914 /* Server side of TOPIC command. Sets topic for channel and/or returns
915 current topic to client. */
917 SILC_SERVER_CMD_FUNC(topic)
919 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
920 SilcServer server = cmd->server;
921 SilcClientEntry client = silc_packet_get_context(cmd->sock);
923 SilcChannelEntry channel;
924 SilcChannelClientEntry chl;
927 SilcUInt32 argc, tmp_len;
928 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
930 if (client->data.conn_type != SILC_CONN_CLIENT || !client)
933 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
935 argc = silc_argument_get_arg_num(cmd->args);
938 if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
939 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
940 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
944 /* Check whether the channel exists */
945 channel = silc_idlist_find_channel_by_id(server->local_list,
946 SILC_ID_GET_ID(id), NULL);
948 channel = silc_idlist_find_channel_by_id(server->global_list,
949 SILC_ID_GET_ID(id), NULL);
951 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
952 silc_server_command_send_status_data(cmd, SILC_COMMAND_TOPIC,
953 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
961 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
963 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
964 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
970 tmp[tmp_len - 1] = '\0';
973 if (!silc_utf8_valid(tmp, tmp_len)) {
974 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
975 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
980 /* See whether the client is on channel and has rights to change topic */
981 if (!silc_server_client_on_channel(client, channel, &chl)) {
982 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
983 silc_server_command_send_status_data(cmd, SILC_COMMAND_TOPIC,
984 SILC_STATUS_ERR_NOT_ON_CHANNEL,
989 if (channel->mode & SILC_CHANNEL_MODE_TOPIC &&
990 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
991 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
992 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
993 silc_server_command_send_status_data(cmd, SILC_COMMAND_TOPIC,
994 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
999 if (!channel->topic || strcmp(channel->topic, tmp)) {
1000 /* Set the topic for channel */
1001 silc_free(channel->topic);
1002 channel->topic = strdup(tmp);
1004 /* Send TOPIC_SET notify type to the network */
1005 silc_server_send_notify_topic_set(server, SILC_PRIMARY_ROUTE(server),
1006 SILC_BROADCAST(server), channel,
1007 client->id, SILC_ID_CLIENT,
1010 /* Send notify about topic change to all clients on the channel */
1011 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1012 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
1013 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
1014 idp->data, silc_buffer_len(idp),
1016 strlen(channel->topic));
1017 silc_buffer_free(idp);
1021 /* Send the topic to client as reply packet */
1022 idp = silc_id_payload_encode(SILC_ID_GET_ID(id), SILC_ID_CHANNEL);
1023 silc_server_send_command_reply(cmd->server, cmd->sock, SILC_COMMAND_TOPIC,
1024 SILC_STATUS_OK, 0, ident, 2,
1025 2, idp->data, silc_buffer_len(idp),
1028 strlen(channel->topic) : 0);
1029 silc_buffer_free(idp);
1032 silc_server_command_free(cmd);
1035 /* Server side of INVITE command. Invites some client to join some channel.
1036 This command is also used to manage the invite list of the channel. */
1038 SILC_SERVER_CMD_FUNC(invite)
1040 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1041 SilcServer server = cmd->server;
1042 SilcPacketStream sock = cmd->sock, dest_sock;
1043 SilcChannelClientEntry chl;
1044 SilcClientEntry sender, dest;
1045 SilcChannelEntry channel;
1047 SilcIDListData idata;
1048 SilcArgumentPayload args;
1049 SilcHashTableList htl;
1050 SilcBuffer list, tmp2;
1051 SilcBufferStruct alist;
1052 unsigned char *tmp, *atype = NULL;
1053 SilcUInt32 len, len2, ttype;
1055 SilcUInt16 argc = 0, ident = silc_command_get_ident(cmd->payload);
1057 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
1059 /* Get Channel ID */
1060 if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
1061 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1062 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
1066 /* Get the channel entry */
1067 channel = silc_idlist_find_channel_by_id(server->local_list,
1068 SILC_ID_GET_ID(id), NULL);
1070 channel = silc_idlist_find_channel_by_id(server->global_list,
1071 SILC_ID_GET_ID(id), NULL);
1073 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1074 silc_server_command_send_status_data(cmd, SILC_COMMAND_INVITE,
1075 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
1081 /* Check whether the sender of this command is on the channel. */
1082 sender = silc_packet_get_context(sock);
1083 if (!sender || !silc_server_client_on_channel(sender, channel, &chl)) {
1084 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1085 silc_server_command_send_status_data(cmd, SILC_COMMAND_INVITE,
1086 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
1091 /* Check whether the channel is invite-only channel. If yes then the
1092 sender of this command must be at least channel operator. */
1093 if (channel->mode & SILC_CHANNEL_MODE_INVITE &&
1094 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
1095 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
1096 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1097 silc_server_command_send_status_data(cmd, SILC_COMMAND_INVITE,
1098 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
1103 /* Get destination client ID */
1104 if (silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id2, NULL)) {
1107 /* Get the client entry */
1108 dest = silc_server_query_client(server, SILC_ID_GET_ID(id2),
1111 if (server->server_type != SILC_SERVER || !resolve || cmd->pending) {
1112 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1113 silc_server_command_send_status_data(
1114 cmd, SILC_COMMAND_INVITE,
1115 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0,
1120 /* The client info is being resolved. Reprocess this packet after
1121 receiving the reply to the query. */
1122 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1124 silc_server_command_invite,
1125 silc_server_command_dup(cmd));
1126 cmd->pending = TRUE;
1130 /* Check whether the requested client is already on the channel. */
1131 if (silc_server_client_on_channel(dest, channel, NULL)) {
1132 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1133 atype = silc_argument_get_arg_type(cmd->args, 1, &len2);
1134 silc_server_command_send_status_data2(cmd, SILC_COMMAND_INVITE,
1135 SILC_STATUS_ERR_USER_ON_CHANNEL,
1141 /* Get route to the client */
1142 dest_sock = silc_server_get_client_route(server, NULL, 0,
1143 SILC_ID_GET_ID(id2),
1146 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1147 silc_server_command_send_status_data(cmd, SILC_COMMAND_INVITE,
1148 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1153 /* Add the client to the invite list */
1155 /* Allocate hash table for invite list if it doesn't exist yet */
1156 if (!channel->invite_list)
1157 channel->invite_list =
1158 silc_hash_table_alloc(0, silc_hash_ptr,
1160 silc_server_inviteban_destruct, channel, TRUE);
1162 /* Check if the ID is in the list already */
1163 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1164 silc_hash_table_list(channel->invite_list, &htl);
1165 while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) {
1166 if (SILC_PTR_TO_32(type) == 3 && !memcmp(tmp2->data, tmp, len)) {
1171 silc_hash_table_list_reset(&htl);
1173 /* Add new Client ID to invite list */
1175 list = silc_buffer_alloc_size(len);
1176 silc_buffer_put(list, tmp, len);
1177 silc_hash_table_add(channel->invite_list, (void *)3, list);
1180 if (!(dest->mode & SILC_UMODE_BLOCK_INVITE)) {
1181 /* Send notify to the client that is invited to the channel */
1182 SilcBuffer idp, idp2;
1183 idp = silc_id_payload_encode(SILC_ID_GET_ID(id), SILC_ID_CHANNEL);
1184 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1185 silc_server_send_notify_dest(server, dest_sock, FALSE,
1186 SILC_ID_GET_ID(id2), SILC_ID_CLIENT,
1187 SILC_NOTIFY_TYPE_INVITE, 3,
1188 idp->data, silc_buffer_len(idp),
1189 channel->channel_name,
1190 strlen(channel->channel_name),
1191 idp2->data, silc_buffer_len(idp2));
1192 silc_buffer_free(idp);
1193 silc_buffer_free(idp2);
1197 /* Get the invite information */
1198 tmp = silc_argument_get_arg_type(cmd->args, 4, &len2);
1199 if (tmp && len2 > 2) {
1200 /* Parse the arguments to see they are constructed correctly */
1201 SILC_GET16_MSB(argc, tmp);
1202 args = silc_argument_payload_parse(tmp + 2, len2 - 2, argc);
1204 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1205 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1210 /* Get the type of action */
1211 atype = silc_argument_get_arg_type(cmd->args, 3, &len);
1212 if (atype && len == 1) {
1213 if (atype[0] == 0x00) {
1214 /* Allocate hash table for invite list if it doesn't exist yet */
1215 if (!channel->invite_list)
1216 channel->invite_list =
1217 silc_hash_table_alloc(0, silc_hash_ptr,
1219 silc_server_inviteban_destruct, channel,
1222 /* Check for resource limit */
1223 if (silc_hash_table_count(channel->invite_list) > 64) {
1224 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1225 SILC_STATUS_ERR_RESOURCE_LIMIT,
1231 /* Now add or delete the information. */
1232 if (!silc_server_inviteban_process(server, channel->invite_list,
1233 (SilcUInt8)atype[0], args)) {
1234 silc_server_command_send_status_reply(
1235 cmd, SILC_COMMAND_INVITE,
1236 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1241 silc_argument_payload_free(args);
1244 /* Encode invite list */
1246 if (channel->invite_list && silc_hash_table_count(channel->invite_list)) {
1247 list = silc_buffer_alloc_size(2);
1248 silc_buffer_format(list,
1249 SILC_STR_UI_SHORT(silc_hash_table_count(
1250 channel->invite_list)),
1252 silc_hash_table_list(channel->invite_list, &htl);
1253 while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2))
1254 list = silc_argument_payload_encode_one(list, tmp2->data,
1255 silc_buffer_len(tmp2),
1256 SILC_PTR_TO_32(type));
1257 silc_hash_table_list_reset(&htl);
1260 /* The notify is sent to local servers (not clients), and to network. */
1261 if (atype && tmp && len2) {
1262 silc_buffer_set(&alist, tmp, len2);
1264 /* Send to local servers if we are router */
1265 if (server->server_type == SILC_ROUTER) {
1266 SilcBuffer idp, idp2;
1267 idp = silc_id_payload_encode(SILC_ID_GET_ID(id), SILC_ID_CHANNEL);
1268 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1269 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, FALSE,
1270 SILC_NOTIFY_TYPE_INVITE, 5,
1271 idp->data, silc_buffer_len(idp),
1272 channel->channel_name,
1273 strlen(channel->channel_name),
1274 idp2->data, silc_buffer_len(idp2),
1276 tmp ? alist.data : NULL,
1277 tmp ? silc_buffer_len(&alist) : 0);
1278 silc_buffer_free(idp);
1279 silc_buffer_free(idp2);
1282 /* Send to network */
1283 silc_server_send_notify_invite(server, SILC_PRIMARY_ROUTE(server),
1284 SILC_BROADCAST(server), channel,
1286 tmp ? &alist : NULL);
1289 /* Send invite list back only if the list was modified, or no arguments
1292 argc = silc_argument_get_arg_num(cmd->args);
1295 if (silc_argument_get_arg_type(cmd->args, 3, &len))
1298 /* Send command reply */
1299 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1300 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_INVITE,
1301 SILC_STATUS_OK, 0, ident, 2,
1305 ttype && list ? silc_buffer_len(list) : 0);
1306 silc_buffer_free(list);
1309 silc_server_command_free(cmd);
1313 SilcPacketStream sock;
1317 /* Quits connection to client. This gets called if client won't
1318 close the connection even when it has issued QUIT command. */
1320 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
1322 SilcServer server = app_context;
1323 QuitInternal q = (QuitInternal)context;
1324 SilcClientEntry client = silc_packet_get_context(q->sock);
1327 /* Free all client specific data, such as client entry and entires
1328 on channels this client may be on. */
1329 silc_server_free_sock_user_data(server, q->sock, q->signoff);
1330 silc_server_close_connection(server, q->sock);
1333 silc_packet_stream_unref(q->sock);
1334 silc_free(q->signoff);
1338 /* Quits SILC session. This is the normal way to disconnect client. */
1340 SILC_SERVER_CMD_FUNC(quit)
1342 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1343 SilcServer server = cmd->server;
1344 SilcPacketStream sock = cmd->sock;
1345 SilcClientEntry client = silc_packet_get_context(sock);
1347 unsigned char *tmp = NULL;
1350 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
1352 if (client->data.conn_type != SILC_CONN_CLIENT)
1356 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1360 q = silc_calloc(1, sizeof(*q));
1362 q->signoff = tmp ? strdup(tmp) : NULL;
1363 silc_packet_stream_ref(q->sock);
1365 /* We quit the connection with little timeout */
1366 silc_schedule_task_add_timeout(server->schedule,
1367 silc_server_command_quit_cb, (void *)q,
1371 silc_server_command_free(cmd);
1374 /* Server side of command KILL. This command is used by router operator
1375 to remove an client from the SILC Network temporarily. */
1377 SILC_SERVER_CMD_FUNC(kill)
1379 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1380 SilcServer server = cmd->server;
1381 SilcClientEntry client = silc_packet_get_context(cmd->sock);
1382 SilcClientEntry remote_client;
1384 unsigned char *tmp, *comment, *auth;
1385 SilcUInt32 tmp_len, tmp_len2, auth_len;
1387 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 3);
1389 if (client->data.conn_type != SILC_CONN_CLIENT || !client)
1392 /* Get authentication payload if present */
1393 auth = silc_argument_get_arg_type(cmd->args, 3, &auth_len);
1396 /* Router operator killing */
1398 /* KILL command works only on router */
1399 if (server->server_type != SILC_ROUTER) {
1400 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1401 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
1405 /* Check whether client has the permissions. */
1406 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
1407 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1408 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
1413 /* Get the client ID */
1414 if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
1415 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1416 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
1420 /* Get the client entry */
1421 remote_client = silc_idlist_find_client_by_id(server->local_list,
1424 if (!remote_client) {
1425 remote_client = silc_idlist_find_client_by_id(server->global_list,
1428 if (!remote_client) {
1429 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1430 silc_server_command_send_status_data(cmd, SILC_COMMAND_KILL,
1431 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1432 0, 2, tmp, tmp_len);
1438 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
1439 if (comment && tmp_len2 > 128) {
1441 comment[tmp_len2 - 1] = '\0';
1444 /* If authentication data is provided then verify that killing is
1446 if (auth && auth_len) {
1447 SilcPacketStream sock;
1449 if (!SILC_IS_LOCAL(remote_client) || !remote_client->data.public_key) {
1450 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1451 SILC_STATUS_ERR_OPERATION_ALLOWED,
1456 /* Verify the signature */
1457 if (!silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
1458 remote_client->data.public_key, 0,
1459 server->sha1hash, remote_client->id,
1461 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1462 SILC_STATUS_ERR_AUTH_FAILED, 0);
1466 /* Send reply to the sender */
1467 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1468 silc_server_command_send_status_data(cmd, SILC_COMMAND_KILL,
1472 /* Do normal signoff for the destination client */
1473 sock = remote_client->connection;
1476 silc_packet_stream_ref(sock);
1478 silc_server_remove_from_channels(server, NULL, remote_client,
1479 TRUE, (char *)"Killed", TRUE, TRUE);
1480 silc_server_free_sock_user_data(server, sock, comment ? comment :
1481 (unsigned char *)"Killed");
1483 silc_packet_set_context(sock, NULL);
1484 silc_server_close_connection(server, sock);
1485 silc_packet_stream_unref(sock);
1488 /* Router operator killing */
1490 /* Send reply to the sender */
1491 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1492 silc_server_command_send_status_data(cmd, SILC_COMMAND_KILL,
1496 /* Check if anyone is watching this nickname */
1497 if (server->server_type == SILC_ROUTER)
1498 silc_server_check_watcher_list(server, client, NULL,
1499 SILC_NOTIFY_TYPE_KILLED);
1501 /* Now do the killing */
1502 silc_server_kill_client(server, remote_client, comment, client->id,
1507 silc_server_command_free(cmd);
1510 /* Server side of command INFO. This sends information about us to
1511 the client. If client requested specific server we will send the
1512 command to that server. */
1514 SILC_SERVER_CMD_FUNC(info)
1516 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1517 SilcServer server = cmd->server;
1521 char *dest_server = NULL, *server_info = NULL, *server_name;
1522 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1523 SilcServerEntry entry = NULL;
1526 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
1528 /* Get server name */
1529 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1531 /* Check server name. */
1532 dest_server = silc_identifier_check(dest_server, strlen(dest_server),
1533 SILC_STRING_UTF8, 256, &tmp_len);
1535 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1536 SILC_STATUS_ERR_BAD_SERVER, 0);
1542 if (silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL)) {
1543 /* Check whether we have this server cached */
1544 entry = silc_idlist_find_server_by_id(server->local_list,
1545 SILC_ID_GET_ID(id), TRUE, NULL);
1547 entry = silc_idlist_find_server_by_id(server->global_list,
1548 SILC_ID_GET_ID(id), TRUE, NULL);
1549 if (!entry && server->server_type != SILC_SERVER) {
1550 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1551 silc_server_command_send_status_data(cmd, SILC_COMMAND_INFO,
1552 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
1553 0, 2, tmp, tmp_len);
1559 if ((!dest_server && !entry) || (entry && entry == server->id_entry) ||
1560 (dest_server && !cmd->pending &&
1561 !memcmp(dest_server, server->server_name, strlen(dest_server)))) {
1562 /* Send our reply */
1563 char info_string[256];
1565 memset(info_string, 0, sizeof(info_string));
1566 silc_snprintf(info_string, sizeof(info_string),
1567 "location: %s server: %s admin: %s <%s> version: %s",
1568 server->config->server_info->location,
1569 server->config->server_info->server_type,
1570 server->config->server_info->admin,
1571 server->config->server_info->email,
1574 server_info = info_string;
1575 entry = server->id_entry;
1577 /* Check whether we have this server cached */
1578 if (!entry && dest_server) {
1579 entry = silc_idlist_find_server_by_name(server->global_list,
1580 dest_server, TRUE, NULL);
1582 entry = silc_idlist_find_server_by_name(server->local_list,
1583 dest_server, TRUE, NULL);
1587 if (!cmd->pending &&
1588 server->server_type != SILC_SERVER && entry && !entry->server_info) {
1589 /* Send to the server */
1591 SilcUInt16 old_ident;
1594 cmd->server->stat.commands_sent++;
1596 old_ident = silc_command_get_ident(cmd->payload);
1597 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1598 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1600 silc_server_packet_send(server, entry->connection,
1601 SILC_PACKET_COMMAND, cmd->packet->flags,
1602 tmpbuf->data, silc_buffer_len(tmpbuf));
1604 /* Reprocess this packet after received reply from router */
1605 silc_server_command_pending(server, SILC_COMMAND_INFO,
1606 silc_command_get_ident(cmd->payload),
1607 silc_server_command_info,
1608 silc_server_command_dup(cmd));
1609 cmd->pending = TRUE;
1610 silc_command_set_ident(cmd->payload, old_ident);
1611 silc_buffer_free(tmpbuf);
1615 if (!entry && !cmd->pending && !server->standalone) {
1616 /* Send to the primary router */
1618 SilcUInt16 old_ident;
1621 cmd->server->stat.commands_sent++;
1623 old_ident = silc_command_get_ident(cmd->payload);
1624 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1625 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1627 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
1628 SILC_PACKET_COMMAND, cmd->packet->flags,
1629 tmpbuf->data, silc_buffer_len(tmpbuf));
1631 /* Reprocess this packet after received reply from router */
1632 silc_server_command_pending(server, SILC_COMMAND_INFO,
1633 silc_command_get_ident(cmd->payload),
1634 silc_server_command_info,
1635 silc_server_command_dup(cmd));
1636 cmd->pending = TRUE;
1637 silc_command_set_ident(cmd->payload, old_ident);
1638 silc_buffer_free(tmpbuf);
1645 silc_free(dest_server);
1646 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1647 silc_server_command_send_status_data(cmd, SILC_COMMAND_INFO,
1648 SILC_STATUS_ERR_NO_SUCH_SERVER, 0,
1650 strlen(dest_server));
1656 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1658 server_info = entry->server_info;
1659 server_name = entry->server_name;
1661 /* Send the reply */
1662 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_INFO,
1663 SILC_STATUS_OK, 0, ident, 3,
1664 2, idp->data, silc_buffer_len(idp),
1666 strlen(server_name),
1669 strlen(server_info) : 0);
1670 silc_buffer_free(idp);
1673 silc_free(dest_server);
1674 silc_server_command_free(cmd);
1677 /* Server side of command PING. This just replies to the ping. */
1679 SILC_SERVER_CMD_FUNC(ping)
1681 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1682 SilcServer server = cmd->server;
1687 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PING, cmd, 1, 1);
1690 if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
1691 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1692 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1697 if (SILC_ID_SERVER_COMPARE(SILC_ID_GET_ID(id), server->id)) {
1698 /* Send our reply */
1699 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1702 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1703 silc_server_command_send_status_data(cmd, SILC_COMMAND_PING,
1704 SILC_STATUS_ERR_NO_SUCH_SERVER_ID, 0,
1710 silc_server_command_free(cmd);
1713 /* Server side of command STATS. */
1715 SILC_SERVER_CMD_FUNC(stats)
1717 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1718 SilcServer server = cmd->server;
1722 SilcBuffer packet, stats;
1723 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1726 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1);
1729 if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
1730 silc_server_command_send_status_reply(cmd, SILC_COMMAND_STATS,
1731 SILC_STATUS_ERR_NO_SERVER_ID, 0);
1735 SILC_LOG_DEBUG(("id %s", silc_id_render(SILC_ID_GET_ID(id),
1738 /* The ID must be ours */
1739 if (!SILC_ID_SERVER_COMPARE(server->id, SILC_ID_GET_ID(id))) {
1740 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1741 silc_server_command_send_status_data(cmd, SILC_COMMAND_STATS,
1742 SILC_STATUS_ERR_NO_SUCH_SERVER_ID, 0,
1747 /* If we are router then just send everything we got. If we are normal
1748 server then we'll send this to our router to get all the latest
1749 statistical information. */
1750 if (!cmd->pending && server->server_type != SILC_ROUTER &&
1751 !server->standalone) {
1755 cmd->server->stat.commands_sent++;
1757 /* Send request to our router */
1758 idp = silc_id_payload_encode(server->router->id,
1760 packet = silc_command_payload_encode_va(SILC_COMMAND_STATS,
1761 ++server->cmd_ident, 1,
1763 silc_buffer_len(idp));
1764 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
1765 SILC_PACKET_COMMAND, 0, packet->data,
1766 silc_buffer_len(packet));
1768 /* Reprocess this packet after received reply from router */
1769 silc_server_command_pending(server, SILC_COMMAND_STATS,
1771 silc_server_command_stats,
1772 silc_server_command_dup(cmd));
1773 cmd->pending = TRUE;
1774 silc_buffer_free(packet);
1775 silc_buffer_free(idp);
1779 /* Send our reply to sender */
1780 uptime = time(NULL) - server->starttime;
1782 stats = silc_buffer_alloc_size(60);
1783 silc_buffer_format(stats,
1784 SILC_STR_UI_INT(server->starttime),
1785 SILC_STR_UI_INT(uptime),
1786 SILC_STR_UI_INT(server->stat.my_clients),
1787 SILC_STR_UI_INT(server->stat.my_channels),
1788 SILC_STR_UI_INT(server->stat.my_server_ops),
1789 SILC_STR_UI_INT(server->stat.my_router_ops),
1790 SILC_STR_UI_INT(server->stat.cell_clients),
1791 SILC_STR_UI_INT(server->stat.cell_channels),
1792 SILC_STR_UI_INT(server->stat.cell_servers),
1793 SILC_STR_UI_INT(server->stat.clients),
1794 SILC_STR_UI_INT(server->stat.channels),
1795 SILC_STR_UI_INT(server->stat.servers),
1796 SILC_STR_UI_INT(server->stat.routers),
1797 SILC_STR_UI_INT(server->stat.server_ops),
1798 SILC_STR_UI_INT(server->stat.router_ops),
1801 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1802 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_STATS,
1803 SILC_STATUS_OK, 0, ident, 2,
1805 3, stats->data, silc_buffer_len(stats));
1806 silc_buffer_free(stats);
1809 silc_server_command_free(cmd);
1812 /* Internal routine to join channel. The channel sent to this function
1813 has been either created or resolved from ID lists. This joins the sent
1814 client to the channel. */
1816 static void silc_server_command_join_channel(SilcServer server,
1817 SilcServerCommandContext cmd,
1818 SilcChannelEntry channel,
1819 SilcClientID *client_id,
1821 SilcBool create_key,
1823 const unsigned char *auth,
1824 SilcUInt32 auth_len,
1825 const unsigned char *cauth,
1826 SilcUInt32 cauth_len)
1828 SilcPacketStream sock = cmd->sock;
1829 SilcIDListData idata = silc_packet_get_context(sock);
1831 SilcUInt32 tmp_len, user_count;
1832 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4], ulimit[4];
1833 SilcClientEntry client;
1834 SilcChannelClientEntry chl;
1835 SilcBuffer reply, chidp, clidp, keyp = NULL;
1836 SilcBuffer user_list, mode_list, invite_list, ban_list;
1837 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1838 char check[512], check2[512];
1840 SilcBool founder = FALSE;
1842 SilcBuffer fkey = NULL, chpklist = NULL;
1843 const char *cipher, *hostname, *ip;
1845 SILC_LOG_DEBUG(("Joining client to channel"));
1850 silc_socket_stream_get_info(silc_packet_stream_get_stream(sock),
1851 NULL, &hostname, &ip, NULL);
1853 /* Get the client entry */
1854 if (idata->conn_type == SILC_CONN_CLIENT) {
1855 client = (SilcClientEntry)idata;
1859 client = silc_server_query_client(server, client_id, FALSE,
1862 if (!resolve || cmd->pending) {
1863 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1864 silc_server_command_send_status_data(
1865 cmd, SILC_COMMAND_JOIN,
1866 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0,
1871 /* The client info is being resolved. Reprocess this packet after
1872 receiving the reply to the query. */
1873 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1875 silc_server_command_join,
1876 silc_server_command_dup(cmd));
1877 cmd->pending = TRUE;
1881 if (!client->data.public_key &&
1882 (auth || cauth || channel->ban_list ||
1883 (channel->mode & SILC_CHANNEL_MODE_INVITE))) {
1884 if (cmd->pending == 2)
1887 /* We must retrieve the client's public key by sending
1888 GETKEY command. Reprocess this packet after receiving the key */
1889 clidp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
1890 silc_server_send_command(server, cmd->sock,
1891 SILC_COMMAND_GETKEY, ++server->cmd_ident,
1892 1, 1, clidp->data, silc_buffer_len(clidp));
1893 silc_buffer_free(clidp);
1894 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
1896 silc_server_command_join,
1897 silc_server_command_dup(cmd));
1902 cmd->pending = FALSE;
1906 * Check founder auth payload if provided. If client can gain founder
1907 * privileges it can override various conditions on joining the channel,
1908 * and can have directly the founder mode set on the channel.
1910 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1911 SilcIDListData idata = (SilcIDListData)client;
1912 SilcChannelClientEntry chl2;
1913 SilcHashTableList htl;
1915 if (channel->founder_key && idata->public_key &&
1916 silc_pkcs_public_key_compare(channel->founder_key,
1917 idata->public_key)) {
1918 /* Check whether the client is to become founder */
1919 if (silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
1920 channel->founder_key, 0, server->sha1hash,
1921 client->id, SILC_ID_CLIENT)) {
1923 /* There cannot be anyone else as founder on the channel now. This
1924 client is definitely the founder due to this authentication */
1925 silc_hash_table_list(channel->user_list, &htl);
1926 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
1927 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
1928 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
1929 silc_server_force_cumode_change(server, NULL, channel, chl2,
1933 silc_hash_table_list_reset(&htl);
1935 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
1942 * Check channel modes
1946 memset(check, 0, sizeof(check));
1947 memset(check2, 0, sizeof(check2));
1948 silc_strncat(check, sizeof(check),
1949 client->nickname, strlen(client->nickname));
1950 silc_strncat(check, sizeof(check), "!", 1);
1951 silc_strncat(check, sizeof(check),
1952 client->username, strlen(client->username));
1953 if (!strchr(client->username, '@')) {
1954 silc_strncat(check, sizeof(check), "@", 1);
1955 silc_strncat(check, sizeof(check),
1956 hostname, strlen(hostname));
1959 silc_strncat(check2, sizeof(check2),
1960 client->nickname, strlen(client->nickname));
1961 if (!strchr(client->nickname, '@')) {
1962 silc_strncat(check2, sizeof(check2), "@", 1);
1963 silc_strncat(check2, sizeof(check2),
1964 SILC_IS_LOCAL(client) ? server->server_name :
1965 client->router->server_name,
1966 SILC_IS_LOCAL(client) ? strlen(server->server_name) :
1967 strlen(client->router->server_name));
1969 silc_strncat(check2, sizeof(check2), "!", 1);
1970 silc_strncat(check2, sizeof(check2),
1971 client->username, strlen(client->username));
1972 if (!strchr(client->username, '@')) {
1973 silc_strncat(check2, sizeof(check2), "@", 1);
1974 silc_strncat(check2, sizeof(check2),
1975 hostname, strlen(hostname));
1978 /* Check invite list if channel is invite-only channel */
1979 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1980 if (!channel->invite_list ||
1981 !silc_hash_table_count(channel->invite_list) ||
1982 (!silc_server_inviteban_match(server, channel->invite_list,
1984 !silc_server_inviteban_match(server, channel->invite_list,
1985 2, client->data.public_key) &&
1986 !silc_server_inviteban_match(server, channel->invite_list,
1987 1, client->nickname) &&
1988 !silc_server_inviteban_match(server, channel->invite_list,
1990 !silc_server_inviteban_match(server, channel->invite_list,
1992 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1993 silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
1994 SILC_STATUS_ERR_NOT_INVITED, 0,
1996 silc_buffer_len(chidp));
1997 silc_buffer_free(chidp);
2002 /* Check ban list if it exists. If the client's nickname, server,
2003 username and/or hostname is in the ban list the access to the
2004 channel is denied. */
2005 if (channel->ban_list && silc_hash_table_count(channel->ban_list)) {
2006 if (silc_server_inviteban_match(server, channel->ban_list,
2008 silc_server_inviteban_match(server, channel->ban_list,
2009 2, client->data.public_key) ||
2010 silc_server_inviteban_match(server, channel->ban_list,
2011 1, client->nickname) ||
2012 silc_server_inviteban_match(server, channel->ban_list,
2014 silc_server_inviteban_match(server, channel->ban_list,
2016 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2017 silc_server_command_send_status_data(
2018 cmd, SILC_COMMAND_JOIN,
2019 SILC_STATUS_ERR_BANNED_FROM_CHANNEL, 0,
2021 silc_buffer_len(chidp));
2022 silc_buffer_free(chidp);
2027 /* Check user count limit if set. */
2028 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
2029 if (silc_hash_table_count(channel->user_list) + 1 >
2030 channel->user_limit) {
2031 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2032 silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
2033 SILC_STATUS_ERR_CHANNEL_IS_FULL,
2035 silc_buffer_len(chidp));
2036 silc_buffer_free(chidp);
2042 /* Check the channel passphrase if set. */
2043 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2044 /* Get passphrase */
2045 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2047 passphrase = silc_memdup(tmp, tmp_len);
2049 if (!passphrase || !channel->passphrase ||
2050 strlen(channel->passphrase) != strlen(passphrase) ||
2051 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
2052 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2053 silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
2054 SILC_STATUS_ERR_BAD_PASSWORD, 0,
2056 silc_buffer_len(chidp));
2057 silc_buffer_free(chidp);
2062 /* Verify channel authentication with channel public keys if set. */
2063 if (channel->mode & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
2064 if (!silc_server_verify_channel_auth(server, channel, client->id,
2065 cauth, cauth_len)) {
2066 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2067 SILC_STATUS_ERR_PERM_DENIED, 0);
2073 * Client is allowed to join to the channel. Make it happen.
2076 /* Check whether the client already is on the channel */
2077 if (silc_server_client_on_channel(client, channel, NULL)) {
2078 clidp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
2079 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2080 silc_server_command_send_status_data2(cmd, SILC_COMMAND_JOIN,
2081 SILC_STATUS_ERR_USER_ON_CHANNEL, 0,
2083 silc_buffer_len(clidp),
2085 silc_buffer_len(chidp));
2086 silc_buffer_free(clidp);
2087 silc_buffer_free(chidp);
2091 /* Generate new channel key as protocol dictates */
2093 if (!silc_server_create_channel_key(server, channel, 0))
2096 /* Send the channel key. This is broadcasted to the channel but is not
2097 sent to the client who is joining to the channel. */
2098 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
2099 silc_server_send_channel_key(server, NULL, channel,
2100 server->server_type == SILC_ROUTER ?
2101 FALSE : !server->standalone);
2104 /* Join the client to the channel by adding it to channel's user list.
2105 Add also the channel to client entry's channels list for fast cross-
2107 chl = silc_calloc(1, sizeof(*chl));
2109 chl->client = client;
2110 chl->channel = channel;
2111 silc_hash_table_add(channel->user_list, client, chl);
2112 silc_hash_table_add(client->channels, channel, chl);
2113 channel->user_count++;
2114 channel->disabled = FALSE;
2116 /* Get users on the channel */
2117 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
2120 /* Encode Client ID Payload of the original client who wants to join */
2121 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2123 /* Encode command reply packet */
2124 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2125 SILC_PUT32_MSB(channel->mode, mode);
2126 SILC_PUT32_MSB(created, tmp2);
2127 SILC_PUT32_MSB(user_count, tmp3);
2128 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2129 SILC_PUT32_MSB(channel->user_limit, ulimit);
2131 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
2132 unsigned char cid[32];
2134 silc_id_id2str(channel->id, SILC_ID_CHANNEL, cid, sizeof(cid), &cid_len);
2135 cipher = silc_cipher_get_name(channel->send_key);
2136 keyp = silc_channel_key_payload_encode(cid_len, cid,
2137 strlen(cipher), cipher,
2138 channel->key_len / 8, channel->key);
2141 if (channel->founder_key)
2142 fkey = silc_public_key_payload_encode(channel->founder_key);
2144 /* Encode invite list */
2146 if (channel->invite_list && silc_hash_table_count(channel->invite_list)) {
2147 SilcHashTableList htl;
2149 invite_list = silc_buffer_alloc_size(2);
2150 silc_buffer_format(invite_list,
2151 SILC_STR_UI_SHORT(silc_hash_table_count(
2152 channel->invite_list)),
2155 silc_hash_table_list(channel->invite_list, &htl);
2156 while (silc_hash_table_get(&htl, (void *)&plen, (void *)&reply))
2157 invite_list = silc_argument_payload_encode_one(invite_list,
2159 silc_buffer_len(reply),
2160 SILC_PTR_TO_32(plen));
2161 silc_hash_table_list_reset(&htl);
2164 /* Encode ban list */
2166 if (channel->ban_list && silc_hash_table_count(channel->ban_list)) {
2167 SilcHashTableList htl;
2169 ban_list = silc_buffer_alloc_size(2);
2170 silc_buffer_format(ban_list,
2171 SILC_STR_UI_SHORT(silc_hash_table_count(
2172 channel->ban_list)),
2175 silc_hash_table_list(channel->ban_list, &htl);
2176 while (silc_hash_table_get(&htl, (void *)&plen, (void *)&reply))
2177 ban_list = silc_argument_payload_encode_one(ban_list,
2179 silc_buffer_len(reply),
2180 SILC_PTR_TO_32(plen));
2181 silc_hash_table_list_reset(&htl);
2184 if (channel->channel_pubkeys)
2185 chpklist = silc_server_get_channel_pk_list(server, channel, FALSE, FALSE);
2188 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2189 SILC_STATUS_OK, 0, ident, 16,
2190 2, channel->channel_name,
2191 strlen(channel->channel_name),
2193 silc_buffer_len(chidp),
2195 silc_buffer_len(clidp),
2198 7, keyp ? keyp->data : NULL,
2199 keyp ? silc_buffer_len(keyp) : 0,
2200 8, ban_list ? ban_list->data : NULL,
2202 silc_buffer_len(ban_list): 0,
2203 9, invite_list ? invite_list->data :
2206 silc_buffer_len(invite_list) : 0,
2209 strlen(channel->topic) : 0,
2210 11, silc_hmac_get_name(channel->hmac),
2211 strlen(silc_hmac_get_name(channel->
2214 13, user_list->data,
2215 silc_buffer_len(user_list),
2216 14, mode_list->data,
2217 silc_buffer_len(mode_list),
2218 15, fkey ? fkey->data : NULL,
2219 fkey ? silc_buffer_len(fkey) : 0,
2220 16, chpklist ? chpklist->data : NULL,
2221 chpklist ? silc_buffer_len(chpklist) : 0,
2222 17, (channel->mode &
2223 SILC_CHANNEL_MODE_ULIMIT ?
2226 SILC_CHANNEL_MODE_ULIMIT ?
2227 sizeof(ulimit) : 0));
2229 /* Send command reply */
2230 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
2231 reply->data, silc_buffer_len(reply));
2234 cmd->server->stat.commands_sent++;
2236 /* Send JOIN notify to locally connected clients on the channel. If
2237 we are normal server then router will send or have sent JOIN notify
2238 already. However since we've added the client already to our channel
2239 we'll ignore it (in packet_receive.c) so we must send it here. If
2240 we are router then this will send it to local clients and local
2242 SILC_LOG_DEBUG(("Send JOIN notify to channel"));
2243 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
2244 SILC_NOTIFY_TYPE_JOIN, 2,
2245 clidp->data, silc_buffer_len(clidp),
2246 chidp->data, silc_buffer_len(chidp));
2248 /* Update statistics */
2249 server->stat.my_chanclients++;
2250 if (server->server_type == SILC_ROUTER) {
2251 server->stat.cell_chanclients++;
2252 server->stat.chanclients++;
2255 if (!cmd->pending) {
2256 /* Send JOIN notify packet to our primary router */
2257 silc_server_send_notify_join(server, SILC_PRIMARY_ROUTE(server),
2258 SILC_BROADCAST(server), channel, client->id);
2261 /* Distribute the channel key to all backup routers. */
2262 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
2263 keyp->data, silc_buffer_len(keyp), FALSE, TRUE);
2265 /* If client became founder by providing correct founder auth data
2266 notify the mode change to the channel. */
2268 SILC_PUT32_MSB(chl->mode, mode);
2269 SILC_LOG_DEBUG(("Send CUMODE_CHANGE notify to channel"));
2270 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
2271 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
2273 silc_buffer_len(clidp),
2274 mode, 4, clidp->data,
2275 silc_buffer_len(clidp),
2276 fkey ? fkey->data : NULL,
2277 fkey ? silc_buffer_len(fkey) : 0);
2281 /* Set CUMODE notify type to network */
2283 silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
2284 SILC_BROADCAST(server), channel,
2285 chl->mode, client->id, SILC_ID_CLIENT,
2286 client->id, channel->founder_key);
2288 silc_buffer_free(reply);
2289 silc_buffer_free(clidp);
2290 silc_buffer_free(chidp);
2291 silc_buffer_free(keyp);
2292 silc_buffer_free(user_list);
2293 silc_buffer_free(mode_list);
2294 silc_buffer_free(fkey);
2295 silc_buffer_free(chpklist);
2296 silc_buffer_free(invite_list);
2297 silc_buffer_free(ban_list);
2301 memset(passphrase, 0, strlen(passphrase));
2302 silc_free(passphrase);
2305 /* Server side of command JOIN. Joins client into requested channel. If
2306 the channel does not exist it will be created. */
2308 void silc_server_command_join_connected(SilcServer server,
2309 SilcServerEntry server_entry,
2312 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2314 if (!server_entry) {
2316 unsigned char *tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2319 SILC_LOG_DEBUG(("Connecting to router failed"));
2320 silc_parse_userfqdn(tmp, NULL, 0, serv, sizeof(serv));
2323 silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
2324 SILC_STATUS_ERR_NO_SUCH_SERVER, 0,
2325 2, serv, strlen(serv));
2327 silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
2328 SILC_STATUS_ERR_NO_SUCH_CHANNEL, 0,
2331 silc_server_command_free(cmd);
2335 /* Reprocess command */
2336 SILC_LOG_DEBUG(("Reprocess JOIN after connecting to router"));
2337 silc_server_command_join(cmd, NULL);
2340 SILC_SERVER_CMD_FUNC(join)
2342 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2343 SilcServer server = cmd->server;
2344 SilcIDListData idata = silc_packet_get_context(cmd->sock);
2345 unsigned char *auth, *cauth;
2346 SilcUInt32 tmp_len, auth_len, cauth_len;
2347 char *tmp, *channel_name, *channel_namec = NULL, *cipher, *hmac;
2348 char parsed[256 + 1], serv[256 + 1];
2349 SilcChannelEntry channel;
2350 SilcUInt32 umode = 0;
2351 SilcBool created = FALSE, create_key = TRUE;
2354 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 7);
2356 /* Get channel name */
2357 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2359 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2360 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2365 /* Truncate over long channel names */
2366 if (tmp_len > 256) {
2368 tmp[tmp_len - 1] = '\0';
2371 /* Parse server name from the channel name */
2372 silc_parse_userfqdn(tmp, parsed, sizeof(parsed), serv,
2374 channel_name = parsed;
2376 if (server->config->dynamic_server) {
2377 /* If server name is not specified but local channels is FALSE then the
2378 channel will be global, based on our router name. */
2379 if (!serv[0] && !server->config->local_channels) {
2380 if (!server->standalone) {
2381 silc_snprintf(serv, sizeof(serv), "%s", server->router->server_name);
2383 SilcServerConfigRouter *router;
2384 router = silc_server_config_get_primary_router(server);
2386 /* Create connection to primary router */
2387 SILC_LOG_DEBUG(("Create dynamic connection to primary router %s:%d",
2388 router->host, router->port));
2389 silc_server_create_connection(server, FALSE, TRUE,
2390 router->host, router->port,
2391 silc_server_command_join_connected,
2398 /* If server name is ours, ignore it. */
2399 if (serv[0] && silc_utf8_strcasecmp(serv, server->server_name))
2400 memset(serv, 0, sizeof(serv));
2402 /* Create connection */
2403 if (serv[0] && server->standalone) {
2404 SilcServerConfigRouter *router;
2405 router = silc_server_config_get_primary_router(server);
2407 /* Create connection to primary router */
2408 SILC_LOG_DEBUG(("Create dynamic connection to primary router %s:%d",
2409 router->host, router->port));
2410 silc_server_create_connection(server, FALSE, TRUE,
2411 router->host, router->port,
2412 silc_server_command_join_connected, cmd);
2418 /* Check for valid channel name. This is cached, the original is saved
2419 in the channel context. */
2420 channel_namec = silc_channel_name_check(channel_name, strlen(channel_name),
2421 SILC_STRING_UTF8, 256, NULL);
2422 if (!channel_namec) {
2423 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2424 SILC_STATUS_ERR_BAD_CHANNEL, 0);
2428 /* Get Client ID of the client who is joining to the channel */
2429 if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id, NULL)) {
2430 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2431 SILC_STATUS_ERR_NO_CLIENT_ID,
2435 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2437 /* Get cipher, hmac name and auth payload */
2438 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2439 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2440 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
2441 cauth = silc_argument_get_arg_type(cmd->args, 7, &cauth_len);
2443 /* See if the channel exists */
2444 channel = silc_idlist_find_channel_by_name(server->local_list,
2445 channel_namec, NULL);
2447 if (idata->conn_type == SILC_CONN_CLIENT) {
2448 SilcClientEntry entry = (SilcClientEntry)idata;
2450 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2451 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2456 #ifndef SILC_DIST_INPLACE
2457 /* Limit how many channels client can join */
2458 if (!cmd->pending && entry->channels &&
2459 silc_hash_table_count(entry->channels) >=
2460 server->config->param.chlimit) {
2461 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2462 SILC_STATUS_ERR_RESOURCE_LIMIT,
2466 #endif /* SILC_DIST_INPLACE */
2469 (channel->disabled && server->server_type != SILC_ROUTER)) {
2470 /* Channel not found or not valid */
2472 /* If we are standalone server we don't have a router, we just create
2473 the channel by ourselves (unless it existed). */
2474 if (server->standalone) {
2476 channel = silc_server_create_new_channel(server, server->id, cipher,
2477 hmac, channel_name, TRUE);
2480 silc_server_command_send_status_data(
2481 cmd, SILC_COMMAND_JOIN,
2482 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
2483 0, 2, cipher, strlen(cipher));
2485 silc_server_command_send_status_data(
2486 cmd, SILC_COMMAND_JOIN,
2487 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
2488 0, 2, hmac, strlen(hmac));
2490 silc_server_command_send_status_reply(
2491 cmd, SILC_COMMAND_JOIN,
2492 SILC_STATUS_ERR_RESOURCE_LIMIT,
2498 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2504 /* The channel does not exist on our server. If we are normal server
2505 we will send JOIN command to our router which will handle the
2506 joining procedure (either creates the channel if it doesn't exist
2507 or joins the client to it). */
2508 if (server->server_type != SILC_ROUTER) {
2510 SilcUInt16 old_ident;
2512 /* If this is pending command callback then we've resolved
2513 it and it didn't work, return since we've notified the
2514 client already in the command reply callback. */
2519 cmd->server->stat.commands_sent++;
2521 old_ident = silc_command_get_ident(cmd->payload);
2522 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2523 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2525 /* Send JOIN command to our router */
2526 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
2527 SILC_PACKET_COMMAND, cmd->packet->flags,
2528 tmpbuf->data, silc_buffer_len(tmpbuf));
2530 /* Reprocess this packet after received reply from router */
2531 silc_server_command_pending(server, SILC_COMMAND_JOIN,
2532 silc_command_get_ident(cmd->payload),
2533 silc_server_command_join,
2534 silc_server_command_dup(cmd));
2535 cmd->pending = TRUE;
2536 silc_command_set_ident(cmd->payload, old_ident);
2537 silc_buffer_free(tmpbuf);
2541 /* We are router and the channel does not seem exist so we will check
2542 our global list as well for the channel. */
2543 channel = silc_idlist_find_channel_by_name(server->global_list,
2544 channel_namec, NULL);
2546 /* Channel really does not exist, create it */
2547 channel = silc_server_create_new_channel(server, server->id, cipher,
2548 hmac, channel_name, TRUE);
2551 silc_server_command_send_status_data(
2552 cmd, SILC_COMMAND_JOIN,
2553 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
2554 0, 2, cipher, strlen(cipher));
2556 silc_server_command_send_status_data(
2557 cmd, SILC_COMMAND_JOIN,
2558 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
2559 0, 2, hmac, strlen(hmac));
2561 silc_server_command_send_status_reply(
2562 cmd, SILC_COMMAND_JOIN,
2563 SILC_STATUS_ERR_RESOURCE_LIMIT,
2569 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2577 /* Channel not found */
2579 /* If the command came from router and we are normal server then
2580 something went wrong with the joining as the channel was not found.
2581 We can't do anything else but ignore this. */
2582 if (idata->conn_type == SILC_CONN_ROUTER ||
2583 server->server_type != SILC_ROUTER)
2586 /* We are router and the channel does not seem exist so we will check
2587 our global list as well for the channel. */
2588 channel = silc_idlist_find_channel_by_name(server->global_list,
2589 channel_namec, NULL);
2591 /* Channel really does not exist, create it */
2592 channel = silc_server_create_new_channel(server, server->id, cipher,
2593 hmac, channel_name, TRUE);
2596 silc_server_command_send_status_data(
2597 cmd, SILC_COMMAND_JOIN,
2598 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
2599 0, 2, cipher, strlen(cipher));
2601 silc_server_command_send_status_data(
2602 cmd, SILC_COMMAND_JOIN,
2603 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
2604 0, 2, hmac, strlen(hmac));
2606 silc_server_command_send_status_reply(
2607 cmd, SILC_COMMAND_JOIN,
2608 SILC_STATUS_ERR_RESOURCE_LIMIT,
2614 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2621 /* Check whether the channel was created by our router */
2622 if (cmd->pending && context2) {
2623 SilcServerCommandReplyContext reply = context2;
2625 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
2626 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
2627 SILC_GET32_MSB(created, tmp);
2628 if (silc_argument_get_arg_type(reply->args, 7, NULL))
2629 create_key = FALSE; /* Router returned the key already */
2631 if (silc_command_get_status(reply->payload, NULL, NULL) &&
2632 channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2633 /* Save channel passphrase, if user provided it successfully */
2636 pa = silc_argument_get_arg_type(cmd->args, 3, &pa_len);
2638 silc_free(channel->passphrase);
2639 channel->passphrase = silc_memdup(pa, pa_len);
2644 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
2645 !channel->disabled && !silc_hash_table_count(channel->user_list))
2649 /* If the channel does not have global users and is also empty the client
2650 will be the channel founder and operator. */
2651 if (!channel->disabled &&
2652 !channel->global_users && !silc_hash_table_count(channel->user_list))
2653 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2655 /* Join to the channel */
2656 silc_server_command_join_channel(server, cmd, channel, SILC_ID_GET_ID(id),
2657 created, create_key, umode,
2658 auth, auth_len, cauth, cauth_len);
2661 silc_free(channel_namec);
2662 silc_server_command_free(cmd);
2665 /* Server side of command MOTD. Sends server's current "message of the
2666 day" to the client. */
2668 SILC_SERVER_CMD_FUNC(motd)
2670 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2671 SilcServer server = cmd->server;
2673 char *motd, *dest_server = NULL;
2674 SilcUInt32 motd_len;
2675 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2677 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
2679 /* Get server name */
2680 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2682 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2683 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2688 /* Check server name */
2689 dest_server = silc_identifier_check(dest_server, strlen(dest_server),
2690 SILC_STRING_UTF8, 256, NULL);
2692 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2693 SILC_STATUS_ERR_BAD_SERVER,
2698 if (!memcmp(dest_server, server->server_name, strlen(dest_server))) {
2701 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
2703 if (server->config && server->config->server_info &&
2704 server->config->server_info->motd_file) {
2706 motd = silc_file_readfile(server->config->server_info->motd_file,
2710 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_MOTD,
2711 SILC_STATUS_OK, 0, ident, 1,
2712 2, idp->data, silc_buffer_len(idp));
2717 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_MOTD,
2718 SILC_STATUS_OK, 0, ident, 2,
2719 2, idp->data, silc_buffer_len(idp),
2723 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_MOTD,
2724 SILC_STATUS_OK, 0, ident, 1,
2725 2, idp->data, silc_buffer_len(idp));
2727 silc_buffer_free(idp);
2729 SilcServerEntry entry;
2731 /* Check whether we have this server cached */
2732 entry = silc_idlist_find_server_by_name(server->global_list,
2733 dest_server, TRUE, NULL);
2735 entry = silc_idlist_find_server_by_name(server->local_list,
2736 dest_server, TRUE, NULL);
2739 if (server->server_type != SILC_SERVER && !cmd->pending &&
2740 entry && !entry->motd) {
2741 /* Send to the server */
2743 SilcUInt16 old_ident;
2746 cmd->server->stat.commands_sent++;
2748 old_ident = silc_command_get_ident(cmd->payload);
2749 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2750 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2752 silc_server_packet_send(server, entry->connection,
2753 SILC_PACKET_COMMAND, cmd->packet->flags,
2754 tmpbuf->data, silc_buffer_len(tmpbuf));
2756 /* Reprocess this packet after received reply from router */
2757 silc_server_command_pending(server, SILC_COMMAND_MOTD,
2758 silc_command_get_ident(cmd->payload),
2759 silc_server_command_motd,
2760 silc_server_command_dup(cmd));
2761 cmd->pending = TRUE;
2762 silc_command_set_ident(cmd->payload, old_ident);
2763 silc_buffer_free(tmpbuf);
2767 /* Send to primary router only if we don't know the server
2768 * the client requested or if the server is not locally connected */
2769 if ((!entry || !(entry->data.status & SILC_IDLIST_STATUS_LOCAL))
2770 && !cmd->pending && !server->standalone) {
2771 /* Send to the primary router */
2773 SilcUInt16 old_ident;
2776 cmd->server->stat.commands_sent++;
2778 old_ident = silc_command_get_ident(cmd->payload);
2779 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2780 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2782 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
2783 SILC_PACKET_COMMAND, cmd->packet->flags,
2784 tmpbuf->data, silc_buffer_len(tmpbuf));
2786 /* Reprocess this packet after received reply from router */
2787 silc_server_command_pending(server, SILC_COMMAND_MOTD,
2788 silc_command_get_ident(cmd->payload),
2789 silc_server_command_motd,
2790 silc_server_command_dup(cmd));
2791 cmd->pending = TRUE;
2792 silc_command_set_ident(cmd->payload, old_ident);
2793 silc_buffer_free(tmpbuf);
2798 silc_free(dest_server);
2799 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2800 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2801 SILC_STATUS_ERR_NO_SUCH_SERVER, 0,
2803 strlen(dest_server));
2808 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2809 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_MOTD,
2810 SILC_STATUS_OK, 0, ident, 2,
2811 2, idp->data, silc_buffer_len(idp),
2814 strlen(entry->motd) : 0);
2815 silc_buffer_free(idp);
2819 silc_free(dest_server);
2820 silc_server_command_free(cmd);
2823 /* Server side of command UMODE. Client can use this command to set/unset
2824 user mode. Client actually cannot set itself to be as server/router
2825 operator so this can be used only to unset the modes. */
2827 SILC_SERVER_CMD_FUNC(umode)
2829 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2830 SilcServer server = cmd->server;
2831 SilcClientEntry client = silc_packet_get_context(cmd->sock);
2832 unsigned char *tmp_mask, m[4];
2833 SilcUInt32 mask = 0, tmp_len;
2834 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2835 SilcBool set_mask = FALSE;
2837 if (client->data.conn_type != SILC_CONN_CLIENT || !client)
2840 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2);
2842 /* Get the client's mode mask */
2843 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2844 if (tmp_mask && tmp_len == 4) {
2845 SILC_GET32_MSB(mask, tmp_mask);
2850 /* Check that mode changing is allowed. */
2851 if (!silc_server_check_umode_rights(server, client, mask)) {
2852 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2853 SILC_STATUS_ERR_PERM_DENIED, 0);
2857 /* Anonymous mode cannot be set by client */
2858 if (mask & SILC_UMODE_ANONYMOUS &&
2859 !(client->mode & SILC_UMODE_ANONYMOUS)) {
2860 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2861 SILC_STATUS_ERR_PERM_DENIED, 0);
2865 /* Update statistics */
2866 if (mask & SILC_UMODE_GONE) {
2867 if (!(client->mode & SILC_UMODE_GONE))
2868 server->stat.my_aways++;
2870 if (client->mode & SILC_UMODE_GONE)
2871 server->stat.my_aways--;
2874 /* If the client has anonymous mode set, preserve it. */
2875 if (client->mode & SILC_UMODE_ANONYMOUS)
2876 mask |= SILC_UMODE_ANONYMOUS;
2878 /* Change the mode */
2879 client->mode = mask;
2881 /* Send UMODE change to primary router */
2882 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
2883 SILC_BROADCAST(server), client->id,
2886 /* Check if anyone is watching this nickname */
2887 if (server->server_type == SILC_ROUTER)
2888 silc_server_check_watcher_list(server, client, NULL,
2889 SILC_NOTIFY_TYPE_UMODE_CHANGE);
2892 /* Send command reply to sender */
2893 SILC_PUT32_MSB(client->mode, m);
2894 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_UMODE,
2895 SILC_STATUS_OK, 0, ident, 1,
2899 silc_server_command_free(cmd);
2902 /* Server side command of CMODE. Changes channel mode */
2904 SILC_SERVER_CMD_FUNC(cmode)
2906 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2907 SilcServer server = cmd->server;
2908 SilcClientEntry client = silc_packet_get_context(cmd->sock);
2909 SilcIDListData idata = (SilcIDListData)client;
2911 SilcChannelEntry channel;
2912 SilcChannelClientEntry chl;
2914 unsigned char *tmp, *tmp_id, *tmp_mask, *chpkdata = NULL;
2915 char *cipher = NULL, *hmac = NULL, *passphrase = NULL, ulimit[4];
2916 SilcUInt32 mode_mask = 0, old_mask = 0, tmp_len, tmp_len2, chpklen;
2917 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2918 SilcBool set_mask = FALSE, set_chpk = FALSE;
2919 SilcPublicKey founder_key = NULL;
2920 SilcBuffer fkey = NULL, chpklist = NULL;
2921 SilcBufferStruct chpk;
2924 silc_server_command_free(cmd);
2928 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 9);
2930 /* Get Channel ID */
2931 if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
2932 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2933 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2934 silc_server_command_free(cmd);
2938 /* Get channel entry */
2939 channel = silc_idlist_find_channel_by_id(server->local_list,
2940 SILC_ID_GET_ID(id), NULL);
2942 channel = silc_idlist_find_channel_by_id(server->global_list,
2943 SILC_ID_GET_ID(id), NULL);
2945 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2946 silc_server_command_send_status_data(cmd, SILC_COMMAND_CMODE,
2947 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
2948 0, 2, tmp_id, tmp_len2);
2949 silc_server_command_free(cmd);
2953 old_mask = channel->mode;
2955 /* Get the channel mode mask */
2956 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2957 if (tmp_mask && tmp_len == 4) {
2958 SILC_GET32_MSB(mode_mask, tmp_mask);
2962 /* Check whether this client is on the channel */
2963 if (!silc_server_client_on_channel(client, channel, &chl)) {
2964 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2965 silc_server_command_send_status_data(cmd, SILC_COMMAND_CMODE,
2966 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
2967 2, tmp_id, tmp_len2);
2971 /* Check that client has rights to change any requested channel modes */
2972 if (set_mask && !silc_server_check_cmode_rights(server, channel, chl,
2974 SILC_LOG_DEBUG(("Client does not have rights to change mode"));
2975 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2976 silc_server_command_send_status_data(
2977 cmd, SILC_COMMAND_CMODE,
2978 (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) ?
2979 SILC_STATUS_ERR_NO_CHANNEL_PRIV :
2980 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV), 0,
2981 2, tmp_id, tmp_len2);
2985 /* If mode mask was not sent as argument then merely return the current
2986 mode mask, founder key and channel public key list to the sender. */
2989 SILC_PUT32_MSB(channel->mode, m);
2990 if (channel->founder_key)
2991 fkey = silc_public_key_payload_encode(channel->founder_key);
2992 if (channel->channel_pubkeys)
2993 chpklist = silc_server_get_channel_pk_list(server, channel,
2995 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2996 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_CMODE,
2997 SILC_STATUS_OK, 0, ident, 4,
2998 2, tmp_id, tmp_len2,
3000 4, fkey ? fkey->data : NULL,
3001 fkey ? silc_buffer_len(fkey) : 0,
3002 5, chpklist ? chpklist->data : NULL,
3003 chpklist ? silc_buffer_len(chpklist) : 0);
3008 * Check the modes. Modes that requires nothing special operation are
3012 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3013 /* Channel uses private keys to protect traffic. Client(s) has set the
3014 key locally they want to use, server does not know that key. */
3015 /* Nothing interesting to do here */
3017 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3018 /* The mode is removed and we need to generate and distribute
3019 new channel key. Clients are not using private channel keys
3020 anymore after this. */
3022 /* if we don't remove the flag from the mode
3023 * silc_server_create_channel_key won't create a new key */
3024 channel->mode &= ~SILC_CHANNEL_MODE_PRIVKEY;
3026 /* Re-generate channel key */
3027 if (!silc_server_create_channel_key(server, channel, 0))
3030 /* Send the channel key. This sends it to our local clients and if
3031 we are normal server to our router as well. */
3032 silc_server_send_channel_key(server, NULL, channel,
3033 server->server_type == SILC_ROUTER ?
3034 FALSE : !server->standalone);
3036 cipher = (char *)silc_cipher_get_name(channel->send_key);
3037 hmac = (char *)silc_hmac_get_name(channel->hmac);
3041 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3042 /* User limit is set on channel */
3043 SilcUInt32 user_limit;
3045 /* Get user limit */
3046 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3048 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3049 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3050 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3054 SILC_GET32_MSB(user_limit, tmp);
3055 channel->user_limit = user_limit;
3058 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3059 /* User limit mode is unset. Remove user limit */
3060 channel->user_limit = 0;
3063 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3064 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3065 /* Passphrase has been set to channel */
3067 /* Get the passphrase */
3068 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3070 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3071 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3075 /* Save the passphrase */
3076 passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
3079 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3080 /* Passphrase mode is unset. remove the passphrase */
3081 silc_free(channel->passphrase);
3082 channel->passphrase = NULL;
3086 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3087 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3088 /* Cipher to use protect the traffic */
3089 SilcCipher send_key, receive_key, olds, oldr;
3092 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3094 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3095 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3099 /* Delete old cipher and allocate the new one */
3100 if (!silc_cipher_alloc(cipher, &send_key)) {
3101 silc_server_command_send_status_data(
3102 cmd, SILC_COMMAND_CMODE,
3103 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
3104 2, cipher, strlen(cipher));
3107 if (!silc_cipher_alloc(cipher, &receive_key)) {
3108 silc_server_command_send_status_data(
3109 cmd, SILC_COMMAND_CMODE,
3110 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
3111 2, cipher, strlen(cipher));
3115 olds = channel->send_key;
3116 oldr = channel->receive_key;
3117 channel->send_key = send_key;
3118 channel->receive_key = receive_key;
3120 /* Re-generate channel key */
3121 if (!silc_server_create_channel_key(server, channel, 0)) {
3122 /* We don't have new key, revert to old one */
3123 channel->send_key = olds;
3124 channel->receive_key = oldr;
3128 /* Remove old channel key for good */
3129 silc_cipher_free(olds);
3130 silc_cipher_free(oldr);
3132 /* Send the channel key. This sends it to our local clients and if
3133 we are normal server to our router as well. */
3134 silc_server_send_channel_key(server, NULL, channel,
3135 server->server_type == SILC_ROUTER ?
3136 FALSE : !server->standalone);
3139 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3140 /* Cipher mode is unset. Remove the cipher and revert back to
3142 SilcCipher send_key, receive_key, olds, oldr;
3143 cipher = channel->cipher;
3145 /* Delete old cipher and allocate default one */
3146 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER,
3148 silc_server_command_send_status_data(
3149 cmd, SILC_COMMAND_CMODE,
3150 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
3151 2, cipher, strlen(cipher));
3154 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER,
3156 silc_server_command_send_status_data(
3157 cmd, SILC_COMMAND_CMODE,
3158 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
3159 2, cipher, strlen(cipher));
3163 olds = channel->send_key;
3164 oldr = channel->receive_key;
3165 channel->send_key = send_key;
3166 channel->receive_key = receive_key;
3168 /* Re-generate channel key */
3169 if (!silc_server_create_channel_key(server, channel, 0)) {
3170 /* We don't have new key, revert to old one */
3171 channel->send_key = olds;
3172 channel->receive_key = oldr;
3176 /* Remove old channel key for good */
3177 silc_cipher_free(olds);
3178 silc_cipher_free(oldr);
3180 /* Send the channel key. This sends it to our local clients and if
3181 we are normal server to our router as well. */
3182 silc_server_send_channel_key(server, NULL, channel,
3183 server->server_type == SILC_ROUTER ?
3184 FALSE : !server->standalone);
3188 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3189 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3190 /* HMAC to use protect the traffic */
3191 unsigned char hash[SILC_HASH_MAXLEN];
3195 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3197 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3198 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3202 /* Delete old hmac and allocate the new one */
3203 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
3204 silc_server_command_send_status_data(
3205 cmd, SILC_COMMAND_CMODE,
3206 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
3207 2, hmac, strlen(hmac));
3211 silc_hmac_free(channel->hmac);
3212 channel->hmac = newhmac;
3214 /* Set the HMAC key out of current channel key. The client must do
3216 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
3217 channel->key_len / 8, hash);
3218 silc_hmac_set_key(channel->hmac, hash,
3219 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3220 memset(hash, 0, sizeof(hash));
3223 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
3224 /* Hmac mode is unset. Remove the hmac and revert back to
3227 unsigned char hash[SILC_HASH_MAXLEN];
3228 hmac = channel->hmac_name;
3230 /* Delete old hmac and allocate default one */
3231 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
3232 silc_server_command_send_status_data(
3233 cmd, SILC_COMMAND_CMODE,
3234 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
3235 2, hmac, strlen(hmac));
3239 silc_hmac_free(channel->hmac);
3240 channel->hmac = newhmac;
3242 /* Set the HMAC key out of current channel key. The client must do
3244 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
3245 channel->key_len / 8,
3247 silc_hmac_set_key(channel->hmac, hash,
3248 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3249 memset(hash, 0, sizeof(hash));
3253 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3254 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3255 /* Check if the founder public key was received */
3256 founder_key = idata->public_key;
3257 tmp = silc_argument_get_arg_type(cmd->args, 8, &tmp_len);
3259 if (!silc_public_key_payload_decode(tmp, tmp_len, &founder_key)) {
3260 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3261 SILC_STATUS_ERR_AUTH_FAILED,
3266 /* If key was not sent and the channel mode has already founder
3267 then the key was not to be changed. */
3268 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)
3272 /* Set the founder authentication */
3273 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
3275 silc_server_command_send_status_reply(
3276 cmd, SILC_COMMAND_CMODE,
3277 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3281 /* Verify the payload before setting the mode */
3282 if (!silc_auth_verify_data(tmp, tmp_len, SILC_AUTH_PUBLIC_KEY,
3283 founder_key, 0, server->sha1hash,
3284 client->id, SILC_ID_CLIENT)) {
3285 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3286 SILC_STATUS_ERR_AUTH_FAILED,
3291 /* Save the public key */
3292 if (channel->founder_key)
3293 silc_pkcs_public_key_free(channel->founder_key);
3294 if (silc_argument_get_arg_type(cmd->args, 8, NULL))
3295 channel->founder_key = founder_key;
3297 channel->founder_key = silc_pkcs_public_key_copy(founder_key);
3298 if (!channel->founder_key) {
3299 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3300 SILC_STATUS_ERR_AUTH_FAILED,
3305 fkey = silc_public_key_payload_encode(channel->founder_key);
3307 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3308 SILC_STATUS_ERR_AUTH_FAILED,
3310 silc_pkcs_public_key_free(channel->founder_key);
3311 channel->founder_key = NULL;
3316 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3317 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3318 if (channel->founder_key)
3319 silc_pkcs_public_key_free(channel->founder_key);
3320 channel->founder_key = NULL;
3326 if (mode_mask & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
3327 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3330 chpkdata = silc_argument_get_arg_type(cmd->args, 9, &chpklen);
3332 if (!chpkdata && channel->mode & SILC_CHANNEL_MODE_CHANNEL_AUTH)
3337 /* Process the channel public key(s) */
3338 st = silc_server_set_channel_pk_list(server, NULL, channel,
3340 if (st != SILC_STATUS_OK) {
3341 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE, st, 0);
3346 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3347 if (channel->mode & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
3348 if (channel->channel_pubkeys)
3349 silc_hash_table_free(channel->channel_pubkeys);
3350 channel->channel_pubkeys = NULL;
3357 /* Finally, set the mode */
3358 old_mask = channel->mode = mode_mask;
3360 /* Send CMODE_CHANGE notify. */
3361 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3362 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT)
3363 SILC_PUT32_MSB(channel->user_limit, ulimit);
3364 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
3365 SILC_NOTIFY_TYPE_CMODE_CHANGE, 8,
3366 cidp->data, silc_buffer_len(cidp),
3368 cipher, cipher ? strlen(cipher) : 0,
3369 hmac, hmac ? strlen(hmac) : 0,
3370 passphrase, passphrase ?
3371 strlen(passphrase) : 0,
3372 fkey ? fkey->data : NULL,
3373 fkey ? silc_buffer_len(fkey) : 0,
3374 chpkdata ? chpkdata : NULL,
3375 chpkdata ? chpklen : 0,
3376 mode_mask & SILC_CHANNEL_MODE_ULIMIT ?
3378 mode_mask & SILC_CHANNEL_MODE_ULIMIT ?
3379 sizeof(ulimit) : 0);
3381 /* Set CMODE notify type to network */
3382 if (chpkdata && chpklen)
3383 silc_buffer_set(&chpk, chpkdata, chpklen);
3384 silc_server_send_notify_cmode(server, SILC_PRIMARY_ROUTE(server),
3385 SILC_BROADCAST(server), channel,
3386 mode_mask, client->id, SILC_ID_CLIENT,
3387 cipher, hmac, passphrase, founder_key,
3388 chpkdata ? &chpk : NULL);
3391 chpklist = silc_server_get_channel_pk_list(server, channel, FALSE, FALSE);
3393 /* Send command reply to sender */
3394 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3395 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_CMODE,
3396 SILC_STATUS_OK, 0, ident, 5,
3397 2, tmp_id, tmp_len2,
3399 4, fkey ? fkey->data : NULL,
3400 fkey ? silc_buffer_len(fkey) : 0,
3401 5, chpklist ? chpklist->data :
3402 NULL, chpklist ? silc_buffer_len(chpklist)
3405 SILC_CHANNEL_MODE_ULIMIT ?
3408 SILC_CHANNEL_MODE_ULIMIT ?
3409 sizeof(ulimit) : 0));
3410 silc_buffer_free(cidp);
3413 channel->mode = old_mask;
3414 silc_buffer_free(chpklist);
3415 silc_buffer_free(fkey);
3416 silc_server_command_free(cmd);
3419 /* Server side of CUMODE command. Changes client's mode on a channel. */
3421 SILC_SERVER_CMD_FUNC(cumode)
3423 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3424 SilcServer server = cmd->server;
3425 SilcClientEntry client = silc_packet_get_context(cmd->sock);
3427 SilcChannelEntry channel;
3428 SilcClientEntry target_client;
3429 SilcChannelClientEntry chl;
3431 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
3432 SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
3434 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3435 SilcPublicKey founder_key = NULL;
3436 SilcBuffer fkey = NULL;
3441 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
3443 /* Get Channel ID */
3444 if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
3445 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3446 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3450 /* Get channel entry */
3451 channel = silc_idlist_find_channel_by_id(server->local_list,
3452 SILC_ID_GET_ID(id), NULL);
3454 channel = silc_idlist_find_channel_by_id(server->global_list,
3455 SILC_ID_GET_ID(id), NULL);
3457 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3458 silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3459 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
3460 0, 2, tmp_ch_id, tmp_ch_len);
3465 /* Check whether sender is on the channel */
3466 if (!silc_server_client_on_channel(client, channel, &chl)) {
3467 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3468 silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3469 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
3470 2, tmp_ch_id, tmp_ch_len);
3473 sender_mask = chl->mode;
3475 /* Get the target client's channel mode mask */
3476 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3478 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3479 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3483 SILC_GET32_MSB(target_mask, tmp_mask);
3485 /* Get target Client ID */
3486 if (!silc_argument_get_decoded(cmd->args, 3, SILC_ARGUMENT_ID, &id2, NULL)) {
3487 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3488 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
3492 /* Get target client's entry */
3493 target_client = silc_idlist_find_client_by_id(server->local_list,
3494 SILC_ID_GET_ID(id2),
3497 target_client = silc_idlist_find_client_by_id(server->global_list,
3498 SILC_ID_GET_ID(id2),
3501 if (target_client != client &&
3502 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
3503 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
3504 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3505 silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3506 SILC_STATUS_ERR_NOT_YOU, 0,
3507 2, tmp_ch_id, tmp_ch_len);
3511 /* Check whether target client is on the channel */
3512 if (target_client != client) {
3513 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
3514 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3515 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3516 silc_server_command_send_status_data2(
3517 cmd, SILC_COMMAND_CUMODE,
3518 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL, 0,
3520 3, tmp_ch_id, tmp_ch_len);
3529 /* If the target client is founder, no one else can change their mode
3531 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
3532 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3533 silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3534 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
3535 0, 2, tmp_ch_id, tmp_ch_len);
3539 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
3540 if (target_client != client) {
3541 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3542 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
3547 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
3548 /* The client tries to claim the founder rights. */
3549 unsigned char *tmp_auth;
3550 SilcUInt32 tmp_auth_len;
3551 SilcChannelClientEntry chl2;
3552 SilcHashTableList htl;
3554 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
3555 !channel->founder_key) {
3556 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3557 SILC_STATUS_ERR_AUTH_FAILED, 0);
3561 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
3563 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3564 SILC_STATUS_ERR_AUTH_FAILED, 0);
3568 /* Verify the authentication payload */
3569 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len, SILC_AUTH_PUBLIC_KEY,
3570 channel->founder_key, 0, server->sha1hash,
3571 client->id, SILC_ID_CLIENT)) {
3572 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3573 SILC_STATUS_ERR_AUTH_FAILED, 0);
3578 founder_key = channel->founder_key;
3579 fkey = silc_public_key_payload_encode(founder_key);
3581 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3582 SILC_STATUS_ERR_AUTH_FAILED, 0);
3586 /* There cannot be anyone else as founder on the channel now. This
3587 client is definitely the founder due to this authentication. This
3588 is done only on router, not on server, since server cannot know
3589 whether router will accept this mode change or not. XXX This
3590 probably shouldn't be done anymore at all, may cause problems in
3591 router-router connections too (maybe just AUTH_FAILED error should
3592 be returned). -Pekka */
3593 if (server->server_type == SILC_ROUTER) {
3594 silc_hash_table_list(channel->user_list, &htl);
3595 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
3596 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
3597 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3598 silc_server_force_cumode_change(server, NULL, channel, chl2,
3602 silc_hash_table_list_reset(&htl);
3605 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
3608 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3609 if (target_client == client) {
3610 /* Remove channel founder rights from itself */
3611 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3614 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3615 SILC_STATUS_ERR_NOT_YOU, 0);
3621 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
3622 /* Promote to operator */
3623 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3624 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3625 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3626 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3627 silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3628 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
3629 0, 2, tmp_ch_id, tmp_ch_len);
3633 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
3637 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
3638 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3639 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3640 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3641 silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3642 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
3643 0, 2, tmp_ch_id, tmp_ch_len);
3647 /* Demote to normal user */
3648 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
3653 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
3654 if (target_client != client) {
3655 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3656 SILC_STATUS_ERR_NOT_YOU, 0);
3660 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
3661 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
3665 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
3666 if (target_client != client) {
3667 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3668 SILC_STATUS_ERR_NOT_YOU, 0);
3672 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
3677 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
3678 if (target_client != client) {
3679 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3680 SILC_STATUS_ERR_NOT_YOU, 0);
3684 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)) {
3685 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
3689 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
3690 if (target_client != client) {
3691 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3692 SILC_STATUS_ERR_NOT_YOU, 0);
3696 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
3701 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
3702 if (target_client != client) {
3703 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3704 SILC_STATUS_ERR_NOT_YOU, 0);
3708 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)) {
3709 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
3713 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
3714 if (target_client != client) {
3715 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3716 SILC_STATUS_ERR_NOT_YOU, 0);
3720 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
3725 if (target_mask & SILC_CHANNEL_UMODE_QUIET) {
3726 if (!(chl->mode & SILC_CHANNEL_UMODE_QUIET)) {
3727 if (client == target_client) {
3728 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3729 SILC_STATUS_ERR_PERM_DENIED, 0);
3732 chl->mode |= SILC_CHANNEL_UMODE_QUIET;
3736 if (chl->mode & SILC_CHANNEL_UMODE_QUIET) {
3737 if (client == target_client) {
3738 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3739 SILC_STATUS_ERR_PERM_DENIED, 0);
3742 chl->mode &= ~SILC_CHANNEL_UMODE_QUIET;
3747 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3748 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3749 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3751 /* Send notify to channel, notify only if mode was actually changed. */
3753 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
3754 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
3755 idp->data, silc_buffer_len(idp),
3758 fkey ? fkey->data : NULL,
3759 fkey ? silc_buffer_len(fkey) : 0);
3761 /* Set CUMODE notify type to network */
3762 silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
3763 SILC_BROADCAST(server), channel,
3764 target_mask, client->id, SILC_ID_CLIENT,
3765 target_client->id, founder_key);
3768 /* Send command reply to sender */
3769 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_CUMODE,
3770 SILC_STATUS_OK, 0, ident, 3,
3772 3, tmp_ch_id, tmp_ch_len,
3773 4, tmp_id, tmp_len);
3774 silc_buffer_free(idp);
3777 silc_buffer_free(fkey);
3778 silc_server_command_free(cmd);
3781 /* Server side of KICK command. Kicks client out of channel. */
3783 SILC_SERVER_CMD_FUNC(kick)
3785 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3786 SilcServer server = cmd->server;
3787 SilcClientEntry client = silc_packet_get_context(cmd->sock);
3788 SilcClientEntry target_client;
3790 SilcChannelEntry channel;
3791 SilcChannelClientEntry chl;
3793 SilcUInt32 tmp_len, target_idp_len, clen;
3794 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3795 unsigned char *tmp, *comment, *target_idp;
3800 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
3802 /* Get Channel ID */
3803 if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
3804 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3805 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3809 /* Get channel entry */
3810 channel = silc_idlist_find_channel_by_id(server->local_list,
3811 SILC_ID_GET_ID(id), NULL);
3813 channel = silc_idlist_find_channel_by_id(server->local_list,
3814 SILC_ID_GET_ID(id), NULL);
3816 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3817 silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3818 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
3819 0, 2, tmp, tmp_len);
3824 /* Check whether sender is on the channel */
3825 if (!silc_server_client_on_channel(client, channel, &chl)) {
3826 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3827 silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3828 SILC_STATUS_ERR_NOT_ON_CHANNEL,
3829 0, 2, tmp, tmp_len);
3833 /* Check that the kicker is channel operator or channel founder */
3834 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
3835 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
3836 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3837 silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3838 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
3839 0, 2, tmp, tmp_len);
3843 /* Get target Client ID */
3844 if (!silc_argument_get_decoded(cmd->args, 2, SILC_ARGUMENT_ID, &id2, NULL)) {
3845 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3846 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
3850 /* Get target client's entry */
3851 target_client = silc_idlist_find_client_by_id(server->local_list,
3852 SILC_ID_GET_ID(id2),
3855 target_client = silc_idlist_find_client_by_id(server->global_list,
3856 SILC_ID_GET_ID(id2),
3859 /* Check whether target client is on the channel */
3860 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
3861 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3862 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
3863 silc_server_command_send_status_data2(cmd, SILC_COMMAND_KICK,
3864 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL,
3865 0, 2, target_idp, target_idp_len,
3870 /* Check that the target client is not channel founder. Channel founder
3871 cannot be kicked from the channel. */
3872 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3873 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3874 silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3875 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
3876 0, 2, tmp, tmp_len);
3881 comment = silc_argument_get_arg_type(cmd->args, 3, &clen);
3885 /* Send the reply back to the client */
3886 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3887 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
3888 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_KICK,
3889 SILC_STATUS_OK, 0, ident, 2,
3891 3, target_idp, target_idp_len);
3893 /* Send KICKED notify to local clients on the channel */
3894 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3895 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
3896 SILC_NOTIFY_TYPE_KICKED, 3,
3897 target_idp, target_idp_len,
3898 comment, comment ? strlen(comment) : 0,
3899 idp->data, silc_buffer_len(idp));
3900 silc_buffer_free(idp);
3902 /* Send KICKED notify to primary route */
3903 silc_server_send_notify_kicked(server, SILC_PRIMARY_ROUTE(server),
3904 SILC_BROADCAST(server), channel,
3905 target_client->id, client->id, comment);
3907 /* Remove the client from channel's invite list */
3908 if (channel->invite_list && silc_hash_table_count(channel->invite_list)) {
3910 silc_argument_payload_encode_one(NULL, target_idp, target_idp_len, 3);
3911 SilcArgumentPayload args =
3912 silc_argument_payload_parse(ab->data, silc_buffer_len(ab), 1);
3914 silc_server_inviteban_process(server, channel->invite_list, 1, args);
3915 silc_buffer_free(ab);
3916 silc_argument_payload_free(args);
3919 /* Remove the client from the channel. If the channel does not exist
3920 after removing the client then the client kicked itself off the channel
3921 and we don't have to send anything after that. */
3922 if (!silc_server_remove_from_one_channel(server, NULL, channel,
3923 target_client, FALSE))
3926 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3927 /* Re-generate channel key */
3928 if (!silc_server_create_channel_key(server, channel, 0))
3931 /* Send the channel key to the channel. The key of course is not sent
3932 to the client who was kicked off the channel. */
3933 silc_server_send_channel_key(server, target_client->connection, channel,
3934 server->server_type == SILC_ROUTER ?
3935 FALSE : !server->standalone);
3939 silc_server_command_free(cmd);
3942 /* Server side of OPER command. Client uses this comand to obtain server
3943 operator privileges to this server/router. */
3945 SILC_SERVER_CMD_FUNC(oper)
3947 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3948 SilcServer server = cmd->server;
3949 SilcClientEntry client = silc_packet_get_context(cmd->sock);
3950 unsigned char *username = NULL, *auth;
3952 SilcServerConfigAdmin *admin;
3953 SilcIDListData idata = (SilcIDListData)client;
3954 SilcBool result = FALSE;
3955 SilcPublicKey cached_key;
3956 const char *hostname, *ip;
3958 if (client->data.conn_type != SILC_CONN_CLIENT || !client)
3961 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
3963 silc_socket_stream_get_info(silc_packet_stream_get_stream(cmd->sock),
3964 NULL, &hostname, &ip, NULL);
3966 /* Get the username */
3967 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3969 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3970 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3975 /* Check username */
3976 username = silc_identifier_check(username, strlen(username),
3977 SILC_STRING_UTF8, 128, &tmp_len);
3979 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3980 SILC_STATUS_ERR_BAD_USERNAME,
3985 /* Get the admin configuration */
3986 admin = silc_server_config_find_admin(server, (char *)ip,
3987 username, client->nickname);
3989 admin = silc_server_config_find_admin(server, (char *)hostname,
3990 username, client->nickname);
3992 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3993 SILC_STATUS_ERR_AUTH_FAILED,
3995 SILC_LOG_INFO(("OPER authentication failed for username '%s' by "
3996 "nickname '%s' from %s", username,
3997 client->nickname, hostname));
4002 /* Get the authentication payload */
4003 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4005 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4006 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4011 /* Verify the authentication data. If both passphrase and public key
4012 is set then try both of them. */
4013 if (admin->passphrase)
4014 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4015 admin->passphrase, admin->passphrase_len,
4016 idata->hash, client->id, SILC_ID_CLIENT);
4017 if (!result && admin->publickeys) {
4019 silc_server_get_public_key(server,
4020 SILC_SKR_USAGE_SERVICE_AUTHORIZATION, admin);
4023 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4024 cached_key, 0, idata->hash,
4025 client->id, SILC_ID_CLIENT);
4028 /* Authentication failed */
4029 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4030 SILC_STATUS_ERR_AUTH_FAILED,
4035 /* Client is now server operator */
4036 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4038 /* Update statistics */
4039 if (SILC_IS_LOCAL(client))
4040 server->stat.my_server_ops++;
4041 if (server->server_type == SILC_ROUTER)
4042 server->stat.server_ops++;
4044 /* Send UMODE change to primary router */
4045 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
4046 SILC_BROADCAST(server), client->id,
4049 /* Check if anyone is watching this nickname */
4050 if (server->server_type == SILC_ROUTER)
4051 silc_server_check_watcher_list(server, client, NULL,
4052 SILC_NOTIFY_TYPE_UMODE_CHANGE);
4054 /* Send reply to the sender */
4055 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4059 silc_free(username);
4060 silc_server_command_free(cmd);
4063 SILC_TASK_CALLBACK(silc_server_command_detach_cb)
4065 SilcServer server = app_context;
4066 QuitInternal q = (QuitInternal)context;
4067 SilcPacketStream sock = q->sock;
4068 SilcClientEntry client = silc_packet_get_context(sock);
4069 SilcIDListData idata = (SilcIDListData)client;
4072 silc_packet_stream_unref(sock);
4077 SILC_LOG_DEBUG(("Detaching client %s",
4078 silc_id_render(client->id, SILC_ID_CLIENT)));
4080 /* Stop rekey for the client. */
4081 silc_server_stop_rekey(server, client);
4083 /* Abort any active protocol */
4084 idata = silc_packet_get_context(sock);
4085 if (idata && idata->sconn && idata->sconn->op) {
4086 SILC_LOG_DEBUG(("Abort active protocol"));
4087 silc_async_abort(idata->sconn->op, NULL, NULL);
4088 idata->sconn->op = NULL;
4091 silc_schedule_task_del_by_all(server->schedule, 0, silc_server_do_heartbeat,
4094 /* Close the connection on our side */
4095 client->router = NULL;
4096 client->connection = NULL;
4097 silc_server_close_connection(server, sock);
4099 /* Mark the client as locally detached. */
4100 client->local_detached = TRUE;
4102 /* Decrement the user count; we'll increment it if the user resumes on our
4104 SILC_VERIFY(&server->stat.my_clients > 0);
4105 server->stat.my_clients--;
4107 silc_packet_stream_unref(sock);
4111 SILC_TASK_CALLBACK(silc_server_command_detach_timeout)
4113 SilcServer server = app_context;
4114 QuitInternal q = (QuitInternal)context;
4115 SilcClientID *client_id = (SilcClientID *)q->sock;
4116 SilcClientEntry client;
4118 client = silc_idlist_find_client_by_id(server->local_list, client_id,
4120 if (client && client->mode & SILC_UMODE_DETACHED) {
4121 SILC_LOG_DEBUG(("Detach timeout"));
4122 silc_server_free_client_data(server, NULL, client, TRUE,
4126 silc_free(client_id);
4130 /* Server side of DETACH command. Detached the client from the network
4131 by closing the connection but preserving the session. */
4133 SILC_SERVER_CMD_FUNC(detach)
4135 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4136 SilcServer server = cmd->server;
4137 SilcClientEntry client = silc_packet_get_context(cmd->sock);
4140 if (server->config->detach_disabled) {
4141 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
4142 SILC_STATUS_ERR_OPERATION_ALLOWED,
4147 if (client->data.conn_type != SILC_CONN_CLIENT || !client)
4150 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
4152 /* Remove operator privileges, since the client may resume in some
4153 other server which to it does not have operator privileges. */
4154 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
4155 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
4157 /* Send the user mode notify to notify that client is detached */
4158 client->mode |= SILC_UMODE_DETACHED;
4159 client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
4160 client->data.status &= ~SILC_IDLIST_STATUS_NOATTR;
4161 client->last_command = 0;
4162 client->fast_command = 0;
4163 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
4164 SILC_BROADCAST(server), client->id,
4166 server->stat.my_detached++;
4168 /* Check if anyone is watching this nickname */
4169 if (server->server_type == SILC_ROUTER)
4170 silc_server_check_watcher_list(server, client, NULL,
4171 SILC_NOTIFY_TYPE_UMODE_CHANGE);
4173 q = silc_calloc(1, sizeof(*q));
4174 q->sock = cmd->sock;
4175 silc_packet_stream_ref(q->sock);
4176 silc_schedule_task_add_timeout(server->schedule,
4177 silc_server_command_detach_cb,
4180 if (server->config->detach_timeout) {
4181 q = silc_calloc(1, sizeof(*q));
4182 q->sock = (void *)silc_id_dup(client->id, SILC_ID_CLIENT);
4183 silc_schedule_task_add_timeout(server->schedule,
4184 silc_server_command_detach_timeout,
4185 q, server->config->detach_timeout * 60, 0);
4188 /* Send reply to the sender */
4189 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
4193 silc_server_command_free(cmd);
4196 /* Server side of WATCH command. */
4198 SILC_SERVER_CMD_FUNC(watch)
4200 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4201 SilcServer server = cmd->server;
4202 char *add_nick, *del_nick;
4203 SilcUInt32 add_nick_len, del_nick_len, tmp_len, pk_len;
4204 unsigned char hash[SILC_HASH_MAXLEN], *tmp, *pk, *nick;
4205 SilcClientEntry client;
4207 SilcUInt16 old_ident;
4209 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WATCH, cmd, 1, 3);
4211 if (server->server_type != SILC_ROUTER && !server->standalone) {
4212 if (!cmd->pending) {
4213 /* Send the command to router */
4216 /* If backup receives this from primary, handle it locally */
4217 if (server->server_type == SILC_BACKUP_ROUTER &&
4218 cmd->sock == SILC_PRIMARY_ROUTE(server))
4221 SILC_LOG_DEBUG(("Forwarding WATCH to router"));
4224 cmd->server->stat.commands_sent++;
4226 old_ident = silc_command_get_ident(cmd->payload);
4227 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4228 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4230 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
4231 SILC_PACKET_COMMAND, cmd->packet->flags,
4232 tmpbuf->data, silc_buffer_len(tmpbuf));
4234 /* Reprocess this packet after received reply from router */
4235 silc_server_command_pending(server, SILC_COMMAND_WATCH,
4236 silc_command_get_ident(cmd->payload),
4237 silc_server_command_watch,
4238 silc_server_command_dup(cmd));
4239 cmd->pending = TRUE;
4240 silc_command_set_ident(cmd->payload, old_ident);
4241 silc_buffer_free(tmpbuf);
4244 SilcServerCommandReplyContext reply = context2;
4250 silc_command_get_status(reply->payload, &status, NULL);
4252 /* Backup router handles the WATCH command also. */
4253 if (server->server_type != SILC_BACKUP_ROUTER ||
4254 SILC_STATUS_IS_ERROR(status)) {
4255 /* Received reply from router, just send same data to the client. */
4256 SILC_LOG_DEBUG(("Received reply to WATCH from router"));
4257 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, status,
4264 /* We are router and keep the watch list for local cell */
4267 /* Get the client ID */
4268 if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
4269 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4270 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4275 /* Get the client entry which must be in local list */
4276 client = silc_idlist_find_client_by_id(server->local_list,
4277 SILC_ID_GET_ID(id), TRUE, NULL);
4279 /* Backup checks global list also */
4280 if (server->server_type == SILC_BACKUP_ROUTER)
4281 client = silc_idlist_find_client_by_id(server->global_list,
4282 SILC_ID_GET_ID(id), TRUE, NULL);
4284 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4285 silc_server_command_send_status_data(cmd, SILC_COMMAND_WATCH,
4286 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
4287 0, 2, tmp, tmp_len);
4292 /* Take public key for watching by public key */
4293 pk = silc_argument_get_arg_type(cmd->args, 4, &pk_len);
4296 add_nick = silc_argument_get_arg_type(cmd->args, 2, &add_nick_len);
4297 del_nick = silc_argument_get_arg_type(cmd->args, 3, &del_nick_len);
4298 if (!add_nick && !del_nick && !pk) {
4299 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4300 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4305 if (add_nick && add_nick_len > 128) {
4307 add_nick[add_nick_len - 1] = '\0';
4309 if (del_nick && del_nick_len > 128) {
4311 del_nick[del_nick_len - 1] = '\0';
4314 /* Add new nickname to be watched in our cell */
4316 nick = silc_identifier_check(add_nick, add_nick_len, SILC_STRING_UTF8, 128,
4319 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4320 SILC_STATUS_ERR_BAD_NICKNAME, 0);
4324 /* Hash the nick, we have the hash saved, not nicks because we can
4325 do one to one mapping to the nick from Client ID hash this way. */
4326 silc_hash_make(server->md5hash, nick, add_nick_len, hash);
4328 /* Check whether this client is already watching this nickname */
4329 if (silc_hash_table_find_by_context(server->watcher_list, hash,
4331 /* Nickname is alredy being watched for this client */
4332 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4333 SILC_STATUS_ERR_NICKNAME_IN_USE,
4339 /* Get the nickname from the watcher list and use the same key in
4340 new entries as well. If key doesn't exist then create it. */
4341 if (!silc_hash_table_find(server->watcher_list, hash, (void *)&tmp, NULL))
4342 tmp = silc_memdup(hash, CLIENTID_HASH_LEN);
4344 /* Add the client to the watcher list with the specified nickname hash. */
4345 silc_hash_table_add(server->watcher_list, tmp, client);
4349 /* Delete nickname from watch list */
4351 nick = silc_identifier_check(del_nick, del_nick_len, SILC_STRING_UTF8, 128,
4354 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4355 SILC_STATUS_ERR_BAD_NICKNAME, 0);
4359 /* Hash the nick, we have the hash saved, not nicks because we can
4360 do one to one mapping to the nick from Client ID hash this way. */
4361 silc_hash_make(server->md5hash, nick, del_nick_len, hash);
4363 /* Check that this client is watching for this nickname */
4364 if (!silc_hash_table_find_by_context(server->watcher_list, hash,
4365 client, (void *)&tmp)) {
4366 /* Nickname is alredy being watched for this client */
4367 silc_server_command_send_status_data(cmd, SILC_COMMAND_WATCH,
4368 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
4369 2, nick, del_nick_len);
4374 /* Delete the nickname from the watcher list. */
4375 silc_hash_table_del_by_context(server->watcher_list, hash, client);
4377 /* Now check whether there still exists entries with this key, if not
4378 then free the key to not leak memory. */
4379 if (!silc_hash_table_find(server->watcher_list, hash, NULL, NULL))
4384 /* Add/del public key */
4387 SilcArgumentPayload pkargs;
4389 SilcPublicKey public_key, pkkey;
4392 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4393 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4398 /* Get the argument from the Argument List Payload */
4399 SILC_GET16_MSB(pkargc, pk);
4400 pkargs = silc_argument_payload_parse(pk + 2, pk_len - 2, pkargc);
4402 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4403 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4408 pk = silc_argument_get_next_arg(pkargs, &type, &pk_len);
4410 if (!silc_public_key_payload_decode(pk, pk_len, &public_key)) {
4411 pk = silc_argument_get_next_arg(pkargs, &type, &pk_len);
4418 /* Add public key to watch list */
4420 /* Check whether this client is already watching this public key */
4421 if (silc_hash_table_find_by_context(server->watcher_list_pk,
4422 public_key, client, NULL)) {
4423 silc_pkcs_public_key_free(public_key);
4424 silc_server_command_send_status_reply(
4425 cmd, SILC_COMMAND_WATCH,
4426 SILC_STATUS_ERR_NICKNAME_IN_USE, 0);
4430 /* Get the public key from the watcher list and use the same key in
4431 new entries as well. If key doesn't exist then create it. */
4433 if (!silc_hash_table_find(server->watcher_list_pk, public_key,
4434 (void *)&pkkey, NULL))
4437 silc_pkcs_public_key_free(public_key);
4439 /* Add the client to the watcher list with the specified public
4441 silc_hash_table_add(server->watcher_list_pk, pkkey, client);
4443 } else if (type == 0x01) {
4444 /* Delete public key from watch list */
4446 /* Check that this client is watching this public key */
4447 if (silc_hash_table_find_by_context(server->watcher_list_pk,
4450 silc_pkcs_public_key_free(public_key);
4451 silc_server_command_send_status_reply(
4452 cmd, SILC_COMMAND_WATCH,
4453 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4457 /* Delete the public key from the watcher list. */
4458 silc_hash_table_del_by_context(server->watcher_list_pk,
4459 public_key, client);
4461 /* Now check whether there still exists entries with this key, if
4462 not then free the key to not leak memory. */
4463 if (!silc_hash_table_find(server->watcher_list_pk, hash, NULL, NULL))
4464 silc_pkcs_public_key_free(pkkey);
4465 silc_pkcs_public_key_free(public_key);
4468 pk = silc_argument_get_next_arg(pkargs, &type, &pk_len);
4473 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4476 /* Distribute the watch list to backup routers too */
4477 if (server->backup) {
4481 cmd->server->stat.commands_sent++;
4483 old_ident = silc_command_get_ident(cmd->payload);
4484 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4485 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4486 silc_server_backup_send(server, silc_packet_get_context(cmd->sock),
4487 SILC_PACKET_COMMAND,
4488 cmd->packet->flags, tmpbuf->data,
4489 silc_buffer_len(tmpbuf),
4491 silc_command_set_ident(cmd->payload, old_ident);
4492 silc_buffer_free(tmpbuf);
4496 silc_server_command_free(cmd);
4499 /* Server side of SILCOPER command. Client uses this comand to obtain router
4500 operator privileges to this router. */
4502 SILC_SERVER_CMD_FUNC(silcoper)
4504 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4505 SilcServer server = cmd->server;
4506 SilcClientEntry client = silc_packet_get_context(cmd->sock);
4507 unsigned char *username = NULL, *auth;
4509 SilcServerConfigAdmin *admin;
4510 SilcIDListData idata = (SilcIDListData)client;
4511 SilcBool result = FALSE;
4512 SilcPublicKey cached_key;
4513 const char *hostname, *ip;
4515 if (client->data.conn_type != SILC_CONN_CLIENT || !client)
4518 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4520 silc_socket_stream_get_info(silc_packet_stream_get_stream(cmd->sock),
4521 NULL, &hostname, &ip, NULL);
4523 if (server->server_type != SILC_ROUTER) {
4524 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4525 SILC_STATUS_ERR_AUTH_FAILED, 0);
4529 /* Get the username */
4530 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4532 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4533 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4538 /* Check username */
4539 username = silc_identifier_check(username, tmp_len, SILC_STRING_UTF8, 128,
4542 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4543 SILC_STATUS_ERR_BAD_USERNAME,
4548 /* Get the admin configuration */
4549 admin = silc_server_config_find_admin(server, (char *)ip,
4550 username, client->nickname);
4552 admin = silc_server_config_find_admin(server, (char *)hostname,
4553 username, client->nickname);
4555 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4556 SILC_STATUS_ERR_AUTH_FAILED, 0);
4557 SILC_LOG_INFO(("SILCOPER authentication failed for username '%s' by "
4558 "nickname '%s' from %s", username,
4559 client->nickname, hostname));
4564 /* Get the authentication payload */
4565 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4567 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4568 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4573 /* Verify the authentication data. If both passphrase and public key
4574 is set then try both of them. */
4575 if (admin->passphrase)
4576 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4577 admin->passphrase, admin->passphrase_len,
4578 idata->hash, client->id, SILC_ID_CLIENT);
4579 if (!result && admin->publickeys) {
4581 silc_server_get_public_key(server,
4582 SILC_SKR_USAGE_SERVICE_AUTHORIZATION, admin);
4585 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4586 cached_key, 0, idata->hash,
4587 client->id, SILC_ID_CLIENT);
4590 /* Authentication failed */
4591 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4592 SILC_STATUS_ERR_AUTH_FAILED, 0);
4596 /* Client is now router operator */
4597 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4599 /* Update statistics */
4600 if (SILC_IS_LOCAL(client))
4601 server->stat.my_router_ops++;
4602 if (server->server_type == SILC_ROUTER)
4603 server->stat.router_ops++;
4605 /* Send UMODE change to primary router */
4606 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
4607 SILC_BROADCAST(server), client->id,
4610 /* Check if anyone is watching this nickname */
4611 if (server->server_type == SILC_ROUTER)
4612 silc_server_check_watcher_list(server, client, NULL,
4613 SILC_NOTIFY_TYPE_UMODE_CHANGE);
4615 /* Send reply to the sender */
4616 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4620 silc_free(username);
4621 silc_server_command_free(cmd);
4624 /* Server side of command BAN. This is used to manage the ban list of the
4625 channel. To add clients and remove clients from the ban list. */
4627 SILC_SERVER_CMD_FUNC(ban)
4629 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4630 SilcServer server = cmd->server;
4631 SilcClientEntry client = silc_packet_get_context(cmd->sock);
4632 SilcBuffer list, tmp2;
4633 SilcChannelEntry channel;
4634 SilcChannelClientEntry chl;
4636 unsigned char *tmp_id, *tmp, *atype = NULL;
4637 SilcUInt32 id_len, len, len2;
4638 SilcArgumentPayload args;
4639 SilcHashTableList htl;
4641 SilcUInt16 argc = 0, ident = silc_command_get_ident(cmd->payload);
4642 SilcBufferStruct blist;
4644 if (client->data.conn_type != SILC_CONN_CLIENT || !client)
4647 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4649 /* Get Channel ID */
4650 if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
4651 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4652 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4656 /* Get channel entry. The server must know about the channel since the
4657 client is expected to be on the channel. */
4658 channel = silc_idlist_find_channel_by_id(server->local_list,
4659 SILC_ID_GET_ID(id), NULL);
4661 channel = silc_idlist_find_channel_by_id(server->global_list,
4662 SILC_ID_GET_ID(id), NULL);
4664 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4665 silc_server_command_send_status_data(
4666 cmd, SILC_COMMAND_BAN,
4667 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
4668 0, 2, tmp_id, id_len);
4673 /* Check whether this client is on the channel */
4674 if (!silc_server_client_on_channel(client, channel, &chl)) {
4675 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4676 silc_server_command_send_status_data(cmd, SILC_COMMAND_BAN,
4677 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
4682 /* The client must be at least channel operator. */
4683 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4684 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4685 silc_server_command_send_status_data(cmd, SILC_COMMAND_BAN,
4686 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0,
4691 /* Get the ban information */
4692 tmp = silc_argument_get_arg_type(cmd->args, 3, &len2);
4693 if (tmp && len2 > 2) {
4694 /* Parse the arguments to see they are constructed correctly */
4695 SILC_GET16_MSB(argc, tmp);
4696 args = silc_argument_payload_parse(tmp + 2, len2 - 2, argc);
4698 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4699 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4704 /* Get the type of action */
4705 atype = silc_argument_get_arg_type(cmd->args, 2, &len);
4706 if (atype && len == 1) {
4707 if (atype[0] == 0x00) {
4708 /* Allocate hash table for ban list if it doesn't exist yet */
4709 if (!channel->ban_list)
4711 silc_hash_table_alloc(0, silc_hash_ptr,
4713 silc_server_inviteban_destruct, channel,
4716 /* Check for resource limit */
4717 if (silc_hash_table_count(channel->ban_list) > 64) {
4718 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4719 SILC_STATUS_ERR_RESOURCE_LIMIT,
4725 /* Now add or delete the information. */
4726 if (!silc_server_inviteban_process(server, channel->ban_list,
4727 (SilcUInt8)atype[0], args)) {
4728 silc_server_command_send_status_reply(
4729 cmd, SILC_COMMAND_BAN,
4730 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4735 silc_argument_payload_free(args);
4738 /* Encode ban list */
4740 if (channel->ban_list && silc_hash_table_count(channel->ban_list)) {
4741 list = silc_buffer_alloc_size(2);
4742 silc_buffer_format(list,
4743 SILC_STR_UI_SHORT(silc_hash_table_count(
4744 channel->ban_list)),
4746 silc_hash_table_list(channel->ban_list, &htl);
4747 while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2))
4748 list = silc_argument_payload_encode_one(list, tmp2->data,
4749 silc_buffer_len(tmp2),
4750 SILC_PTR_TO_32(type));
4751 silc_hash_table_list_reset(&htl);
4754 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4756 /* Send BAN notify type to local servers (but not clients) and to
4758 if (atype && tmp && len2) {
4759 silc_buffer_set(&blist, tmp, len2);
4761 /* Send to local servers if we are router */
4762 if (server->server_type == SILC_ROUTER)
4763 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, FALSE,
4764 SILC_NOTIFY_TYPE_BAN, 3,
4767 tmp ? blist.data : NULL,
4768 tmp ? silc_buffer_len(&blist) : 0);
4770 /* Send to network. */
4771 silc_server_send_notify_ban(server, SILC_PRIMARY_ROUTE(server),
4772 SILC_BROADCAST(server), channel, atype,
4776 /* Send the reply back to the client */
4777 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_BAN,
4778 SILC_STATUS_OK, 0, ident, 2,
4780 3, list ? list->data : NULL,
4781 list ? silc_buffer_len(list) : 0);
4782 silc_buffer_free(list);
4785 silc_server_command_free(cmd);
4788 /* Server side command of LEAVE. Removes client from a channel. */
4790 SILC_SERVER_CMD_FUNC(leave)
4792 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4793 SilcServer server = cmd->server;
4794 SilcPacketStream sock = cmd->sock;
4795 SilcClientEntry id_entry = silc_packet_get_context(cmd->sock);
4797 SilcChannelEntry channel;
4801 if (id_entry->data.conn_type != SILC_CONN_CLIENT || !id_entry)
4804 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4806 /* Get Channel ID */
4807 if (!silc_argument_get_decoded(cmd->args, 1, SILC_ARGUMENT_ID, &id, NULL)) {
4808 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4809 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4813 /* Get channel entry */
4814 channel = silc_idlist_find_channel_by_id(server->local_list,
4815 SILC_ID_GET_ID(id), NULL);
4817 channel = silc_idlist_find_channel_by_id(server->global_list,
4818 SILC_ID_GET_ID(id), NULL);
4820 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4821 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4822 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
4828 /* Check whether this client is on the channel */
4829 if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
4830 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4831 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4832 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
4837 /* Notify routers that they should remove this client from their list
4838 of clients on the channel. Send LEAVE notify type. */
4839 silc_server_send_notify_leave(server, SILC_PRIMARY_ROUTE(server),
4840 SILC_BROADCAST(server), channel, id_entry->id);
4842 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4843 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4844 SILC_STATUS_OK, 0, 2, tmp, len);
4846 /* Remove client from channel */
4847 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4849 /* If the channel does not exist anymore we won't send anything */
4852 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4853 /* Re-generate channel key */
4854 if (!silc_server_create_channel_key(server, channel, 0))
4857 /* Send the channel key */
4858 silc_server_send_channel_key(server, NULL, channel,
4859 server->server_type == SILC_ROUTER ?
4860 FALSE : !server->standalone);
4864 silc_server_command_free(cmd);
4867 /* Server side of command USERS. Resolves clients and their USERS currently
4868 joined on the requested channel. The list of Client ID's and their modes
4869 on the channel is sent back. */
4871 SILC_SERVER_CMD_FUNC(users)
4873 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4874 SilcServer server = cmd->server;
4875 SilcIDListData idata = silc_packet_get_context(cmd->sock);
4876 SilcChannelEntry channel;
4879 unsigned char *channel_id;
4880 SilcUInt32 channel_id_len;
4881 SilcBuffer client_id_list;
4882 SilcBuffer client_mode_list;
4883 unsigned char lc[4];
4884 SilcUInt32 list_count = 0;
4885 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4886 char *channel_name, *channel_namec = NULL;
4888 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
4890 /* Get Channel ID */
4891 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4893 /* Get channel name */
4894 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
4896 if (!channel_id && !channel_name) {
4897 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4898 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4902 /* Check channel name */
4904 channel_namec = silc_channel_name_check(channel_name, strlen(channel_name),
4905 SILC_STRING_UTF8, 256, NULL);
4906 if (!channel_namec) {
4907 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4908 SILC_STATUS_ERR_BAD_CHANNEL, 0);
4913 /* Check Channel ID */
4915 if (!silc_id_payload_parse_id(channel_id, channel_id_len, &id)) {
4916 silc_server_command_send_status_data(cmd, SILC_COMMAND_USERS,
4917 SILC_STATUS_ERR_BAD_CHANNEL_ID, 0,
4918 2, channel_id, channel_id_len);
4923 /* If we are server and we don't know about this channel we will send
4924 the command to our router. If we know about the channel then we also
4925 have the list of users already. */
4927 channel = silc_idlist_find_channel_by_id(server->local_list,
4928 SILC_ID_GET_ID(id), NULL);
4930 channel = silc_idlist_find_channel_by_name(server->local_list,
4931 channel_namec, NULL);
4933 if (!channel || (!server->standalone && (channel->disabled ||
4934 !channel->users_resolved))) {
4935 if (server->server_type != SILC_ROUTER && !server->standalone &&
4940 cmd->server->stat.commands_sent++;
4942 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4943 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4945 /* Send USERS command */
4946 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
4947 SILC_PACKET_COMMAND, cmd->packet->flags,
4948 tmpbuf->data, silc_buffer_len(tmpbuf));
4950 /* Reprocess this packet after received reply */
4951 silc_server_command_pending(server, SILC_COMMAND_USERS,
4952 silc_command_get_ident(cmd->payload),
4953 silc_server_command_users,
4954 silc_server_command_dup(cmd));
4955 cmd->pending = TRUE;
4956 silc_command_set_ident(cmd->payload, ident);
4957 silc_buffer_free(tmpbuf);
4961 /* Check the global list as well. */
4963 channel = silc_idlist_find_channel_by_id(server->global_list,
4964 SILC_ID_GET_ID(id), NULL);
4966 channel = silc_idlist_find_channel_by_name(server->global_list,
4967 channel_namec, NULL);
4969 /* Channel really does not exist */
4971 silc_server_command_send_status_data(
4972 cmd, SILC_COMMAND_USERS,
4973 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID, 0,
4974 2, channel_id, channel_id_len);
4976 silc_server_command_send_status_data(
4977 cmd, SILC_COMMAND_USERS,
4978 SILC_STATUS_ERR_NO_SUCH_CHANNEL, 0,
4979 2, channel_name, strlen(channel_name));
4984 /* If the channel is private or secret do not send anything, unless the
4985 user requesting this command is on the channel or is server */
4986 if (idata->conn_type == SILC_CONN_CLIENT) {
4987 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
4988 && !silc_server_client_on_channel((SilcClientEntry)idata, channel,
4990 silc_server_command_send_status_data(cmd, SILC_COMMAND_USERS,
4991 SILC_STATUS_ERR_NO_SUCH_CHANNEL, 0,
4992 2, channel->channel_name,
4993 strlen(channel->channel_name));
4998 /* Get the users list */
4999 if (!silc_server_get_users_on_channel(server, channel, &client_id_list,
5000 &client_mode_list, &list_count)) {
5002 client_id_list = NULL;
5003 client_mode_list = NULL;
5007 SILC_PUT32_MSB(list_count, lc);
5010 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5011 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_USERS,
5012 SILC_STATUS_OK, 0, ident, 4,
5013 2, idp->data, silc_buffer_len(idp),
5016 client_id_list->data : NULL,
5018 silc_buffer_len(client_id_list) : 0,
5019 5, client_mode_list ?
5020 client_mode_list->data : NULL,
5022 silc_buffer_len(client_mode_list) : 0);
5023 silc_buffer_free(idp);
5025 silc_buffer_free(client_id_list);
5026 if (client_mode_list)
5027 silc_buffer_free(client_mode_list);
5030 silc_free(channel_namec);
5031 silc_server_command_free(cmd);
5034 /* Server side of command GETKEY. This fetches the client's public key
5035 from the server where to the client is connected. */
5037 SILC_SERVER_CMD_FUNC(getkey)
5039 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5040 SilcServer server = cmd->server;
5041 SilcClientEntry client;
5042 SilcServerEntry server_entry;
5043 SilcClientID client_id;
5044 SilcServerID server_id;
5045 SilcIDPayload idp = NULL;
5046 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5049 SilcBuffer pk = NULL;
5051 SilcPublicKey public_key;
5053 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5055 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5056 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5060 idp = silc_id_payload_parse(tmp, tmp_len);
5062 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5063 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5068 id_type = silc_id_payload_get_type(idp);
5069 if (id_type == SILC_ID_CLIENT) {
5070 silc_id_payload_get_id(idp, &client_id, sizeof(client_id));
5072 /* If the client is not found from local list there is no chance it
5073 would be locally connected client so send the command further. */
5074 client = silc_idlist_find_client_by_id(server->local_list,
5075 &client_id, TRUE, NULL);
5077 client = silc_idlist_find_client_by_id(server->global_list,
5078 &client_id, TRUE, NULL);
5080 if ((!client && !cmd->pending && !server->standalone) ||
5081 (client && !client->connection && !cmd->pending &&
5082 !(client->mode & SILC_UMODE_DETACHED)) ||
5083 (client && !client->data.public_key && !cmd->pending)) {
5085 SilcUInt16 old_ident;
5086 SilcPacketStream dest_sock;
5088 dest_sock = silc_server_get_client_route(server, NULL, 0,
5089 &client_id, NULL, NULL);
5094 cmd->server->stat.commands_sent++;
5096 old_ident = silc_command_get_ident(cmd->payload);
5097 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5098 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5100 silc_server_packet_send(server, dest_sock,
5101 SILC_PACKET_COMMAND, cmd->packet->flags,
5102 tmpbuf->data, silc_buffer_len(tmpbuf));
5104 /* Reprocess this packet after received reply from router */
5105 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5106 silc_command_get_ident(cmd->payload),
5107 silc_server_command_getkey,
5108 silc_server_command_dup(cmd));
5109 cmd->pending = TRUE;
5110 silc_command_set_ident(cmd->payload, old_ident);
5111 silc_buffer_free(tmpbuf);
5116 silc_server_command_send_status_data(cmd, SILC_COMMAND_GETKEY,
5117 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5118 0, 2, tmp, tmp_len);
5122 /* The client is locally connected, just get the public key and
5123 send it back. If they key does not exist then do not send it,
5124 send just OK reply */
5125 public_key = client->data.public_key;
5127 pk = silc_public_key_payload_encode(public_key);
5128 } else if (id_type == SILC_ID_SERVER) {
5129 silc_id_payload_get_id(idp, &server_id, sizeof(server_id));
5131 /* If the server is not found from local list there is no chance it
5132 would be locally connected server so send the command further. */
5133 server_entry = silc_idlist_find_server_by_id(server->local_list,
5134 &server_id, TRUE, NULL);
5136 server_entry = silc_idlist_find_server_by_id(server->global_list,
5137 &server_id, TRUE, NULL);
5139 if (server_entry != server->id_entry &&
5140 ((!server_entry && !cmd->pending && !server->standalone) ||
5141 (server_entry && !server_entry->connection && !cmd->pending &&
5142 !server->standalone) ||
5143 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5144 !server->standalone))) {
5146 SilcUInt16 old_ident;
5149 cmd->server->stat.commands_sent++;
5151 old_ident = silc_command_get_ident(cmd->payload);
5152 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5153 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5155 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5156 SILC_PACKET_COMMAND, cmd->packet->flags,
5157 tmpbuf->data, silc_buffer_len(tmpbuf));
5159 /* Reprocess this packet after received reply from router */
5160 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5161 silc_command_get_ident(cmd->payload),
5162 silc_server_command_getkey,
5163 silc_server_command_dup(cmd));
5164 cmd->pending = TRUE;
5165 silc_command_set_ident(cmd->payload, old_ident);
5166 silc_buffer_free(tmpbuf);
5170 if (!server_entry) {
5171 silc_server_command_send_status_data(cmd, SILC_COMMAND_GETKEY,
5172 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
5173 0, 2, tmp, tmp_len);
5177 /* If they key does not exist then do not send it, send just OK reply */
5178 public_key = (!server_entry->data.public_key ?
5179 (server_entry == server->id_entry ? server->public_key :
5180 NULL) : server_entry->data.public_key);
5182 pk = silc_public_key_payload_encode(public_key);
5187 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5188 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_GETKEY,
5189 SILC_STATUS_OK, 0, ident, 2,
5191 3, pk ? pk->data : NULL,
5192 pk ? silc_buffer_len(pk) : 0);
5196 silc_id_payload_free(idp);
5197 silc_buffer_free(pk);
5198 silc_server_command_free(cmd);
5201 /* Server side of command SERVICE. */
5202 /* XXX currently this just sends empty reply back */
5204 SILC_SERVER_CMD_FUNC(service)
5206 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5207 SilcServer server = cmd->server;
5208 SilcUInt32 tmp_len, auth_len;
5209 unsigned char *service_name, *auth;
5210 SilcBool send_list = FALSE;
5211 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5213 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SERVICE, cmd, 0, 256);
5215 /* Get requested service */
5216 service_name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5217 if (service_name && tmp_len) {
5218 /* Verify service name */
5219 if (!silc_identifier_verify(service_name, tmp_len,
5220 SILC_STRING_UTF8, 256)) {
5221 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SERVICE,
5222 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5228 /* Get authentication payload if present */
5229 auth = silc_argument_get_arg_type(cmd->args, 2, &auth_len);
5237 /* Send our service list back */
5238 silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_SERVICE,
5239 SILC_STATUS_OK, 0, ident, 0);
5242 silc_server_command_free(cmd);
5246 /* Private range commands, specific to this implementation */
5248 /* Server side command of CONNECT. Connects us to the specified remote
5249 server or router. */
5251 SILC_SERVER_CMD_FUNC(connect)
5253 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5254 SilcServer server = cmd->server;
5255 SilcClientEntry client = silc_packet_get_context(cmd->sock);
5256 unsigned char *tmp, *host;
5258 SilcUInt32 port = SILC_PORT;
5260 if (client->data.conn_type != SILC_CONN_CLIENT || !client)
5263 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
5265 /* Check whether client has the permissions. */
5266 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5267 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5268 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5269 SILC_STATUS_ERR_NO_SERVER_PRIV, 0);
5273 if (server->server_type == SILC_ROUTER && !server->backup_router &&
5274 client->mode & SILC_UMODE_SERVER_OPERATOR) {
5275 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5276 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
5280 /* Get the remote server */
5281 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5283 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5284 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5290 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5292 SILC_GET32_MSB(port, tmp);
5294 /* Create the connection. It is done with timeout and is async. */
5295 silc_server_create_connection(server, FALSE, FALSE, host, port, NULL, NULL);
5297 /* Send reply to the sender */
5298 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5302 silc_server_command_free(cmd);
5305 /* Server side command of CLOSE. Closes connection to a specified server. */
5307 SILC_SERVER_CMD_FUNC(close)
5309 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5310 SilcServer server = cmd->server;
5311 SilcClientEntry client = silc_packet_get_context(cmd->sock);
5312 SilcServerEntry server_entry;
5313 SilcPacketStream sock;
5316 unsigned char *name;
5317 SilcUInt32 port = SILC_PORT;
5319 if (client->data.conn_type != SILC_CONN_CLIENT || !client)
5322 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
5324 /* Check whether client has the permissions. */
5325 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5326 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5327 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5328 SILC_STATUS_ERR_NO_SERVER_PRIV,
5333 /* Get the remote server */
5334 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5336 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5337 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5343 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5345 SILC_GET32_MSB(port, tmp);
5347 server_entry = silc_idlist_find_server_by_conn(server->local_list,
5348 name, port, TRUE, NULL);
5350 server_entry = silc_idlist_find_server_by_conn(server->global_list,
5351 name, port, TRUE, NULL);
5352 if (!server_entry) {
5353 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5354 SILC_STATUS_ERR_NO_SERVER_ID, 0);
5358 if (server_entry == server->id_entry) {
5359 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5360 SILC_STATUS_ERR_NO_SERVER_ID, 0);
5364 /* Send reply to the sender */
5365 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5368 /* Close the connection to the server */
5369 sock = server_entry->connection;
5371 if (server_entry->server_type == SILC_BACKUP_ROUTER) {
5372 server->backup_closed = TRUE;
5373 silc_server_backup_del(server, server_entry);
5376 server->backup_noswitch = TRUE;
5377 if (server->router == server_entry) {
5378 server->id_entry->router = NULL;
5379 server->router = NULL;
5380 server->standalone = TRUE;
5382 silc_server_disconnect_remote(server, sock,
5383 SILC_STATUS_ERR_BANNED_FROM_SERVER,
5384 "Closed by administrator");
5385 silc_server_free_sock_user_data(server, sock, NULL);
5386 server->backup_noswitch = FALSE;
5389 silc_server_command_free(cmd);
5392 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
5393 active connections. */
5395 SILC_SERVER_CMD_FUNC(shutdown)
5397 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5398 SilcServer server = cmd->server;
5399 SilcClientEntry client = silc_packet_get_context(cmd->sock);
5401 if (client->data.conn_type != SILC_CONN_CLIENT || !client)
5404 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
5406 /* Check whether client has the permission. */
5407 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5408 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5409 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5410 SILC_STATUS_ERR_NO_SERVER_PRIV,
5415 /* Send reply to the sender */
5416 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5419 /* Then, gracefully, or not, bring the server down. */
5420 silc_server_stop(server);
5424 silc_server_command_free(cmd);