5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2005 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
21 #include "serverincludes.h"
22 #include "server_internal.h"
24 static int silc_server_is_registered(SilcServer server,
25 SilcSocketConnection sock,
26 SilcServerCommandContext cmd,
29 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
34 silc_server_command_send_status_data(SilcServerCommandContext cmd,
39 const unsigned char *arg,
42 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
43 SilcServerCommandReplyContext cmdr,
45 SILC_TASK_CALLBACK(silc_server_command_process_timeout);
47 /* Server command list. */
48 SilcServerCommand silc_command_list[] =
50 SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
51 SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
52 SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
53 SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
54 SILC_SERVER_CMD(list, LIST, SILC_CF_LAG_STRICT | SILC_CF_REG),
55 SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
56 SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
57 SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
58 SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG_STRICT | SILC_CF_REG | SILC_CF_OPER),
59 SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
60 SILC_SERVER_CMD(stats, STATS, SILC_CF_LAG | SILC_CF_REG),
61 SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
62 SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
63 SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG_STRICT | SILC_CF_REG),
64 SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
65 SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
66 SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG_STRICT | SILC_CF_REG),
67 SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
68 SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
69 SILC_SERVER_CMD(ban, BAN, SILC_CF_LAG_STRICT | SILC_CF_REG),
70 SILC_SERVER_CMD(detach, DETACH, SILC_CF_LAG_STRICT | SILC_CF_REG),
71 SILC_SERVER_CMD(watch, WATCH, SILC_CF_LAG | SILC_CF_REG),
72 SILC_SERVER_CMD(silcoper, SILCOPER,
73 SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
74 SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
75 SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
76 SILC_SERVER_CMD(getkey, GETKEY, SILC_CF_LAG | SILC_CF_REG),
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 SilcSocketConnection sock,
129 SilcServerCommandContext cmd,
132 SilcIDListData idata = (SilcIDListData)sock->user_data;
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 = (SilcClientEntry)timeout->ctx->sock->user_data;
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 SilcSocketConnection sock,
192 SilcPacketContext *packet)
194 SilcServerCommandContext ctx;
195 SilcServerCommand *cmd;
198 /* Allocate command context. This must be free'd by the
199 command routine receiving it. */
200 ctx = silc_server_command_alloc();
201 ctx->server = server;
202 ctx->sock = silc_socket_dup(sock);
203 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
205 /* Parse the command payload in the packet */
206 ctx->payload = silc_command_payload_parse(packet->buffer->data,
207 packet->buffer->len);
209 SILC_LOG_ERROR(("Bad command payload, dropped (%s:%d [%s])",
210 sock->hostname, sock->port,
211 (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
212 sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
213 sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
215 silc_packet_context_free(packet);
216 silc_socket_free(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_server_command_free(ctx);
236 /* Execute client's commands always with timeout. Normally they are
237 executed with zero (0) timeout but if client is sending command more
238 frequently than once in 2 seconds, then the timeout may be 0 to 2
240 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
241 SilcClientEntry client = (SilcClientEntry)sock->user_data;
242 SilcServerCommandTimeout timeout;
246 SILC_LOG_DEBUG(("Client entry is invalid"));
247 silc_server_command_free(ctx);
251 timeout = silc_calloc(1, sizeof(*timeout));
255 if (client->last_command && (time(NULL) - client->last_command) < 2) {
256 client->fast_command++;
259 if (client->fast_command - 2 <= 0)
260 client->fast_command = 0;
262 client->fast_command -= 2;
266 if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
267 (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
268 silc_schedule_task_add(server->schedule, sock->sock,
269 silc_server_command_process_timeout, timeout,
270 (client->fast_command < 3 ? 0 :
271 2 - (time(NULL) - client->last_command)),
272 (client->fast_command < 3 ? 200000 : 0),
273 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
275 silc_schedule_task_add(server->schedule, sock->sock,
276 silc_server_command_process_timeout, timeout,
277 0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
281 /* Execute for server */
283 if (!(cmd->flags & SILC_CF_REG)) {
284 SILC_LOG_DEBUG(("Calling %s command", silc_get_command_name(cmd->cmd)));
286 } else if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) {
287 SILC_LOG_DEBUG(("Calling %s command", silc_get_command_name(cmd->cmd)));
290 SILC_LOG_DEBUG(("Server is not registered"));
291 silc_server_command_free(ctx);
295 /* Allocate Command Context */
297 SilcServerCommandContext silc_server_command_alloc()
299 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
304 /* Free's the command context allocated before executing the command */
306 void silc_server_command_free(SilcServerCommandContext ctx)
309 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
311 if (ctx->users < 1) {
313 silc_command_payload_free(ctx->payload);
315 silc_packet_context_free(ctx->packet);
317 silc_socket_free(ctx->sock); /* Decrease reference counter */
322 /* Duplicate Command Context by adding reference counter. The context won't
323 be free'd untill it hits zero. */
325 SilcServerCommandContext
326 silc_server_command_dup(SilcServerCommandContext ctx)
329 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
334 /* Timeout for pending command. If reply to pending command never arrives
335 this is called to free resources. */
337 SILC_TASK_CALLBACK(silc_server_command_pending_timeout)
339 SilcServer server = app_context;
340 SilcServerCommandPending *reply = context;
341 SilcServerCommandReplyContext cmdr;
345 SILC_LOG_DEBUG(("Timeout pending command"));
347 /* Allocate temporary and bogus command reply context */
348 cmdr = silc_calloc(1, sizeof(*cmdr));
349 cmdr->server = server;
350 cmdr->ident = reply->ident;
352 /* Check for pending commands and mark to be exeucted */
354 silc_server_command_pending_check(server, reply->reply_cmd,
355 reply->ident, &cmdr->callbacks_count);
357 /* Create bogus command reply with an error inside */
359 silc_command_reply_payload_encode_va(reply->reply_cmd ? reply->reply_cmd :
360 SILC_COMMAND_RESERVED,
361 SILC_STATUS_ERR_TIMEDOUT, 0,
363 cmdr->payload = silc_command_payload_parse(tmpreply->data, tmpreply->len);
364 silc_buffer_free(tmpreply);
366 /* Call all callbacks. Same as SILC_SERVER_PENDING_EXEC macro. */
367 for (i = 0; i < cmdr->callbacks_count; i++)
368 if (cmdr->callbacks[i].callback)
369 (*cmdr->callbacks[i].callback)(cmdr->callbacks[i].context, cmdr);
371 silc_server_command_pending_del(server, reply->reply_cmd, reply->ident);
372 silc_server_command_reply_free(cmdr);
375 /* Add new pending command to be executed when reply to a command has been
376 received. The `reply_cmd' is the command that will call the `callback'
377 with `context' when reply has been received. It can be SILC_COMMAND_NONE
378 to match any command with the `ident'. If `ident' is non-zero
379 the `callback' will be executed when received reply with command
380 identifier `ident'. If there already exists pending command for the
381 specified command, ident, callback and context this function has no
384 bool silc_server_command_pending(SilcServer server,
385 SilcCommand reply_cmd,
387 SilcCommandCb callback,
390 return silc_server_command_pending_timed(server, reply_cmd, ident, callback,
394 /* Same as silc_server_command_pending with specific timeout for pending
395 commands. If the `timeout' is zero default timeout is used. */
397 bool silc_server_command_pending_timed(SilcServer server,
398 SilcCommand reply_cmd,
400 SilcCommandCb callback,
404 SilcServerCommandPending *reply;
406 /* Check whether identical pending already exists for same command,
407 ident, callback and callback context. If it does then it would be
408 error to register it again. */
409 silc_dlist_start(server->pending_commands);
410 while ((reply = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
411 if (reply->reply_cmd == reply_cmd && reply->ident == ident &&
412 reply->callback == callback && reply->context == context)
416 reply = silc_calloc(1, sizeof(*reply));
417 reply->reply_cmd = reply_cmd;
418 reply->ident = ident;
419 reply->context = context;
420 reply->callback = callback;
422 silc_schedule_task_add(server->schedule, 0,
423 silc_server_command_pending_timeout, reply,
424 timeout ? timeout : 10, 0,
425 SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
426 silc_dlist_add(server->pending_commands, reply);
431 /* Deletes pending command by reply command type. */
433 void silc_server_command_pending_del(SilcServer server,
434 SilcCommand reply_cmd,
437 SilcServerCommandPending *r;
439 silc_dlist_start(server->pending_commands);
440 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
441 if ((r->reply_cmd == reply_cmd || (r->reply_cmd == SILC_COMMAND_NONE &&
443 && r->ident == ident) {
444 silc_dlist_del(server->pending_commands, r);
446 silc_schedule_task_del(server->schedule, r->timeout);
452 /* Checks for pending commands and marks callbacks to be called from
453 the command reply function. Returns TRUE if there were pending command. */
455 SilcServerCommandPendingCallbacks
456 silc_server_command_pending_check(SilcServer server,
459 SilcUInt32 *callbacks_count)
461 SilcServerCommandPending *r;
462 SilcServerCommandPendingCallbacks callbacks = NULL;
465 silc_dlist_start(server->pending_commands);
466 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
467 if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE)
468 && r->ident == ident) {
469 callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
470 callbacks[i].context = r->context;
471 callbacks[i].callback = r->callback;
472 r->reply_check = TRUE;
477 *callbacks_count = i;
481 /* Sends simple status message as command reply packet */
484 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
491 SILC_LOG_DEBUG(("Sending command status %d", status));
494 silc_command_reply_payload_encode_va(command, status, error,
495 silc_command_get_ident(cmd->payload),
497 silc_server_packet_send(cmd->server, cmd->sock,
498 SILC_PACKET_COMMAND_REPLY, 0,
499 buffer->data, buffer->len, FALSE);
500 silc_buffer_free(buffer);
503 /* Sends command status reply with one extra argument. The argument
504 type must be sent as argument. */
507 silc_server_command_send_status_data(SilcServerCommandContext cmd,
512 const unsigned char *arg,
517 SILC_LOG_DEBUG(("Sending command status %d", status));
520 silc_command_reply_payload_encode_va(command, status, 0,
521 silc_command_get_ident(cmd->payload),
522 1, arg_type, arg, arg_len);
523 silc_server_packet_send(cmd->server, cmd->sock,
524 SILC_PACKET_COMMAND_REPLY, 0,
525 buffer->data, buffer->len, FALSE);
526 silc_buffer_free(buffer);
530 silc_server_command_send_status_data2(SilcServerCommandContext cmd,
534 SilcUInt32 arg_type1,
535 const unsigned char *arg1,
537 SilcUInt32 arg_type2,
538 const unsigned char *arg2,
543 SILC_LOG_DEBUG(("Sending command status %d", status));
546 silc_command_reply_payload_encode_va(command, status, 0,
547 silc_command_get_ident(cmd->payload),
548 2, arg_type1, arg1, arg_len1,
549 arg_type2, arg2, arg_len2);
550 silc_server_packet_send(cmd->server, cmd->sock,
551 SILC_PACKET_COMMAND_REPLY, 0,
552 buffer->data, buffer->len, FALSE);
553 silc_buffer_free(buffer);
556 /* This function can be called to check whether in the command reply
557 an error occurred. This function has no effect if this is called
558 when the command function was not called as pending command callback.
559 This returns TRUE if error had occurred. */
562 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
563 SilcServerCommandReplyContext cmdr,
566 if (!cmd->pending || !cmdr)
569 if (!silc_command_get_status(cmdr->payload, NULL, NULL)) {
572 /* Send the same command reply payload */
573 silc_command_set_command(cmdr->payload, silc_command_get(cmd->payload));
574 silc_command_set_ident(cmdr->payload,
575 silc_command_get_ident(cmd->payload));
576 buffer = silc_command_payload_encode_payload(cmdr->payload);
577 silc_server_packet_send(cmd->server, cmd->sock,
578 SILC_PACKET_COMMAND_REPLY, 0,
579 buffer->data, buffer->len, FALSE);
580 silc_buffer_free(buffer);
587 /* Server side of command WHOIS. */
589 SILC_SERVER_CMD_FUNC(whois)
591 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
592 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 256);
593 silc_server_query_command(cmd->server, SILC_COMMAND_WHOIS, cmd);
594 silc_server_command_free(cmd);
597 /* Server side of command WHOWAS. */
599 SILC_SERVER_CMD_FUNC(whowas)
601 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
602 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
603 silc_server_query_command(cmd->server, SILC_COMMAND_WHOWAS, cmd);
604 silc_server_command_free(cmd);
607 /* Server side of command IDENTIFY. */
609 SILC_SERVER_CMD_FUNC(identify)
611 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
612 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 256);
613 silc_server_query_command(cmd->server, SILC_COMMAND_IDENTIFY, cmd);
614 silc_server_command_free(cmd);
617 /* Server side of command NICK. Sets nickname for user. Setting
618 nickname causes generation of a new client ID for the client. The
619 new client ID is sent to the client after changing the nickname. */
621 SILC_SERVER_CMD_FUNC(nick)
623 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
624 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
625 SilcServer server = cmd->server;
626 SilcBuffer packet, nidp, oidp = NULL;
627 SilcClientID *new_id;
629 unsigned char *nick = NULL;
630 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
633 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
636 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
639 nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
641 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
642 SILC_STATUS_ERR_BAD_NICKNAME, 0);
646 /* Truncate over long nicks */
647 if (nick_len > 128) {
652 /* Check for valid nickname string */
653 nick = silc_identifier_check(nick, nick_len, SILC_STRING_UTF8, 128,
656 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
657 SILC_STATUS_ERR_BAD_NICKNAME, 0);
662 /* Check for same nickname */
663 if (!memcmp(client->nickname, nick, nick_len)) {
664 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
666 nick = client->nickname;
670 /* Create new Client ID */
671 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
673 cmd->server->md5hash, nick, nick_len,
677 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
678 SILC_STATUS_ERR_BAD_NICKNAME, 0);
682 nick = silc_realloc(nick, sizeof(*nick) * (nick_len + 2));
684 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
685 SILC_STATUS_ERR_BAD_NICKNAME, 0);
689 nick[nick_len - 1] = '\0';
691 snprintf(&nick[nick_len - 2], 1, "%d", nickfail);
694 /* Send notify about nickname change to our router. We send the new
695 ID and ask to replace it with the old one. If we are router the
696 packet is broadcasted. Send NICK_CHANGE notify. */
697 silc_server_send_notify_nick_change(server, SILC_PRIMARY_ROUTE(server),
698 SILC_BROADCAST(server), client->id,
701 /* Check if anyone is watching the old nickname */
702 if (server->server_type == SILC_ROUTER)
703 silc_server_check_watcher_list(server, client, nick,
704 SILC_NOTIFY_TYPE_NICK_CHANGE);
706 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
708 /* Remove old cache entry */
709 silc_idcache_del_by_context(server->local_list->clients, client);
711 silc_free(client->id);
714 silc_free(client->nickname);
715 client->nickname = nick;
717 /* Update client cache */
718 silc_idcache_add(server->local_list->clients, client->nickname,
719 client->id, (void *)client, 0, NULL);
721 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
723 /* Send NICK_CHANGE notify to the client's channels */
724 silc_server_send_notify_on_channels(server, NULL, client,
725 SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
726 oidp->data, oidp->len,
727 nidp->data, nidp->len,
729 strlen(client->nickname));
731 /* Check if anyone is watching the new nickname */
732 if (server->server_type == SILC_ROUTER)
733 silc_server_check_watcher_list(server, client, NULL,
734 SILC_NOTIFY_TYPE_NICK_CHANGE);
737 /* Send the new Client ID as reply command back to client */
738 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
739 SILC_STATUS_OK, 0, ident, 2,
740 2, nidp->data, nidp->len,
742 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
743 0, packet->data, packet->len, FALSE);
745 silc_buffer_free(packet);
746 silc_buffer_free(nidp);
748 silc_buffer_free(oidp);
751 silc_server_command_free(cmd);
754 /* Sends the LIST command reply */
757 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
758 SilcChannelEntry *lch,
759 SilcUInt32 lch_count,
760 SilcChannelEntry *gch,
761 SilcUInt32 gch_count)
764 SilcBuffer packet, idp;
765 SilcChannelEntry entry;
767 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
769 unsigned char usercount[4];
771 int valid_lcount = 0, valid_rcount = 0;
773 for (i = 0; i < lch_count; i++) {
774 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
779 for (i = 0; i < gch_count; i++) {
780 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
786 if (!lch_count && !gch_count) {
787 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
792 status = SILC_STATUS_OK;
793 if ((lch_count + gch_count) > 1)
794 status = SILC_STATUS_LIST_START;
797 for (i = 0, k = 0; i < lch_count; i++) {
803 status = SILC_STATUS_LIST_ITEM;
804 if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
805 status = SILC_STATUS_LIST_END;
807 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
809 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
811 memset(usercount, 0, sizeof(usercount));
813 topic = entry->topic;
814 users = silc_hash_table_count(entry->user_list);
815 SILC_PUT32_MSB(users, usercount);
820 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
822 2, idp->data, idp->len,
823 3, entry->channel_name,
824 strlen(entry->channel_name),
825 4, topic, topic ? strlen(topic) : 0,
827 silc_server_packet_send(cmd->server, cmd->sock,
828 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
830 silc_buffer_free(packet);
831 silc_buffer_free(idp);
836 for (i = 0, k = 0; i < gch_count; i++) {
842 status = SILC_STATUS_LIST_ITEM;
843 if (valid_rcount > 1 && k == valid_rcount - 1)
844 status = SILC_STATUS_LIST_END;
846 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
848 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
850 memset(usercount, 0, sizeof(usercount));
852 topic = entry->topic;
853 users = entry->user_count;
854 SILC_PUT32_MSB(users, usercount);
859 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
861 2, idp->data, idp->len,
862 3, entry->channel_name,
863 strlen(entry->channel_name),
864 4, topic, topic ? strlen(topic) : 0,
866 silc_server_packet_send(cmd->server, cmd->sock,
867 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
869 silc_buffer_free(packet);
870 silc_buffer_free(idp);
875 /* Server side of LIST command. This lists the channel of the requested
876 server. Secret channels are not listed. */
878 SILC_SERVER_CMD_FUNC(list)
880 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
881 SilcServer server = cmd->server;
882 SilcChannelID *channel_id = NULL;
885 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
886 SilcUInt32 lch_count = 0, gch_count = 0;
888 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
890 /* If we are normal server, send the command to router, since we
891 want to know all channels in the network. */
892 if (!cmd->pending && server->server_type != SILC_ROUTER &&
893 !server->standalone) {
895 SilcUInt16 old_ident;
897 old_ident = silc_command_get_ident(cmd->payload);
898 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
899 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
900 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
901 SILC_PACKET_COMMAND, cmd->packet->flags,
902 tmpbuf->data, tmpbuf->len, TRUE);
904 /* Reprocess this packet after received reply from router */
905 silc_server_command_pending(server, SILC_COMMAND_LIST,
906 silc_command_get_ident(cmd->payload),
907 silc_server_command_list,
908 silc_server_command_dup(cmd));
910 silc_command_set_ident(cmd->payload, old_ident);
911 silc_buffer_free(tmpbuf);
916 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
918 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
920 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
921 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
926 /* Get the channels from local list */
927 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
930 /* Get the channels from global list */
931 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
935 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
936 gchannels, gch_count);
938 silc_free(lchannels);
939 silc_free(gchannels);
942 silc_server_command_free(cmd);
945 /* Server side of TOPIC command. Sets topic for channel and/or returns
946 current topic to client. */
948 SILC_SERVER_CMD_FUNC(topic)
950 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
951 SilcServer server = cmd->server;
952 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
953 SilcChannelID *channel_id;
954 SilcChannelEntry channel;
955 SilcChannelClientEntry chl;
956 SilcBuffer packet, idp;
958 SilcUInt32 argc, tmp_len;
959 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
961 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
964 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
966 argc = silc_argument_get_arg_num(cmd->args);
969 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
971 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
972 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
975 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
977 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
978 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
982 /* Check whether the channel exists */
983 channel = silc_idlist_find_channel_by_id(server->local_list,
986 channel = silc_idlist_find_channel_by_id(server->global_list,
989 silc_server_command_send_status_data(cmd, SILC_COMMAND_TOPIC,
990 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
998 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1000 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1001 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1006 if (strlen(tmp) > 256) {
1007 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1008 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1013 /* See whether the client is on channel and has rights to change topic */
1014 if (!silc_server_client_on_channel(client, channel, &chl)) {
1015 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1016 silc_server_command_send_status_data(cmd, SILC_COMMAND_TOPIC,
1017 SILC_STATUS_ERR_NOT_ON_CHANNEL,
1018 0, 2, tmp, tmp_len);
1022 if (channel->mode & SILC_CHANNEL_MODE_TOPIC &&
1023 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
1024 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
1025 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1026 silc_server_command_send_status_data(cmd, SILC_COMMAND_TOPIC,
1027 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
1028 0, 2, tmp, tmp_len);
1032 if (!channel->topic || strcmp(channel->topic, tmp)) {
1033 /* Set the topic for channel */
1034 silc_free(channel->topic);
1035 channel->topic = strdup(tmp);
1037 /* Send TOPIC_SET notify type to the network */
1038 silc_server_send_notify_topic_set(server, SILC_PRIMARY_ROUTE(server),
1039 SILC_BROADCAST(server), channel,
1040 client->id, SILC_ID_CLIENT,
1043 /* Send notify about topic change to all clients on the channel */
1044 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1045 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
1046 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
1047 idp->data, idp->len,
1049 strlen(channel->topic));
1050 silc_buffer_free(idp);
1054 /* Send the topic to client as reply packet */
1055 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1056 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1057 SILC_STATUS_OK, 0, ident, 2,
1058 2, idp->data, idp->len,
1061 strlen(channel->topic) : 0);
1062 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1063 0, packet->data, packet->len, FALSE);
1065 silc_buffer_free(packet);
1066 silc_buffer_free(idp);
1067 silc_free(channel_id);
1070 silc_server_command_free(cmd);
1073 /* Server side of INVITE command. Invites some client to join some channel.
1074 This command is also used to manage the invite list of the channel. */
1076 SILC_SERVER_CMD_FUNC(invite)
1078 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1079 SilcServer server = cmd->server;
1080 SilcSocketConnection sock = cmd->sock, dest_sock;
1081 SilcChannelClientEntry chl;
1082 SilcClientEntry sender, dest;
1083 SilcClientID *dest_id = NULL;
1084 SilcChannelEntry channel;
1085 SilcChannelID *channel_id = NULL;
1086 SilcIDListData idata;
1087 SilcArgumentPayload args;
1088 SilcHashTableList htl;
1089 SilcBuffer packet, list, tmp2;
1090 SilcBufferStruct alist;
1091 unsigned char *tmp, *atype = NULL;
1092 SilcUInt32 len, type, len2;
1093 SilcUInt16 argc = 0, ident = silc_command_get_ident(cmd->payload);
1095 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
1097 /* Get Channel ID */
1098 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1100 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1101 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
1104 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
1106 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1107 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
1111 /* Get the channel entry */
1112 channel = silc_idlist_find_channel_by_id(server->local_list,
1115 channel = silc_idlist_find_channel_by_id(server->global_list,
1118 silc_server_command_send_status_data(cmd, SILC_COMMAND_INVITE,
1119 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
1125 /* Check whether the sender of this command is on the channel. */
1126 sender = (SilcClientEntry)sock->user_data;
1127 if (!sender || !silc_server_client_on_channel(sender, channel, &chl)) {
1128 silc_server_command_send_status_data(cmd, SILC_COMMAND_INVITE,
1129 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
1134 /* Check whether the channel is invite-only channel. If yes then the
1135 sender of this command must be at least channel operator. */
1136 if (channel->mode & SILC_CHANNEL_MODE_INVITE &&
1137 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
1138 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
1139 silc_server_command_send_status_data(cmd, SILC_COMMAND_INVITE,
1140 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
1145 /* Get destination client ID */
1146 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1150 dest_id = silc_id_payload_parse_id(tmp, len, NULL);
1152 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1153 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
1157 /* Get the client entry */
1158 dest = silc_server_query_client(server, dest_id, FALSE, &resolve);
1160 if (server->server_type != SILC_SERVER || !resolve || cmd->pending) {
1161 silc_server_command_send_status_data(
1162 cmd, SILC_COMMAND_INVITE,
1163 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0,
1168 /* The client info is being resolved. Reprocess this packet after
1169 receiving the reply to the query. */
1170 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1172 silc_server_command_invite,
1173 silc_server_command_dup(cmd));
1174 cmd->pending = TRUE;
1178 /* Check whether the requested client is already on the channel. */
1179 if (silc_server_client_on_channel(dest, channel, NULL)) {
1180 atype = silc_argument_get_arg_type(cmd->args, 1, &len2);
1181 silc_server_command_send_status_data2(cmd, SILC_COMMAND_INVITE,
1182 SILC_STATUS_ERR_USER_ON_CHANNEL,
1188 /* Get route to the client */
1189 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id,
1192 silc_server_command_send_status_data(cmd, SILC_COMMAND_INVITE,
1193 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1198 /* Add the client to the invite list */
1200 /* Allocate hash table for invite list if it doesn't exist yet */
1201 if (!channel->invite_list)
1202 channel->invite_list =
1203 silc_hash_table_alloc(0, silc_hash_ptr,
1205 silc_server_inviteban_destruct, channel, TRUE);
1207 /* Check if the ID is in the list already */
1208 silc_hash_table_list(channel->invite_list, &htl);
1209 while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) {
1210 if (type == 3 && !memcmp(tmp2->data, tmp, len)) {
1215 silc_hash_table_list_reset(&htl);
1217 /* Add new Client ID to invite list */
1219 list = silc_buffer_alloc_size(len);
1220 silc_buffer_put(list, tmp, len);
1221 silc_hash_table_add(channel->invite_list, (void *)3, list);
1224 if (!(dest->mode & SILC_UMODE_BLOCK_INVITE)) {
1225 /* Send notify to the client that is invited to the channel */
1226 SilcBuffer idp, idp2;
1227 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1228 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1229 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
1231 SILC_NOTIFY_TYPE_INVITE, 3,
1232 idp->data, idp->len,
1233 channel->channel_name,
1234 strlen(channel->channel_name),
1235 idp2->data, idp2->len);
1236 silc_buffer_free(idp);
1237 silc_buffer_free(idp2);
1241 /* Get the invite information */
1242 tmp = silc_argument_get_arg_type(cmd->args, 4, &len2);
1243 if (tmp && len2 > 2) {
1244 /* Parse the arguments to see they are constructed correctly */
1245 SILC_GET16_MSB(argc, tmp);
1246 args = silc_argument_payload_parse(tmp + 2, len2 - 2, argc);
1248 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1249 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1254 /* Get the type of action */
1255 atype = silc_argument_get_arg_type(cmd->args, 3, &len);
1256 if (atype && len == 1) {
1257 if (atype[0] == 0x00) {
1258 /* Allocate hash table for invite list if it doesn't exist yet */
1259 if (!channel->invite_list)
1260 channel->invite_list =
1261 silc_hash_table_alloc(0, silc_hash_ptr,
1263 silc_server_inviteban_destruct, channel,
1266 /* Check for resource limit */
1267 if (silc_hash_table_count(channel->invite_list) > 64) {
1268 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1269 SILC_STATUS_ERR_RESOURCE_LIMIT,
1275 /* Now add or delete the information. */
1276 silc_server_inviteban_process(server, channel->invite_list,
1277 (SilcUInt8)atype[0], args);
1279 silc_argument_payload_free(args);
1282 /* Encode invite list */
1284 if (channel->invite_list && silc_hash_table_count(channel->invite_list)) {
1285 list = silc_buffer_alloc_size(2);
1286 silc_buffer_format(list,
1287 SILC_STR_UI_SHORT(silc_hash_table_count(
1288 channel->invite_list)),
1290 silc_hash_table_list(channel->invite_list, &htl);
1291 while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2))
1292 list = silc_argument_payload_encode_one(list, tmp2->data, tmp2->len,
1294 silc_hash_table_list_reset(&htl);
1297 /* The notify is sent to local servers (not clients), and to network. */
1298 if (atype && tmp && len2) {
1299 silc_buffer_set(&alist, tmp, len2);
1301 /* Send to local servers if we are router */
1302 if (server->server_type == SILC_ROUTER) {
1303 SilcBuffer idp, idp2;
1304 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1305 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1306 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, FALSE,
1307 SILC_NOTIFY_TYPE_INVITE, 5,
1308 idp->data, idp->len,
1309 channel->channel_name,
1310 strlen(channel->channel_name),
1311 idp2->data, idp2->len,
1313 tmp ? alist.data : NULL,
1314 tmp ? alist.len : 0);
1315 silc_buffer_free(idp);
1316 silc_buffer_free(idp2);
1319 /* Send to network */
1320 silc_server_send_notify_invite(server, SILC_PRIMARY_ROUTE(server),
1321 SILC_BROADCAST(server), channel,
1323 tmp ? &alist : NULL);
1326 /* Send invite list back only if the list was modified, or no arguments
1329 argc = silc_argument_get_arg_num(cmd->args);
1332 if (silc_argument_get_arg_type(cmd->args, 3, &len))
1335 /* Send command reply */
1336 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1337 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
1338 SILC_STATUS_OK, 0, ident, 2,
1342 type && list ? list->len : 0);
1343 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1344 packet->data, packet->len, FALSE);
1345 silc_buffer_free(packet);
1346 silc_buffer_free(list);
1350 silc_free(channel_id);
1351 silc_server_command_free(cmd);
1355 SilcSocketConnection sock;
1359 /* Quits connection to client. This gets called if client won't
1360 close the connection even when it has issued QUIT command. */
1362 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
1364 SilcServer server = app_context;
1365 QuitInternal q = (QuitInternal)context;
1367 if (q->sock->user_data) {
1368 /* Free all client specific data, such as client entry and entires
1369 on channels this client may be on. */
1370 silc_server_free_client_data(server, q->sock, q->sock->user_data,
1372 q->sock->user_data = NULL;
1375 if (!SILC_IS_DISCONNECTED(q->sock))
1376 /* Close the connection on our side */
1377 silc_server_close_connection(server, q->sock);
1379 silc_socket_free(q->sock);
1380 silc_free(q->signoff);
1384 /* Quits SILC session. This is the normal way to disconnect client. */
1386 SILC_SERVER_CMD_FUNC(quit)
1388 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1389 SilcServer server = cmd->server;
1390 SilcSocketConnection sock = cmd->sock;
1392 unsigned char *tmp = NULL;
1395 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
1397 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1401 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1405 q = silc_calloc(1, sizeof(*q));
1406 q->sock = silc_socket_dup(sock);
1407 q->signoff = tmp ? strdup(tmp) : NULL;
1409 /* We quit the connection with little timeout */
1410 silc_schedule_task_add(server->schedule, sock->sock,
1411 silc_server_command_quit_cb, (void *)q,
1412 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1415 silc_server_command_free(cmd);
1418 /* Server side of command KILL. This command is used by router operator
1419 to remove an client from the SILC Network temporarily. */
1421 SILC_SERVER_CMD_FUNC(kill)
1423 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1424 SilcServer server = cmd->server;
1425 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1426 SilcClientEntry remote_client;
1427 SilcClientID *client_id = NULL;
1428 unsigned char *tmp, *comment, *auth;
1429 SilcUInt32 tmp_len, tmp_len2, auth_len;
1431 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 3);
1433 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
1436 /* Get authentication payload if present */
1437 auth = silc_argument_get_arg_type(cmd->args, 3, &auth_len);
1440 /* Router operator killing */
1442 /* KILL command works only on router */
1443 if (server->server_type != SILC_ROUTER) {
1444 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1445 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
1449 /* Check whether client has the permissions. */
1450 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
1451 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1452 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
1457 /* Get the client ID */
1458 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1460 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1461 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1465 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1467 silc_server_command_send_status_data(cmd, SILC_COMMAND_KILL,
1468 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1469 0, 2, tmp, tmp_len);
1473 /* Get the client entry */
1474 remote_client = silc_idlist_find_client_by_id(server->local_list,
1475 client_id, TRUE, NULL);
1476 if (!remote_client) {
1477 remote_client = silc_idlist_find_client_by_id(server->global_list,
1478 client_id, TRUE, NULL);
1479 if (!remote_client) {
1480 silc_server_command_send_status_data(cmd, SILC_COMMAND_KILL,
1481 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1482 0, 2, tmp, tmp_len);
1488 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
1489 if (comment && tmp_len2 > 128) {
1491 comment[127] = '\0';
1494 /* If authentication data is provided then verify that killing is
1496 if (auth && auth_len) {
1497 SilcSocketConnection sock;
1499 if (!SILC_IS_LOCAL(remote_client) || !remote_client->data.public_key) {
1500 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1501 SILC_STATUS_ERR_OPERATION_ALLOWED,
1506 /* Verify the signature */
1507 if (!silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
1508 remote_client->data.public_key, 0,
1509 server->sha1hash, remote_client->id,
1511 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1512 SILC_STATUS_ERR_AUTH_FAILED, 0);
1516 /* Send reply to the sender */
1517 silc_server_command_send_status_data(cmd, SILC_COMMAND_KILL,
1521 /* Do normal signoff for the destination client */
1522 sock = remote_client->connection;
1523 silc_server_remove_from_channels(server, NULL, remote_client,
1524 TRUE, (char *)"Killed", TRUE, TRUE);
1525 silc_server_free_client_data(server, NULL, remote_client, TRUE,
1527 (unsigned char *)"Killed");
1529 silc_server_close_connection(server, sock);
1531 /* Router operator killing */
1533 /* Send reply to the sender */
1534 silc_server_command_send_status_data(cmd, SILC_COMMAND_KILL,
1538 /* Check if anyone is watching this nickname */
1539 if (server->server_type == SILC_ROUTER)
1540 silc_server_check_watcher_list(server, client, NULL,
1541 SILC_NOTIFY_TYPE_KILLED);
1543 /* Now do the killing */
1544 silc_server_kill_client(server, remote_client, comment, client->id,
1549 silc_free(client_id);
1550 silc_server_command_free(cmd);
1553 /* Server side of command INFO. This sends information about us to
1554 the client. If client requested specific server we will send the
1555 command to that server. */
1557 SILC_SERVER_CMD_FUNC(info)
1559 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1560 SilcServer server = cmd->server;
1561 SilcBuffer packet, idp;
1564 char *dest_server = NULL, *server_info = NULL, *server_name;
1565 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1566 SilcServerEntry entry = NULL;
1567 SilcServerID *server_id = NULL;
1569 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
1571 /* Get server name */
1572 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1574 /* Check server name */
1575 dest_server = silc_identifier_check(dest_server, strlen(dest_server),
1576 SILC_STRING_UTF8, 256, &tmp_len);
1578 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1579 SILC_STATUS_ERR_BAD_SERVER, 0);
1585 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1587 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1589 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1590 SILC_STATUS_ERR_NO_SERVER_ID, 0);
1596 /* Check whether we have this server cached */
1597 entry = silc_idlist_find_server_by_id(server->local_list,
1598 server_id, TRUE, NULL);
1600 entry = silc_idlist_find_server_by_id(server->global_list,
1601 server_id, TRUE, NULL);
1602 if (!entry && server->server_type != SILC_SERVER) {
1603 silc_server_command_send_status_data(cmd, SILC_COMMAND_INFO,
1604 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
1605 0, 2, tmp, tmp_len);
1611 /* Some buggy servers has sent request to router about themselves. */
1612 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
1615 if ((!dest_server && !server_id && !entry) || (entry &&
1616 entry == server->id_entry) ||
1617 (dest_server && !cmd->pending &&
1618 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
1619 /* Send our reply */
1620 char info_string[256];
1622 memset(info_string, 0, sizeof(info_string));
1623 snprintf(info_string, sizeof(info_string),
1624 "location: %s server: %s admin: %s <%s>",
1625 server->config->server_info->location,
1626 server->config->server_info->server_type,
1627 server->config->server_info->admin,
1628 server->config->server_info->email);
1630 server_info = info_string;
1631 entry = server->id_entry;
1633 /* Check whether we have this server cached */
1634 if (!entry && dest_server) {
1635 entry = silc_idlist_find_server_by_name(server->global_list,
1636 dest_server, TRUE, NULL);
1638 entry = silc_idlist_find_server_by_name(server->local_list,
1639 dest_server, TRUE, NULL);
1643 if (!cmd->pending &&
1644 server->server_type != SILC_SERVER && entry && !entry->server_info) {
1645 /* Send to the server */
1647 SilcUInt16 old_ident;
1649 old_ident = silc_command_get_ident(cmd->payload);
1650 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1651 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1653 silc_server_packet_send(server, entry->connection,
1654 SILC_PACKET_COMMAND, cmd->packet->flags,
1655 tmpbuf->data, tmpbuf->len, TRUE);
1657 /* Reprocess this packet after received reply from router */
1658 silc_server_command_pending(server, SILC_COMMAND_INFO,
1659 silc_command_get_ident(cmd->payload),
1660 silc_server_command_info,
1661 silc_server_command_dup(cmd));
1662 cmd->pending = TRUE;
1663 silc_command_set_ident(cmd->payload, old_ident);
1664 silc_buffer_free(tmpbuf);
1668 if (!entry && !cmd->pending && !server->standalone) {
1669 /* Send to the primary router */
1671 SilcUInt16 old_ident;
1673 old_ident = silc_command_get_ident(cmd->payload);
1674 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1675 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1677 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
1678 SILC_PACKET_COMMAND, cmd->packet->flags,
1679 tmpbuf->data, tmpbuf->len, TRUE);
1681 /* Reprocess this packet after received reply from router */
1682 silc_server_command_pending(server, SILC_COMMAND_INFO,
1683 silc_command_get_ident(cmd->payload),
1684 silc_server_command_info,
1685 silc_server_command_dup(cmd));
1686 cmd->pending = TRUE;
1687 silc_command_set_ident(cmd->payload, old_ident);
1688 silc_buffer_free(tmpbuf);
1693 silc_free(server_id);
1697 silc_server_command_send_status_data(cmd, SILC_COMMAND_INFO,
1698 SILC_STATUS_ERR_NO_SUCH_SERVER, 0,
1700 strlen(dest_server));
1704 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1706 server_info = entry->server_info;
1707 server_name = entry->server_name;
1709 /* Send the reply */
1710 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
1711 SILC_STATUS_OK, 0, ident, 3,
1712 2, idp->data, idp->len,
1714 strlen(server_name),
1717 strlen(server_info) : 0);
1718 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1719 packet->data, packet->len, FALSE);
1721 silc_buffer_free(packet);
1722 silc_buffer_free(idp);
1725 silc_free(dest_server);
1726 silc_server_command_free(cmd);
1729 /* Server side of command PING. This just replies to the ping. */
1731 SILC_SERVER_CMD_FUNC(ping)
1733 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1734 SilcServer server = cmd->server;
1737 SilcServerID *server_id = NULL;
1739 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PING, cmd, 1, 1);
1742 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1744 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1745 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1749 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1753 if (SILC_ID_SERVER_COMPARE(server_id, server->id)) {
1754 /* Send our reply */
1755 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1758 silc_server_command_send_status_data(cmd, SILC_COMMAND_PING,
1759 SILC_STATUS_ERR_NO_SUCH_SERVER_ID, 0,
1765 silc_free(server_id);
1766 silc_server_command_free(cmd);
1769 /* Server side of command STATS. */
1771 SILC_SERVER_CMD_FUNC(stats)
1773 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1774 SilcServer server = cmd->server;
1775 SilcServerID *server_id;
1778 SilcBuffer packet, stats;
1779 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1782 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1);
1785 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1787 silc_server_command_send_status_reply(cmd, SILC_COMMAND_STATS,
1788 SILC_STATUS_ERR_NO_SERVER_ID, 0);
1791 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1795 /* The ID must be ours */
1796 if (!SILC_ID_SERVER_COMPARE(server->id, server_id)) {
1797 silc_server_command_send_status_data(cmd, SILC_COMMAND_STATS,
1798 SILC_STATUS_ERR_NO_SUCH_SERVER_ID, 0,
1800 silc_free(server_id);
1803 silc_free(server_id);
1805 /* If we are router then just send everything we got. If we are normal
1806 server then we'll send this to our router to get all the latest
1807 statistical information. */
1808 if (!cmd->pending && server->server_type != SILC_ROUTER &&
1809 !server->standalone) {
1810 /* Send request to our router */
1811 SilcBuffer idp = silc_id_payload_encode(server->router->id,
1813 packet = silc_command_payload_encode_va(SILC_COMMAND_STATS,
1814 ++server->cmd_ident, 1,
1815 1, idp->data, idp->len);
1816 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
1817 SILC_PACKET_COMMAND, 0, packet->data,
1818 packet->len, FALSE);
1820 /* Reprocess this packet after received reply from router */
1821 silc_server_command_pending(server, SILC_COMMAND_STATS,
1823 silc_server_command_stats,
1824 silc_server_command_dup(cmd));
1825 cmd->pending = TRUE;
1826 silc_buffer_free(packet);
1827 silc_buffer_free(idp);
1831 /* Send our reply to sender */
1832 uptime = time(NULL) - server->starttime;
1834 stats = silc_buffer_alloc_size(60);
1835 silc_buffer_format(stats,
1836 SILC_STR_UI_INT(server->starttime),
1837 SILC_STR_UI_INT(uptime),
1838 SILC_STR_UI_INT(server->stat.my_clients),
1839 SILC_STR_UI_INT(server->stat.my_channels),
1840 SILC_STR_UI_INT(server->stat.my_server_ops),
1841 SILC_STR_UI_INT(server->stat.my_router_ops),
1842 SILC_STR_UI_INT(server->stat.cell_clients),
1843 SILC_STR_UI_INT(server->stat.cell_channels),
1844 SILC_STR_UI_INT(server->stat.cell_servers),
1845 SILC_STR_UI_INT(server->stat.clients),
1846 SILC_STR_UI_INT(server->stat.channels),
1847 SILC_STR_UI_INT(server->stat.servers),
1848 SILC_STR_UI_INT(server->stat.routers),
1849 SILC_STR_UI_INT(server->stat.server_ops),
1850 SILC_STR_UI_INT(server->stat.router_ops),
1853 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_STATS,
1854 SILC_STATUS_OK, 0, ident, 2,
1856 3, stats->data, stats->len);
1857 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1858 0, packet->data, packet->len, FALSE);
1859 silc_buffer_free(packet);
1860 silc_buffer_free(stats);
1863 silc_server_command_free(cmd);
1866 /* Internal routine to join channel. The channel sent to this function
1867 has been either created or resolved from ID lists. This joins the sent
1868 client to the channel. */
1870 static void silc_server_command_join_channel(SilcServer server,
1871 SilcServerCommandContext cmd,
1872 SilcChannelEntry channel,
1873 SilcClientID *client_id,
1877 const unsigned char *auth,
1878 SilcUInt32 auth_len,
1879 const unsigned char *cauth,
1880 SilcUInt32 cauth_len)
1882 SilcSocketConnection sock = cmd->sock;
1884 SilcUInt32 tmp_len, user_count;
1885 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4], ulimit[4];
1886 SilcClientEntry client;
1887 SilcChannelClientEntry chl;
1888 SilcBuffer reply, chidp, clidp, keyp = NULL;
1889 SilcBuffer user_list, mode_list, invite_list, ban_list;
1890 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1891 char check[512], check2[512];
1892 bool founder = FALSE;
1894 SilcBuffer fkey = NULL, chpklist = NULL;
1897 SILC_LOG_DEBUG(("Joining client to channel"));
1902 /* Get the client entry */
1903 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1904 client = (SilcClientEntry)sock->user_data;
1908 client = silc_server_query_client(server, client_id, FALSE,
1911 if (!resolve || cmd->pending) {
1912 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1913 silc_server_command_send_status_data(
1914 cmd, SILC_COMMAND_JOIN,
1915 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0,
1920 /* The client info is being resolved. Reprocess this packet after
1921 receiving the reply to the query. */
1922 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1924 silc_server_command_join,
1925 silc_server_command_dup(cmd));
1926 cmd->pending = TRUE;
1930 if (!client->data.public_key &&
1931 (auth || cauth || channel->ban_list ||
1932 (channel->mode & SILC_CHANNEL_MODE_INVITE))) {
1933 if (cmd->pending == 2)
1936 /* We must retrieve the client's public key by sending
1937 GETKEY command. Reprocess this packet after receiving the key */
1938 clidp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
1939 silc_server_send_command(server, cmd->sock,
1940 SILC_COMMAND_GETKEY, ++server->cmd_ident,
1941 1, 1, clidp->data, clidp->len);
1942 silc_buffer_free(clidp);
1943 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
1945 silc_server_command_join,
1946 silc_server_command_dup(cmd));
1951 cmd->pending = FALSE;
1955 * Check founder auth payload if provided. If client can gain founder
1956 * privileges it can override various conditions on joining the channel,
1957 * and can have directly the founder mode set on the channel.
1959 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1960 SilcIDListData idata = (SilcIDListData)client;
1961 SilcChannelClientEntry chl2;
1962 SilcHashTableList htl;
1964 if (channel->founder_key && idata->public_key &&
1965 silc_pkcs_public_key_compare(channel->founder_key,
1966 idata->public_key)) {
1967 /* Check whether the client is to become founder */
1968 if (silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
1969 channel->founder_key, 0, server->sha1hash,
1970 client->id, SILC_ID_CLIENT)) {
1972 /* There cannot be anyone else as founder on the channel now. This
1973 client is definitely the founder due to this authentication */
1974 silc_hash_table_list(channel->user_list, &htl);
1975 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
1976 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
1977 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
1978 silc_server_force_cumode_change(server, NULL, channel, chl2,
1982 silc_hash_table_list_reset(&htl);
1984 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
1991 * Check channel modes
1995 memset(check, 0, sizeof(check));
1996 memset(check2, 0, sizeof(check2));
1997 silc_strncat(check, sizeof(check),
1998 client->nickname, strlen(client->nickname));
1999 silc_strncat(check, sizeof(check), "!", 1);
2000 silc_strncat(check, sizeof(check),
2001 client->username, strlen(client->username));
2002 if (!strchr(client->username, '@')) {
2003 silc_strncat(check, sizeof(check), "@", 1);
2004 silc_strncat(check, sizeof(check),
2005 cmd->sock->hostname, strlen(cmd->sock->hostname));
2008 silc_strncat(check2, sizeof(check2),
2009 client->nickname, strlen(client->nickname));
2010 if (!strchr(client->nickname, '@')) {
2011 silc_strncat(check2, sizeof(check2), "@", 1);
2012 silc_strncat(check2, sizeof(check2),
2013 SILC_IS_LOCAL(client) ? server->server_name :
2014 client->router->server_name,
2015 SILC_IS_LOCAL(client) ? strlen(server->server_name) :
2016 strlen(client->router->server_name));
2018 silc_strncat(check2, sizeof(check2), "!", 1);
2019 silc_strncat(check2, sizeof(check2),
2020 client->username, strlen(client->username));
2021 if (!strchr(client->username, '@')) {
2022 silc_strncat(check2, sizeof(check2), "@", 1);
2023 silc_strncat(check2, sizeof(check2),
2024 cmd->sock->hostname, strlen(cmd->sock->hostname));
2027 /* Check invite list if channel is invite-only channel */
2028 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2029 if (!channel->invite_list ||
2030 !silc_hash_table_count(channel->invite_list) ||
2031 (!silc_server_inviteban_match(server, channel->invite_list,
2033 !silc_server_inviteban_match(server, channel->invite_list,
2034 2, client->data.public_key) &&
2035 !silc_server_inviteban_match(server, channel->invite_list,
2036 1, client->nickname) &&
2037 !silc_server_inviteban_match(server, channel->invite_list,
2039 !silc_server_inviteban_match(server, channel->invite_list,
2041 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2042 silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
2043 SILC_STATUS_ERR_NOT_INVITED, 0,
2044 2, chidp->data, chidp->len);
2045 silc_buffer_free(chidp);
2050 /* Check ban list if it exists. If the client's nickname, server,
2051 username and/or hostname is in the ban list the access to the
2052 channel is denied. */
2053 if (channel->ban_list && silc_hash_table_count(channel->ban_list)) {
2054 if (silc_server_inviteban_match(server, channel->ban_list,
2056 silc_server_inviteban_match(server, channel->ban_list,
2057 2, client->data.public_key) ||
2058 silc_server_inviteban_match(server, channel->ban_list,
2059 1, client->nickname) ||
2060 silc_server_inviteban_match(server, channel->ban_list,
2062 silc_server_inviteban_match(server, channel->ban_list,
2064 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2065 silc_server_command_send_status_data(
2066 cmd, SILC_COMMAND_JOIN,
2067 SILC_STATUS_ERR_BANNED_FROM_CHANNEL, 0,
2068 2, chidp->data, chidp->len);
2069 silc_buffer_free(chidp);
2074 /* Check user count limit if set. */
2075 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
2076 if (silc_hash_table_count(channel->user_list) + 1 >
2077 channel->user_limit) {
2078 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2079 silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
2080 SILC_STATUS_ERR_CHANNEL_IS_FULL,
2081 0, 2, chidp->data, chidp->len);
2082 silc_buffer_free(chidp);
2088 /* Check the channel passphrase if set. */
2089 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2090 /* Get passphrase */
2091 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2093 passphrase = silc_memdup(tmp, tmp_len);
2095 if (!passphrase || !channel->passphrase ||
2096 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
2097 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2098 silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
2099 SILC_STATUS_ERR_BAD_PASSWORD, 0,
2100 2, chidp->data, chidp->len);
2101 silc_buffer_free(chidp);
2106 /* Verify channel authentication with channel public keys if set. */
2107 if (channel->mode & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
2108 if (!silc_server_verify_channel_auth(server, channel, client->id,
2109 cauth, cauth_len)) {
2110 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2111 SILC_STATUS_ERR_PERM_DENIED, 0);
2117 * Client is allowed to join to the channel. Make it happen.
2120 /* Check whether the client already is on the channel */
2121 if (silc_server_client_on_channel(client, channel, NULL)) {
2122 clidp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
2123 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2124 silc_server_command_send_status_data2(cmd, SILC_COMMAND_JOIN,
2125 SILC_STATUS_ERR_USER_ON_CHANNEL, 0,
2126 2, clidp->data, clidp->len,
2127 3, chidp->data, chidp->len);
2128 silc_buffer_free(clidp);
2129 silc_buffer_free(chidp);
2133 /* Generate new channel key as protocol dictates */
2135 if (!silc_server_create_channel_key(server, channel, 0))
2138 /* Send the channel key. This is broadcasted to the channel but is not
2139 sent to the client who is joining to the channel. */
2140 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
2141 silc_server_send_channel_key(server, NULL, channel,
2142 server->server_type == SILC_ROUTER ?
2143 FALSE : !server->standalone);
2146 /* Join the client to the channel by adding it to channel's user list.
2147 Add also the channel to client entry's channels list for fast cross-
2149 chl = silc_calloc(1, sizeof(*chl));
2151 chl->client = client;
2152 chl->channel = channel;
2153 silc_hash_table_add(channel->user_list, client, chl);
2154 silc_hash_table_add(client->channels, channel, chl);
2155 channel->user_count++;
2156 channel->disabled = FALSE;
2158 /* Get users on the channel */
2159 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
2162 /* Encode Client ID Payload of the original client who wants to join */
2163 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2165 /* Encode command reply packet */
2166 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2167 SILC_PUT32_MSB(channel->mode, mode);
2168 SILC_PUT32_MSB(created, tmp2);
2169 SILC_PUT32_MSB(user_count, tmp3);
2170 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2171 SILC_PUT32_MSB(channel->user_limit, ulimit);
2173 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
2174 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
2175 cipher = silc_cipher_get_name(channel->channel_key);
2176 keyp = silc_channel_key_payload_encode(silc_id_get_len(channel->id,
2179 strlen(cipher), cipher,
2180 channel->key_len / 8, channel->key);
2184 if (channel->founder_key)
2185 fkey = silc_pkcs_public_key_payload_encode(channel->founder_key);
2187 /* Encode invite list */
2189 if (channel->invite_list && silc_hash_table_count(channel->invite_list)) {
2190 SilcHashTableList htl;
2192 invite_list = silc_buffer_alloc_size(2);
2193 silc_buffer_format(invite_list,
2194 SILC_STR_UI_SHORT(silc_hash_table_count(
2195 channel->invite_list)),
2198 silc_hash_table_list(channel->invite_list, &htl);
2199 while (silc_hash_table_get(&htl, (void *)&tmp_len, (void *)&reply))
2200 invite_list = silc_argument_payload_encode_one(invite_list,
2202 reply->len, tmp_len);
2203 silc_hash_table_list_reset(&htl);
2206 /* Encode ban list */
2208 if (channel->ban_list && silc_hash_table_count(channel->ban_list)) {
2209 SilcHashTableList htl;
2211 ban_list = silc_buffer_alloc_size(2);
2212 silc_buffer_format(ban_list,
2213 SILC_STR_UI_SHORT(silc_hash_table_count(
2214 channel->ban_list)),
2217 silc_hash_table_list(channel->ban_list, &htl);
2218 while (silc_hash_table_get(&htl, (void *)&tmp_len, (void *)&reply))
2219 ban_list = silc_argument_payload_encode_one(ban_list,
2221 reply->len, tmp_len);
2222 silc_hash_table_list_reset(&htl);
2225 if (channel->channel_pubkeys)
2226 chpklist = silc_server_get_channel_pk_list(server, channel, FALSE, FALSE);
2229 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2230 SILC_STATUS_OK, 0, ident, 16,
2231 2, channel->channel_name,
2232 strlen(channel->channel_name),
2233 3, chidp->data, chidp->len,
2234 4, clidp->data, clidp->len,
2237 7, keyp ? keyp->data : NULL,
2238 keyp ? keyp->len : 0,
2239 8, ban_list ? ban_list->data : NULL,
2240 ban_list ? ban_list->len : 0,
2241 9, invite_list ? invite_list->data :
2243 invite_list ? invite_list->len : 0,
2246 strlen(channel->topic) : 0,
2247 11, silc_hmac_get_name(channel->hmac),
2248 strlen(silc_hmac_get_name(channel->
2251 13, user_list->data, user_list->len,
2252 14, mode_list->data,
2254 15, fkey ? fkey->data : NULL,
2255 fkey ? fkey->len : 0,
2256 16, chpklist ? chpklist->data : NULL,
2257 chpklist ? chpklist->len : 0,
2258 17, (channel->mode &
2259 SILC_CHANNEL_MODE_ULIMIT ?
2262 SILC_CHANNEL_MODE_ULIMIT ?
2263 sizeof(ulimit) : 0));
2265 /* Send command reply */
2266 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
2267 reply->data, reply->len, FALSE);
2269 /* Send JOIN notify to locally connected clients on the channel. If
2270 we are normal server then router will send or have sent JOIN notify
2271 already. However since we've added the client already to our channel
2272 we'll ignore it (in packet_receive.c) so we must send it here. If
2273 we are router then this will send it to local clients and local
2275 SILC_LOG_DEBUG(("Send JOIN notify to channel"));
2276 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
2277 SILC_NOTIFY_TYPE_JOIN, 2,
2278 clidp->data, clidp->len,
2279 chidp->data, chidp->len);
2281 /* Update statistics */
2282 server->stat.my_chanclients++;
2283 if (server->server_type == SILC_ROUTER) {
2284 server->stat.cell_chanclients++;
2285 server->stat.chanclients++;
2288 if (!cmd->pending) {
2289 /* Send JOIN notify packet to our primary router */
2290 silc_server_send_notify_join(server, SILC_PRIMARY_ROUTE(server),
2291 SILC_BROADCAST(server), channel, client->id);
2294 /* Distribute the channel key to all backup routers. */
2295 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
2296 keyp->data, keyp->len, FALSE, TRUE);
2298 /* If client became founder by providing correct founder auth data
2299 notify the mode change to the channel. */
2301 SILC_PUT32_MSB(chl->mode, mode);
2302 SILC_LOG_DEBUG(("Send CUMODE_CHANGE notify to channel"));
2303 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
2304 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
2305 clidp->data, clidp->len,
2306 mode, 4, clidp->data, clidp->len,
2307 fkey ? fkey->data : NULL,
2308 fkey ? fkey->len : 0);
2312 /* Set CUMODE notify type to network */
2314 silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
2315 SILC_BROADCAST(server), channel,
2316 chl->mode, client->id, SILC_ID_CLIENT,
2317 client->id, channel->founder_key);
2319 silc_buffer_free(reply);
2320 silc_buffer_free(clidp);
2321 silc_buffer_free(chidp);
2322 silc_buffer_free(keyp);
2323 silc_buffer_free(user_list);
2324 silc_buffer_free(mode_list);
2325 silc_buffer_free(fkey);
2326 silc_buffer_free(chpklist);
2327 silc_buffer_free(invite_list);
2328 silc_buffer_free(ban_list);
2332 memset(passphrase, 0, strlen(passphrase));
2333 silc_free(passphrase);
2336 /* Server side of command JOIN. Joins client into requested channel. If
2337 the channel does not exist it will be created. */
2339 SILC_SERVER_CMD_FUNC(join)
2341 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2342 SilcServer server = cmd->server;
2343 unsigned char *auth, *cauth;
2344 SilcUInt32 tmp_len, auth_len, cauth_len;
2345 char *tmp, *channel_name = NULL, *cipher, *hmac;
2346 SilcChannelEntry channel;
2347 SilcUInt32 umode = 0;
2348 bool created = FALSE, create_key = TRUE;
2349 SilcClientID *client_id;
2351 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 7);
2353 /* Get channel name */
2354 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2356 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2357 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2362 /* Truncate over long channel names */
2363 if (tmp_len > 256) {
2368 /* Check for valid channel name */
2369 channel_name = silc_identifier_check(tmp, tmp_len, SILC_STRING_UTF8, 256,
2371 if (!channel_name) {
2372 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2373 SILC_STATUS_ERR_BAD_CHANNEL, 0);
2377 /* Get Client ID of the client who is joining to the channel */
2378 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2380 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2381 SILC_STATUS_ERR_NO_CLIENT_ID,
2385 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2387 silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
2388 SILC_STATUS_ERR_BAD_CLIENT_ID, 0,
2393 /* Get cipher, hmac name and auth payload */
2394 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2395 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2396 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
2397 cauth = silc_argument_get_arg_type(cmd->args, 7, &cauth_len);
2399 /* See if the channel exists */
2400 channel = silc_idlist_find_channel_by_name(server->local_list,
2401 channel_name, NULL);
2403 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2404 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2406 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2407 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2412 silc_free(client_id);
2413 client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
2416 (channel->disabled && server->server_type != SILC_ROUTER)) {
2417 /* Channel not found or not valid */
2419 /* If we are standalone server we don't have a router, we just create
2420 the channel by ourselves (unless it existed). */
2421 if (server->standalone) {
2423 channel = silc_server_create_new_channel(server, server->id, cipher,
2424 hmac, channel_name, TRUE);
2426 silc_server_command_send_status_data(
2427 cmd, SILC_COMMAND_JOIN,
2428 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
2429 0, 2, cipher, strlen(cipher));
2430 silc_free(client_id);
2434 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2440 /* The channel does not exist on our server. If we are normal server
2441 we will send JOIN command to our router which will handle the
2442 joining procedure (either creates the channel if it doesn't exist
2443 or joins the client to it). */
2444 if (server->server_type != SILC_ROUTER) {
2446 SilcUInt16 old_ident;
2448 /* If this is pending command callback then we've resolved
2449 it and it didn't work, return since we've notified the
2450 client already in the command reply callback. */
2452 silc_free(client_id);
2456 old_ident = silc_command_get_ident(cmd->payload);
2457 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2458 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2460 /* Send JOIN command to our router */
2461 silc_server_packet_send(server, (SilcSocketConnection)
2462 SILC_PRIMARY_ROUTE(server),
2463 SILC_PACKET_COMMAND, cmd->packet->flags,
2464 tmpbuf->data, tmpbuf->len, TRUE);
2466 /* Reprocess this packet after received reply from router */
2467 silc_server_command_pending(server, SILC_COMMAND_JOIN,
2468 silc_command_get_ident(cmd->payload),
2469 silc_server_command_join,
2470 silc_server_command_dup(cmd));
2471 cmd->pending = TRUE;
2472 silc_command_set_ident(cmd->payload, old_ident);
2473 silc_buffer_free(tmpbuf);
2474 silc_free(client_id);
2478 /* We are router and the channel does not seem exist so we will check
2479 our global list as well for the channel. */
2480 channel = silc_idlist_find_channel_by_name(server->global_list,
2481 channel_name, NULL);
2483 /* Channel really does not exist, create it */
2484 channel = silc_server_create_new_channel(server, server->id, cipher,
2485 hmac, channel_name, TRUE);
2487 silc_server_command_send_status_data(
2488 cmd, SILC_COMMAND_JOIN,
2489 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
2490 2, cipher, strlen(cipher));
2491 silc_free(client_id);
2495 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2503 /* Channel not found */
2505 /* If the command came from router and we are normal server then
2506 something went wrong with the joining as the channel was not found.
2507 We can't do anything else but ignore this. */
2508 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
2509 server->server_type != SILC_ROUTER) {
2510 silc_free(client_id);
2514 /* We are router and the channel does not seem exist so we will check
2515 our global list as well for the channel. */
2516 channel = silc_idlist_find_channel_by_name(server->global_list,
2517 channel_name, NULL);
2519 /* Channel really does not exist, create it */
2520 channel = silc_server_create_new_channel(server, server->id, cipher,
2521 hmac, channel_name, TRUE);
2523 silc_server_command_send_status_data(
2524 cmd, SILC_COMMAND_JOIN,
2525 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
2526 2, cipher, strlen(cipher));
2527 silc_free(client_id);
2531 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2538 /* Check whether the channel was created by our router */
2539 if (cmd->pending && context2) {
2540 SilcServerCommandReplyContext reply = context2;
2542 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
2543 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
2544 SILC_GET32_MSB(created, tmp);
2545 if (silc_argument_get_arg_type(reply->args, 7, NULL))
2546 create_key = FALSE; /* Router returned the key already */
2548 if (silc_command_get_status(reply->payload, NULL, NULL) &&
2549 channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2550 /* Save channel passphrase, if user provided it successfully */
2553 pa = silc_argument_get_arg_type(cmd->args, 3, &pa_len);
2555 silc_free(channel->passphrase);
2556 channel->passphrase = silc_memdup(pa, pa_len);
2561 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
2562 !channel->disabled && !silc_hash_table_count(channel->user_list))
2566 /* If the channel does not have global users and is also empty the client
2567 will be the channel founder and operator. */
2568 if (!channel->disabled &&
2569 !channel->global_users && !silc_hash_table_count(channel->user_list))
2570 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2572 /* Join to the channel */
2573 silc_server_command_join_channel(server, cmd, channel, client_id,
2574 created, create_key, umode,
2575 auth, auth_len, cauth, cauth_len);
2577 silc_free(client_id);
2580 silc_server_command_free(cmd);
2583 /* Server side of command MOTD. Sends server's current "message of the
2584 day" to the client. */
2586 SILC_SERVER_CMD_FUNC(motd)
2588 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2589 SilcServer server = cmd->server;
2590 SilcBuffer packet, idp;
2591 char *motd, *dest_server = NULL;
2592 SilcUInt32 motd_len;
2593 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2595 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
2597 /* Get server name */
2598 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2600 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2601 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2606 /* Check server name */
2607 dest_server = silc_identifier_check(dest_server, strlen(dest_server),
2608 SILC_STRING_UTF8, 256, NULL);
2610 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2611 SILC_STATUS_ERR_BAD_SERVER,
2616 if (!memcmp(dest_server, server->server_name, strlen(dest_server))) {
2619 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
2621 if (server->config && server->config->server_info &&
2622 server->config->server_info->motd_file) {
2624 motd = silc_file_readfile(server->config->server_info->motd_file,
2630 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
2633 2, idp->data, idp->len,
2637 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
2640 2, idp->data, idp->len);
2643 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2644 packet->data, packet->len, FALSE);
2645 silc_buffer_free(packet);
2646 silc_buffer_free(idp);
2648 SilcServerEntry entry;
2650 /* Check whether we have this server cached */
2651 entry = silc_idlist_find_server_by_name(server->global_list,
2652 dest_server, TRUE, NULL);
2654 entry = silc_idlist_find_server_by_name(server->local_list,
2655 dest_server, TRUE, NULL);
2658 if (server->server_type != SILC_SERVER && !cmd->pending &&
2659 entry && !entry->motd) {
2660 /* Send to the server */
2662 SilcUInt16 old_ident;
2664 old_ident = silc_command_get_ident(cmd->payload);
2665 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2666 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2668 silc_server_packet_send(server, entry->connection,
2669 SILC_PACKET_COMMAND, cmd->packet->flags,
2670 tmpbuf->data, tmpbuf->len, TRUE);
2672 /* Reprocess this packet after received reply from router */
2673 silc_server_command_pending(server, SILC_COMMAND_MOTD,
2674 silc_command_get_ident(cmd->payload),
2675 silc_server_command_motd,
2676 silc_server_command_dup(cmd));
2677 cmd->pending = TRUE;
2678 silc_command_set_ident(cmd->payload, old_ident);
2679 silc_buffer_free(tmpbuf);
2683 /* Send to primary router only if we don't know the server
2684 * the client requested or if the server is not locally connected */
2685 if ((!entry || !(entry->data.status & SILC_IDLIST_STATUS_LOCAL))
2686 && !cmd->pending && !server->standalone) {
2687 /* Send to the primary router */
2689 SilcUInt16 old_ident;
2691 old_ident = silc_command_get_ident(cmd->payload);
2692 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2693 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2695 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
2696 SILC_PACKET_COMMAND, cmd->packet->flags,
2697 tmpbuf->data, tmpbuf->len, TRUE);
2699 /* Reprocess this packet after received reply from router */
2700 silc_server_command_pending(server, SILC_COMMAND_MOTD,
2701 silc_command_get_ident(cmd->payload),
2702 silc_server_command_motd,
2703 silc_server_command_dup(cmd));
2704 cmd->pending = TRUE;
2705 silc_command_set_ident(cmd->payload, old_ident);
2706 silc_buffer_free(tmpbuf);
2711 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2712 SILC_STATUS_ERR_NO_SUCH_SERVER, 0,
2714 strlen(dest_server));
2718 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2719 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
2720 SILC_STATUS_OK, 0, ident, 2,
2721 2, idp->data, idp->len,
2724 strlen(entry->motd) : 0);
2725 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2726 packet->data, packet->len, FALSE);
2727 silc_buffer_free(packet);
2728 silc_buffer_free(idp);
2732 silc_free(dest_server);
2733 silc_server_command_free(cmd);
2736 /* Server side of command UMODE. Client can use this command to set/unset
2737 user mode. Client actually cannot set itself to be as server/router
2738 operator so this can be used only to unset the modes. */
2740 SILC_SERVER_CMD_FUNC(umode)
2742 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2743 SilcServer server = cmd->server;
2744 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2746 unsigned char *tmp_mask, m[4];
2747 SilcUInt32 mask = 0;
2748 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2749 bool set_mask = FALSE;
2751 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
2754 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2);
2756 /* Get the client's mode mask */
2757 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2759 SILC_GET32_MSB(mask, tmp_mask);
2764 /* Check that mode changing is allowed. */
2765 if (!silc_server_check_umode_rights(server, client, mask)) {
2766 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2767 SILC_STATUS_ERR_PERM_DENIED, 0);
2771 /* Anonymous mode cannot be set by client */
2772 if (mask & SILC_UMODE_ANONYMOUS &&
2773 !(client->mode & SILC_UMODE_ANONYMOUS)) {
2774 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2775 SILC_STATUS_ERR_PERM_DENIED, 0);
2779 /* Update statistics */
2780 if (mask & SILC_UMODE_GONE) {
2781 if (!(client->mode & SILC_UMODE_GONE))
2782 server->stat.my_aways++;
2784 if (client->mode & SILC_UMODE_GONE)
2785 server->stat.my_aways--;
2788 /* If the client has anonymous mode set, preserve it. */
2789 if (client->mode & SILC_UMODE_ANONYMOUS)
2790 mask |= SILC_UMODE_ANONYMOUS;
2792 /* Change the mode */
2793 client->mode = mask;
2795 /* Send UMODE change to primary router */
2796 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
2797 SILC_BROADCAST(server), client->id,
2800 /* Check if anyone is watching this nickname */
2801 if (server->server_type == SILC_ROUTER)
2802 silc_server_check_watcher_list(server, client, NULL,
2803 SILC_NOTIFY_TYPE_UMODE_CHANGE);
2806 /* Send command reply to sender */
2807 SILC_PUT32_MSB(client->mode, m);
2808 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
2809 SILC_STATUS_OK, 0, ident, 1,
2811 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2812 packet->data, packet->len, FALSE);
2813 silc_buffer_free(packet);
2816 silc_server_command_free(cmd);
2819 /* Server side command of CMODE. Changes channel mode */
2821 SILC_SERVER_CMD_FUNC(cmode)
2823 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2824 SilcServer server = cmd->server;
2825 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2826 SilcIDListData idata = (SilcIDListData)client;
2827 SilcChannelID *channel_id = NULL;
2828 SilcChannelEntry channel;
2829 SilcChannelClientEntry chl;
2830 SilcBuffer packet, cidp;
2831 unsigned char *tmp, *tmp_id, *tmp_mask, *chpkdata = NULL;
2832 char *cipher = NULL, *hmac = NULL, *passphrase = NULL, ulimit[4];
2833 SilcUInt32 mode_mask = 0, old_mask = 0, tmp_len, tmp_len2, chpklen;
2834 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2835 bool set_mask = FALSE, set_chpk = FALSE;
2836 SilcPublicKey founder_key = NULL;
2837 SilcBuffer fkey = NULL, chpklist = NULL;
2838 SilcBufferStruct chpk;
2841 silc_server_command_free(cmd);
2845 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 9);
2847 /* Get Channel ID */
2848 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2850 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2851 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2852 silc_server_command_free(cmd);
2855 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
2857 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2858 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2859 silc_server_command_free(cmd);
2863 /* Get channel entry */
2864 channel = silc_idlist_find_channel_by_id(server->local_list,
2867 channel = silc_idlist_find_channel_by_id(server->global_list,
2870 silc_server_command_send_status_data(cmd, SILC_COMMAND_CMODE,
2871 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
2872 0, 2, tmp_id, tmp_len2);
2873 silc_free(channel_id);
2874 silc_server_command_free(cmd);
2878 old_mask = channel->mode;
2880 /* Get the channel mode mask */
2881 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2883 SILC_GET32_MSB(mode_mask, tmp_mask);
2887 /* Check whether this client is on the channel */
2888 if (!silc_server_client_on_channel(client, channel, &chl)) {
2889 silc_server_command_send_status_data(cmd, SILC_COMMAND_CMODE,
2890 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
2891 2, tmp_id, tmp_len2);
2895 /* Check that client has rights to change any requested channel modes */
2896 if (set_mask && !silc_server_check_cmode_rights(server, channel, chl,
2898 SILC_LOG_DEBUG(("Client does not have rights to change mode"));
2899 silc_server_command_send_status_data(
2900 cmd, SILC_COMMAND_CMODE,
2901 (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) ?
2902 SILC_STATUS_ERR_NO_CHANNEL_PRIV :
2903 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV), 0,
2904 2, tmp_id, tmp_len2);
2908 /* If mode mask was not sent as argument then merely return the current
2909 mode mask, founder key and channel public key list to the sender. */
2912 SILC_PUT32_MSB(channel->mode, m);
2913 if (channel->founder_key)
2914 fkey = silc_pkcs_public_key_payload_encode(channel->founder_key);
2915 if (channel->channel_pubkeys)
2916 chpklist = silc_server_get_channel_pk_list(server, channel,
2919 silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2920 SILC_STATUS_OK, 0, ident, 4,
2921 2, tmp_id, tmp_len2,
2923 4, fkey ? fkey->data : NULL,
2924 fkey ? fkey->len : 0,
2925 5, chpklist ? chpklist->data : NULL,
2926 chpklist ? chpklist->len : 0);
2927 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2928 packet->data, packet->len, FALSE);
2929 silc_buffer_free(packet);
2934 * Check the modes. Modes that requires nothing special operation are
2938 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2939 /* Channel uses private keys to protect traffic. Client(s) has set the
2940 key locally they want to use, server does not know that key. */
2941 /* Nothing interesting to do here */
2943 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2944 /* The mode is removed and we need to generate and distribute
2945 new channel key. Clients are not using private channel keys
2946 anymore after this. */
2948 /* Re-generate channel key */
2949 if (!silc_server_create_channel_key(server, channel, 0))
2952 /* Send the channel key. This sends it to our local clients and if
2953 we are normal server to our router as well. */
2954 silc_server_send_channel_key(server, NULL, channel,
2955 server->server_type == SILC_ROUTER ?
2956 FALSE : !server->standalone);
2958 cipher = (char *)silc_cipher_get_name(channel->channel_key);
2959 hmac = (char *)silc_hmac_get_name(channel->hmac);
2963 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2964 /* User limit is set on channel */
2965 SilcUInt32 user_limit;
2967 /* Get user limit */
2968 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2970 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2971 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2972 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
2976 SILC_GET32_MSB(user_limit, tmp);
2977 channel->user_limit = user_limit;
2980 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2981 /* User limit mode is unset. Remove user limit */
2982 channel->user_limit = 0;
2985 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
2986 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
2987 /* Passphrase has been set to channel */
2989 /* Get the passphrase */
2990 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
2992 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2993 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
2997 /* Save the passphrase */
2998 passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
3001 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3002 /* Passphrase mode is unset. remove the passphrase */
3003 silc_free(channel->passphrase);
3004 channel->passphrase = NULL;
3008 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3009 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3010 /* Cipher to use protect the traffic */
3011 SilcCipher newkey, oldkey;
3014 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3016 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3017 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3021 /* Delete old cipher and allocate the new one */
3022 if (!silc_cipher_alloc(cipher, &newkey)) {
3023 silc_server_command_send_status_data(
3024 cmd, SILC_COMMAND_CMODE,
3025 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
3026 2, cipher, strlen(cipher));
3030 oldkey = channel->channel_key;
3031 channel->channel_key = newkey;
3033 /* Re-generate channel key */
3034 if (!silc_server_create_channel_key(server, channel, 0)) {
3035 /* We don't have new key, revert to old one */
3036 channel->channel_key = oldkey;
3040 /* Remove old channel key for good */
3041 silc_cipher_free(oldkey);
3043 /* Send the channel key. This sends it to our local clients and if
3044 we are normal server to our router as well. */
3045 silc_server_send_channel_key(server, NULL, channel,
3046 server->server_type == SILC_ROUTER ?
3047 FALSE : !server->standalone);
3050 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3051 /* Cipher mode is unset. Remove the cipher and revert back to
3053 SilcCipher newkey, oldkey;
3054 cipher = channel->cipher;
3056 /* Delete old cipher and allocate default one */
3057 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
3058 silc_server_command_send_status_data(
3059 cmd, SILC_COMMAND_CMODE,
3060 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
3061 2, cipher, strlen(cipher));
3065 oldkey = channel->channel_key;
3066 channel->channel_key = newkey;
3068 /* Re-generate channel key */
3069 if (!silc_server_create_channel_key(server, channel, 0)) {
3070 /* We don't have new key, revert to old one */
3071 channel->channel_key = oldkey;
3075 /* Remove old channel key for good */
3076 silc_cipher_free(oldkey);
3078 /* Send the channel key. This sends it to our local clients and if
3079 we are normal server to our router as well. */
3080 silc_server_send_channel_key(server, NULL, channel,
3081 server->server_type == SILC_ROUTER ?
3082 FALSE : !server->standalone);
3086 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3087 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3088 /* HMAC to use protect the traffic */
3089 unsigned char hash[32];
3093 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3095 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3096 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3100 /* Delete old hmac and allocate the new one */
3101 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
3102 silc_server_command_send_status_data(
3103 cmd, SILC_COMMAND_CMODE,
3104 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
3105 2, hmac, strlen(hmac));
3109 silc_hmac_free(channel->hmac);
3110 channel->hmac = newhmac;
3112 /* Set the HMAC key out of current channel key. The client must do
3114 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
3115 channel->key_len / 8, hash);
3116 silc_hmac_set_key(channel->hmac, hash,
3117 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3118 memset(hash, 0, sizeof(hash));
3121 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
3122 /* Hmac mode is unset. Remove the hmac and revert back to
3125 unsigned char hash[32];
3126 hmac = channel->hmac_name;
3128 /* Delete old hmac and allocate default one */
3129 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
3130 silc_server_command_send_status_data(
3131 cmd, SILC_COMMAND_CMODE,
3132 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
3133 2, hmac, strlen(hmac));
3137 silc_hmac_free(channel->hmac);
3138 channel->hmac = newhmac;
3140 /* Set the HMAC key out of current channel key. The client must do
3142 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
3143 channel->key_len / 8,
3145 silc_hmac_set_key(channel->hmac, hash,
3146 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3147 memset(hash, 0, sizeof(hash));
3151 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3152 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3153 /* Check if the founder public key was received */
3154 founder_key = idata->public_key;
3155 tmp = silc_argument_get_arg_type(cmd->args, 8, &tmp_len);
3157 if (!silc_pkcs_public_key_payload_decode(tmp, tmp_len, &founder_key)) {
3158 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3159 SILC_STATUS_ERR_AUTH_FAILED,
3164 /* If key was not sent and the channel mode has already founder
3165 then the key was not to be changed. */
3166 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)
3170 /* Set the founder authentication */
3171 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
3173 silc_server_command_send_status_reply(
3174 cmd, SILC_COMMAND_CMODE,
3175 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3179 /* Verify the payload before setting the mode */
3180 if (!silc_auth_verify_data(tmp, tmp_len, SILC_AUTH_PUBLIC_KEY,
3181 founder_key, 0, server->sha1hash,
3182 client->id, SILC_ID_CLIENT)) {
3183 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3184 SILC_STATUS_ERR_AUTH_FAILED,
3189 /* Save the public key */
3190 if (channel->founder_key)
3191 silc_pkcs_public_key_free(channel->founder_key);
3192 if (silc_argument_get_arg_type(cmd->args, 8, NULL))
3193 channel->founder_key = founder_key;
3195 channel->founder_key = silc_pkcs_public_key_copy(founder_key);
3196 if (!channel->founder_key) {
3197 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3198 SILC_STATUS_ERR_AUTH_FAILED,
3203 fkey = silc_pkcs_public_key_payload_encode(channel->founder_key);
3205 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3206 SILC_STATUS_ERR_AUTH_FAILED,
3208 silc_pkcs_public_key_free(channel->founder_key);
3209 channel->founder_key = NULL;
3214 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3215 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3216 if (channel->founder_key)
3217 silc_pkcs_public_key_free(channel->founder_key);
3218 channel->founder_key = NULL;
3224 if (mode_mask & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
3225 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3228 chpkdata = silc_argument_get_arg_type(cmd->args, 9, &chpklen);
3230 if (!chpkdata && channel->mode & SILC_CHANNEL_MODE_CHANNEL_AUTH)
3235 /* Process the channel public key(s) */
3236 st = silc_server_set_channel_pk_list(server, NULL, channel,
3238 if (st != SILC_STATUS_OK) {
3239 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE, st, 0);
3244 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3245 if (channel->mode & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
3246 if (channel->channel_pubkeys)
3247 silc_hash_table_free(channel->channel_pubkeys);
3248 channel->channel_pubkeys = NULL;
3255 /* Finally, set the mode */
3256 old_mask = channel->mode = mode_mask;
3258 /* Send CMODE_CHANGE notify. */
3259 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3260 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT)
3261 SILC_PUT32_MSB(channel->user_limit, ulimit);
3262 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
3263 SILC_NOTIFY_TYPE_CMODE_CHANGE, 8,
3264 cidp->data, cidp->len,
3266 cipher, cipher ? strlen(cipher) : 0,
3267 hmac, hmac ? strlen(hmac) : 0,
3268 passphrase, passphrase ?
3269 strlen(passphrase) : 0,
3270 fkey ? fkey->data : NULL,
3271 fkey ? fkey->len : 0,
3272 chpkdata ? chpkdata : NULL,
3273 chpkdata ? chpklen : 0,
3274 mode_mask & SILC_CHANNEL_MODE_ULIMIT ?
3276 mode_mask & SILC_CHANNEL_MODE_ULIMIT ?
3277 sizeof(ulimit) : 0);
3279 /* Set CMODE notify type to network */
3280 if (chpkdata && chpklen)
3281 silc_buffer_set(&chpk, chpkdata, chpklen);
3282 silc_server_send_notify_cmode(server, SILC_PRIMARY_ROUTE(server),
3283 SILC_BROADCAST(server), channel,
3284 mode_mask, client->id, SILC_ID_CLIENT,
3285 cipher, hmac, passphrase, founder_key,
3286 chpkdata ? &chpk : NULL);
3289 chpklist = silc_server_get_channel_pk_list(server, channel, FALSE, FALSE);
3291 /* Send command reply to sender */
3292 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3293 SILC_STATUS_OK, 0, ident, 5,
3294 2, tmp_id, tmp_len2,
3296 4, fkey ? fkey->data : NULL,
3297 fkey ? fkey->len : 0,
3298 5, chpklist ? chpklist->data :
3299 NULL, chpklist ? chpklist->len
3302 SILC_CHANNEL_MODE_ULIMIT ?
3305 SILC_CHANNEL_MODE_ULIMIT ?
3306 sizeof(ulimit) : 0));
3308 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3309 packet->data, packet->len, FALSE);
3311 silc_buffer_free(packet);
3312 silc_buffer_free(cidp);
3315 channel->mode = old_mask;
3316 silc_buffer_free(chpklist);
3317 silc_buffer_free(fkey);
3318 silc_free(channel_id);
3319 silc_server_command_free(cmd);
3322 /* Server side of CUMODE command. Changes client's mode on a channel. */
3324 SILC_SERVER_CMD_FUNC(cumode)
3326 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3327 SilcServer server = cmd->server;
3328 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3329 SilcChannelID *channel_id = NULL;
3330 SilcClientID *client_id = NULL;
3331 SilcChannelEntry channel;
3332 SilcClientEntry target_client;
3333 SilcChannelClientEntry chl;
3334 SilcBuffer packet, idp;
3335 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
3336 SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
3338 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3339 SilcPublicKey founder_key = NULL;
3340 SilcBuffer fkey = NULL;
3345 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
3347 /* Get Channel ID */
3348 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3350 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3351 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3354 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
3356 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3357 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3361 /* Get channel entry */
3362 channel = silc_idlist_find_channel_by_id(server->local_list,
3365 channel = silc_idlist_find_channel_by_id(server->global_list,
3368 silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3369 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
3370 0, 2, tmp_ch_id, tmp_ch_len);
3375 /* Check whether sender is on the channel */
3376 if (!silc_server_client_on_channel(client, channel, &chl)) {
3377 silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3378 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
3379 2, tmp_ch_id, tmp_ch_len);
3382 sender_mask = chl->mode;
3384 /* Get the target client's channel mode mask */
3385 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3387 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3388 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3392 SILC_GET32_MSB(target_mask, tmp_mask);
3394 /* Get target Client ID */
3395 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3397 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3398 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
3401 client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
3403 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3404 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
3408 /* Get target client's entry */
3409 target_client = silc_idlist_find_client_by_id(server->local_list,
3410 client_id, TRUE, NULL);
3412 target_client = silc_idlist_find_client_by_id(server->global_list,
3413 client_id, TRUE, NULL);
3415 if (target_client != client &&
3416 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
3417 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
3418 silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3419 SILC_STATUS_ERR_NOT_YOU, 0,
3420 2, tmp_ch_id, tmp_ch_len);
3424 /* Check whether target client is on the channel */
3425 if (target_client != client) {
3426 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
3427 silc_server_command_send_status_data2(
3428 cmd, SILC_COMMAND_CUMODE,
3429 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL, 0,
3431 3, tmp_ch_id, tmp_ch_len);
3440 /* If the target client is founder, no one else can change their mode
3442 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
3443 silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3444 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
3445 0, 2, tmp_ch_id, tmp_ch_len);
3449 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
3450 if (target_client != client) {
3451 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3452 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
3457 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
3458 /* The client tries to claim the founder rights. */
3459 unsigned char *tmp_auth;
3460 SilcUInt32 tmp_auth_len;
3461 SilcChannelClientEntry chl2;
3462 SilcHashTableList htl;
3464 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
3465 !channel->founder_key) {
3466 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3467 SILC_STATUS_ERR_AUTH_FAILED, 0);
3471 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
3473 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3474 SILC_STATUS_ERR_AUTH_FAILED, 0);
3478 /* Verify the authentication payload */
3479 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len, SILC_AUTH_PUBLIC_KEY,
3480 channel->founder_key, 0, server->sha1hash,
3481 client->id, SILC_ID_CLIENT)) {
3482 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3483 SILC_STATUS_ERR_AUTH_FAILED, 0);
3488 founder_key = channel->founder_key;
3489 fkey = silc_pkcs_public_key_payload_encode(founder_key);
3491 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3492 SILC_STATUS_ERR_AUTH_FAILED, 0);
3496 /* There cannot be anyone else as founder on the channel now. This
3497 client is definitely the founder due to this authentication. This
3498 is done only on router, not on server, since server cannot know
3499 whether router will accept this mode change or not. XXX This
3500 probably shouldn't be done anymore at all, may cause problems in
3501 router-router connections too (maybe just AUTH_FAILED error should
3502 be returned). -Pekka */
3503 if (server->server_type == SILC_ROUTER) {
3504 silc_hash_table_list(channel->user_list, &htl);
3505 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
3506 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
3507 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3508 silc_server_force_cumode_change(server, NULL, channel, chl2,
3512 silc_hash_table_list_reset(&htl);
3515 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
3518 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3519 if (target_client == client) {
3520 /* Remove channel founder rights from itself */
3521 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3524 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3525 SILC_STATUS_ERR_NOT_YOU, 0);
3531 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
3532 /* Promote to operator */
3533 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3534 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3535 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3536 silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3537 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
3538 0, 2, tmp_ch_id, tmp_ch_len);
3542 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
3546 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
3547 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3548 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3549 silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3550 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
3551 0, 2, tmp_ch_id, tmp_ch_len);
3555 /* Demote to normal user */
3556 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
3561 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
3562 if (target_client != client) {
3563 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3564 SILC_STATUS_ERR_NOT_YOU, 0);
3568 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
3569 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
3573 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
3574 if (target_client != client) {
3575 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3576 SILC_STATUS_ERR_NOT_YOU, 0);
3580 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
3585 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
3586 if (target_client != client) {
3587 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3588 SILC_STATUS_ERR_NOT_YOU, 0);
3592 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)) {
3593 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
3597 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
3598 if (target_client != client) {
3599 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3600 SILC_STATUS_ERR_NOT_YOU, 0);
3604 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
3609 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
3610 if (target_client != client) {
3611 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3612 SILC_STATUS_ERR_NOT_YOU, 0);
3616 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)) {
3617 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
3621 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
3622 if (target_client != client) {
3623 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3624 SILC_STATUS_ERR_NOT_YOU, 0);
3628 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
3633 if (target_mask & SILC_CHANNEL_UMODE_QUIET) {
3634 if (!(chl->mode & SILC_CHANNEL_UMODE_QUIET)) {
3635 if (client == target_client) {
3636 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3637 SILC_STATUS_ERR_PERM_DENIED, 0);
3640 chl->mode |= SILC_CHANNEL_UMODE_QUIET;
3644 if (chl->mode & SILC_CHANNEL_UMODE_QUIET) {
3645 if (client == target_client) {
3646 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3647 SILC_STATUS_ERR_PERM_DENIED, 0);
3650 chl->mode &= ~SILC_CHANNEL_UMODE_QUIET;
3655 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3656 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3658 /* Send notify to channel, notify only if mode was actually changed. */
3660 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
3661 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
3662 idp->data, idp->len,
3665 fkey ? fkey->data : NULL,
3666 fkey ? fkey->len : 0);
3668 /* Set CUMODE notify type to network */
3669 silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
3670 SILC_BROADCAST(server), channel,
3671 target_mask, client->id, SILC_ID_CLIENT,
3672 target_client->id, founder_key);
3675 /* Send command reply to sender */
3676 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
3677 SILC_STATUS_OK, 0, ident, 3,
3679 3, tmp_ch_id, tmp_ch_len,
3680 4, tmp_id, tmp_len);
3681 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3682 packet->data, packet->len, FALSE);
3684 silc_buffer_free(packet);
3685 silc_buffer_free(idp);
3688 silc_free(channel_id);
3689 silc_free(client_id);
3690 silc_buffer_free(fkey);
3691 silc_server_command_free(cmd);
3694 /* Server side of KICK command. Kicks client out of channel. */
3696 SILC_SERVER_CMD_FUNC(kick)
3698 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3699 SilcServer server = cmd->server;
3700 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3701 SilcClientEntry target_client;
3702 SilcChannelID *channel_id;
3703 SilcClientID *client_id;
3704 SilcChannelEntry channel;
3705 SilcChannelClientEntry chl;
3706 SilcBuffer idp, packet;
3707 SilcUInt32 tmp_len, target_idp_len, clen;
3708 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3709 unsigned char *tmp, *comment, *target_idp;
3714 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
3716 /* Get Channel ID */
3717 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3719 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3720 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3723 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3725 silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3726 SILC_STATUS_ERR_BAD_CHANNEL_ID, 0,
3731 /* Get channel entry */
3732 channel = silc_idlist_find_channel_by_id(server->local_list,
3735 channel = silc_idlist_find_channel_by_id(server->local_list,
3738 silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3739 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
3740 0, 2, tmp, tmp_len);
3745 /* Check whether sender is on the channel */
3746 if (!silc_server_client_on_channel(client, channel, &chl)) {
3747 silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3748 SILC_STATUS_ERR_NOT_ON_CHANNEL,
3749 0, 2, tmp, tmp_len);
3753 /* Check that the kicker is channel operator or channel founder */
3754 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
3755 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
3756 silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3757 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
3758 0, 2, tmp, tmp_len);
3762 /* Get target Client ID */
3763 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
3765 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3766 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
3769 client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
3771 silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3772 SILC_STATUS_ERR_BAD_CLIENT_ID,
3773 0, 2, target_idp, target_idp_len);
3777 /* Get target client's entry */
3778 target_client = silc_idlist_find_client_by_id(server->local_list,
3779 client_id, TRUE, NULL);
3780 if (!target_client) {
3781 target_client = silc_idlist_find_client_by_id(server->global_list,
3782 client_id, TRUE, NULL);
3785 /* Check whether target client is on the channel */
3786 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
3787 silc_server_command_send_status_data2(cmd, SILC_COMMAND_KICK,
3788 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL,
3789 0, 2, target_idp, target_idp_len,
3794 /* Check that the target client is not channel founder. Channel founder
3795 cannot be kicked from the channel. */
3796 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3797 silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3798 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
3799 0, 2, tmp, tmp_len);
3804 comment = silc_argument_get_arg_type(cmd->args, 3, &clen);
3809 /* Send the reply back to the client */
3811 silc_command_reply_payload_encode_va(SILC_COMMAND_KICK,
3812 SILC_STATUS_OK, 0, ident, 2,
3814 3, target_idp, target_idp_len);
3815 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3816 packet->data, packet->len, FALSE);
3817 silc_buffer_free(packet);
3819 /* Send KICKED notify to local clients on the channel */
3820 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3821 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
3822 SILC_NOTIFY_TYPE_KICKED, 3,
3823 target_idp, target_idp_len,
3824 comment, comment ? strlen(comment) : 0,
3825 idp->data, idp->len);
3826 silc_buffer_free(idp);
3828 /* Send KICKED notify to primary route */
3829 silc_server_send_notify_kicked(server, SILC_PRIMARY_ROUTE(server),
3830 SILC_BROADCAST(server), channel,
3831 target_client->id, client->id, comment);
3833 /* Remove the client from channel's invite list */
3834 if (channel->invite_list && silc_hash_table_count(channel->invite_list)) {
3836 silc_argument_payload_encode_one(NULL, target_idp, target_idp_len, 3);
3837 SilcArgumentPayload args =
3838 silc_argument_payload_parse(ab->data, ab->len, 1);
3839 silc_server_inviteban_process(server, channel->invite_list, 1, args);
3840 silc_buffer_free(ab);
3841 silc_argument_payload_free(args);
3844 /* Remove the client from the channel. If the channel does not exist
3845 after removing the client then the client kicked itself off the channel
3846 and we don't have to send anything after that. */
3847 if (!silc_server_remove_from_one_channel(server, NULL, channel,
3848 target_client, FALSE))
3851 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3852 /* Re-generate channel key */
3853 if (!silc_server_create_channel_key(server, channel, 0))
3856 /* Send the channel key to the channel. The key of course is not sent
3857 to the client who was kicked off the channel. */
3858 silc_server_send_channel_key(server, target_client->connection, channel,
3859 server->server_type == SILC_ROUTER ?
3860 FALSE : !server->standalone);
3864 silc_server_command_free(cmd);
3867 /* Server side of OPER command. Client uses this comand to obtain server
3868 operator privileges to this server/router. */
3870 SILC_SERVER_CMD_FUNC(oper)
3872 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3873 SilcServer server = cmd->server;
3874 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3875 unsigned char *username = NULL, *auth;
3877 SilcServerConfigAdmin *admin;
3878 SilcIDListData idata = (SilcIDListData)client;
3879 bool result = FALSE;
3880 SilcPublicKey cached_key;
3882 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
3885 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
3887 /* Get the username */
3888 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3890 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3891 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3896 /* Check username */
3897 username = silc_identifier_check(username, strlen(username),
3898 SILC_STRING_UTF8, 128, &tmp_len);
3900 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3901 SILC_STATUS_ERR_BAD_USERNAME,
3906 /* Get the admin configuration */
3907 admin = silc_server_config_find_admin(server, cmd->sock->ip,
3908 username, client->nickname);
3910 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
3911 username, client->nickname);
3913 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3914 SILC_STATUS_ERR_AUTH_FAILED,
3916 SILC_LOG_INFO(("OPER authentication failed for username '%s' by "
3917 "nickname '%s' from %s", username,
3918 client->nickname, cmd->sock->hostname));
3923 /* Get the authentication payload */
3924 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3926 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3927 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3932 /* Verify the authentication data. If both passphrase and public key
3933 is set then try both of them. */
3934 if (admin->passphrase)
3935 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
3936 admin->passphrase, admin->passphrase_len,
3937 idata->hash, client->id, SILC_ID_CLIENT);
3938 if (!result && admin->publickeys) {
3939 cached_key = silc_server_get_public_key(server, admin->publickeys);
3942 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
3943 cached_key, 0, idata->hash,
3944 client->id, SILC_ID_CLIENT);
3947 /* Authentication failed */
3948 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3949 SILC_STATUS_ERR_AUTH_FAILED,
3954 /* Client is now server operator */
3955 client->mode |= SILC_UMODE_SERVER_OPERATOR;
3957 /* Update statistics */
3958 if (SILC_IS_LOCAL(client))
3959 server->stat.my_server_ops++;
3960 if (server->server_type == SILC_ROUTER)
3961 server->stat.server_ops++;
3963 /* Send UMODE change to primary router */
3964 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
3965 SILC_BROADCAST(server), client->id,
3968 /* Check if anyone is watching this nickname */
3969 if (server->server_type == SILC_ROUTER)
3970 silc_server_check_watcher_list(server, client, NULL,
3971 SILC_NOTIFY_TYPE_UMODE_CHANGE);
3973 /* Send reply to the sender */
3974 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3978 silc_free(username);
3979 silc_server_command_free(cmd);
3982 SILC_TASK_CALLBACK(silc_server_command_detach_cb)
3984 SilcServer server = app_context;
3985 QuitInternal q = (QuitInternal)context;
3986 SilcClientID *client_id = (SilcClientID *)q->sock;
3987 SilcClientEntry client;
3988 SilcSocketConnection sock;
3990 client = silc_idlist_find_client_by_id(server->local_list, client_id,
3992 if (client && client->connection) {
3993 sock = client->connection;
3995 /* If there is pending outgoing data for the client then purge it
3996 to the network before closing connection. */
3997 silc_server_packet_queue_purge(server, sock);
3999 /* Close the connection on our side */
4000 client->router = NULL;
4001 client->connection = NULL;
4002 sock->user_data = NULL;
4003 silc_server_close_connection(server, sock);
4006 silc_free(client_id);
4010 SILC_TASK_CALLBACK(silc_server_command_detach_timeout)
4012 SilcServer server = app_context;
4013 QuitInternal q = (QuitInternal)context;
4014 SilcClientID *client_id = (SilcClientID *)q->sock;
4015 SilcClientEntry client;
4017 client = silc_idlist_find_client_by_id(server->local_list, client_id,
4019 if (client && client->mode & SILC_UMODE_DETACHED) {
4020 SILC_LOG_DEBUG(("Detach timeout"));
4021 silc_server_free_client_data(server, NULL, client, TRUE,
4025 silc_free(client_id);
4029 /* Server side of DETACH command. Detached the client from the network
4030 by closing the connection but preserving the session. */
4032 SILC_SERVER_CMD_FUNC(detach)
4034 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4035 SilcServer server = cmd->server;
4036 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4039 if (server->config->detach_disabled) {
4040 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
4041 SILC_STATUS_ERR_OPERATION_ALLOWED,
4046 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
4049 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
4051 /* Remove operator privileges, since the client may resume in some
4052 other server which to it does not have operator privileges. */
4053 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
4054 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
4056 /* Send the user mode notify to notify that client is detached */
4057 client->mode |= SILC_UMODE_DETACHED;
4058 client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
4059 client->data.status &= ~SILC_IDLIST_STATUS_NOATTR;
4060 client->last_command = 0;
4061 client->fast_command = 0;
4062 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
4063 SILC_BROADCAST(server), client->id,
4065 server->stat.my_detached++;
4067 /* Check if anyone is watching this nickname */
4068 if (server->server_type == SILC_ROUTER)
4069 silc_server_check_watcher_list(server, client, NULL,
4070 SILC_NOTIFY_TYPE_UMODE_CHANGE);
4072 q = silc_calloc(1, sizeof(*q));
4073 q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
4074 silc_schedule_task_add(server->schedule, 0, silc_server_command_detach_cb,
4075 q, 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
4077 if (server->config->detach_timeout) {
4078 q = silc_calloc(1, sizeof(*q));
4079 q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
4080 silc_schedule_task_add(server->schedule, 0,
4081 silc_server_command_detach_timeout,
4082 q, server->config->detach_timeout * 60,
4083 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
4086 /* Send reply to the sender */
4087 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
4091 silc_server_command_free(cmd);
4094 /* Server side of WATCH command. */
4096 SILC_SERVER_CMD_FUNC(watch)
4098 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4099 SilcServer server = cmd->server;
4100 char *add_nick, *del_nick;
4101 SilcUInt32 add_nick_len, del_nick_len, tmp_len, pk_len;
4102 unsigned char hash[16], *tmp, *pk, *nick;
4103 SilcClientEntry client;
4104 SilcClientID *client_id = NULL;
4106 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WATCH, cmd, 1, 3);
4108 if (server->server_type != SILC_ROUTER && !server->standalone) {
4109 if (!cmd->pending) {
4110 /* Send the command to router */
4112 SilcUInt16 old_ident;
4114 SILC_LOG_DEBUG(("Forwarding WATCH to router"));
4116 old_ident = silc_command_get_ident(cmd->payload);
4117 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4118 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4120 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
4121 SILC_PACKET_COMMAND, cmd->packet->flags,
4122 tmpbuf->data, tmpbuf->len, TRUE);
4124 /* Reprocess this packet after received reply from router */
4125 silc_server_command_pending(server, SILC_COMMAND_WATCH,
4126 silc_command_get_ident(cmd->payload),
4127 silc_server_command_watch,
4128 silc_server_command_dup(cmd));
4129 cmd->pending = TRUE;
4130 silc_command_set_ident(cmd->payload, old_ident);
4131 silc_buffer_free(tmpbuf);
4132 } else if (context2) {
4133 /* Received reply from router, just send same data to the client. */
4134 SilcServerCommandReplyContext reply = context2;
4137 SILC_LOG_DEBUG(("Received reply to WATCH from router"));
4138 silc_command_get_status(reply->payload, &status, NULL);
4139 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, status,
4146 /* We are router and keep the watch list for local cell */
4148 /* Get the client ID */
4149 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4151 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4152 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4156 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4158 silc_server_command_send_status_data(cmd, SILC_COMMAND_WATCH,
4159 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
4160 0, 2, tmp, tmp_len);
4164 /* Get the client entry which must be in local list */
4165 client = silc_idlist_find_client_by_id(server->local_list,
4166 client_id, TRUE, NULL);
4168 silc_server_command_send_status_data(cmd, SILC_COMMAND_WATCH,
4169 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0,
4174 /* Take public key for watching by public key */
4175 pk = silc_argument_get_arg_type(cmd->args, 4, &pk_len);
4178 add_nick = silc_argument_get_arg_type(cmd->args, 2, &add_nick_len);
4179 del_nick = silc_argument_get_arg_type(cmd->args, 3, &del_nick_len);
4180 if (!add_nick && !del_nick && !pk) {
4181 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4182 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4187 if (add_nick && add_nick_len > 128) {
4188 add_nick[128] = '\0';
4191 if (del_nick && del_nick_len > 128) {
4192 del_nick[128] = '\0';
4196 /* Add new nickname to be watched in our cell */
4198 nick = silc_identifier_check(add_nick, add_nick_len, SILC_STRING_UTF8, 128,
4201 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4202 SILC_STATUS_ERR_BAD_NICKNAME, 0);
4206 /* Hash the nick, we have the hash saved, not nicks because we can
4207 do one to one mapping to the nick from Client ID hash this way. */
4208 silc_hash_make(server->md5hash, nick, add_nick_len, hash);
4210 /* Check whether this client is already watching this nickname */
4211 if (silc_hash_table_find_by_context(server->watcher_list, hash,
4213 /* Nickname is alredy being watched for this client */
4214 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4215 SILC_STATUS_ERR_NICKNAME_IN_USE,
4221 /* Get the nickname from the watcher list and use the same key in
4222 new entries as well. If key doesn't exist then create it. */
4223 if (!silc_hash_table_find(server->watcher_list, hash, (void *)&tmp, NULL))
4224 tmp = silc_memdup(hash, CLIENTID_HASH_LEN);
4226 /* Add the client to the watcher list with the specified nickname hash. */
4227 silc_hash_table_add(server->watcher_list, tmp, client);
4231 /* Delete nickname from watch list */
4233 nick = silc_identifier_check(del_nick, del_nick_len, SILC_STRING_UTF8, 128,
4236 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4237 SILC_STATUS_ERR_BAD_NICKNAME, 0);
4241 /* Hash the nick, we have the hash saved, not nicks because we can
4242 do one to one mapping to the nick from Client ID hash this way. */
4243 silc_hash_make(server->md5hash, nick, del_nick_len, hash);
4245 /* Check that this client is watching for this nickname */
4246 if (!silc_hash_table_find_by_context(server->watcher_list, hash,
4247 client, (void *)&tmp)) {
4248 /* Nickname is alredy being watched for this client */
4249 silc_server_command_send_status_data(cmd, SILC_COMMAND_WATCH,
4250 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
4251 2, nick, del_nick_len);
4256 /* Delete the nickname from the watcher list. */
4257 silc_hash_table_del_by_context(server->watcher_list, hash, client);
4259 /* Now check whether there still exists entries with this key, if not
4260 then free the key to not leak memory. */
4261 if (!silc_hash_table_find(server->watcher_list, hash, NULL, NULL))
4266 /* Add/del public key */
4269 SilcArgumentPayload pkargs;
4271 SilcPublicKey public_key, pkkey;
4274 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4275 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4280 /* Get the argument from the Argument List Payload */
4281 SILC_GET16_MSB(pkargc, pk);
4282 pkargs = silc_argument_payload_parse(pk + 2, pk_len - 2, pkargc);
4284 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4285 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4290 pk = silc_argument_get_next_arg(pkargs, &type, &pk_len);
4292 if (!silc_pkcs_public_key_payload_decode(pk, pk_len, &public_key))
4298 /* Add public key to watch list */
4300 /* Check whether this client is already watching this public key */
4301 if (silc_hash_table_find_by_context(server->watcher_list_pk,
4302 public_key, client, NULL)) {
4303 silc_pkcs_public_key_free(public_key);
4304 silc_server_command_send_status_reply(
4305 cmd, SILC_COMMAND_WATCH,
4306 SILC_STATUS_ERR_NICKNAME_IN_USE, 0);
4310 /* Get the public key from the watcher list and use the same key in
4311 new entries as well. If key doesn't exist then create it. */
4313 if (!silc_hash_table_find(server->watcher_list_pk, public_key,
4314 (void *)&pkkey, NULL))
4317 silc_pkcs_public_key_free(public_key);
4319 /* Add the client to the watcher list with the specified public
4321 silc_hash_table_add(server->watcher_list_pk, pkkey, client);
4323 } else if (type == 0x01) {
4324 /* Delete public key from watch list */
4326 /* Check that this client is watching this public key */
4327 if (silc_hash_table_find_by_context(server->watcher_list_pk,
4330 silc_pkcs_public_key_free(public_key);
4331 silc_server_command_send_status_reply(
4332 cmd, SILC_COMMAND_WATCH,
4333 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4337 /* Delete the public key from the watcher list. */
4338 silc_hash_table_del_by_context(server->watcher_list_pk,
4339 public_key, client);
4341 /* Now check whether there still exists entries with this key, if
4342 not then free the key to not leak memory. */
4343 if (!silc_hash_table_find(server->watcher_list_pk, hash, NULL, NULL))
4344 silc_pkcs_public_key_free(pkkey);
4345 silc_pkcs_public_key_free(public_key);
4348 pk = silc_argument_get_next_arg(pkargs, &type, &pk_len);
4352 /* Distribute the watch list to backup routers too */
4353 if (server->backup) {
4355 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4356 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4357 silc_server_backup_send(server, NULL, SILC_PACKET_COMMAND,
4358 cmd->packet->flags, tmpbuf->data, tmpbuf->len,
4360 silc_buffer_free(tmpbuf);
4363 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4367 silc_free(client_id);
4368 silc_server_command_free(cmd);
4371 /* Server side of SILCOPER command. Client uses this comand to obtain router
4372 operator privileges to this router. */
4374 SILC_SERVER_CMD_FUNC(silcoper)
4376 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4377 SilcServer server = cmd->server;
4378 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4379 unsigned char *username = NULL, *auth;
4381 SilcServerConfigAdmin *admin;
4382 SilcIDListData idata = (SilcIDListData)client;
4383 bool result = FALSE;
4384 SilcPublicKey cached_key;
4386 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
4389 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4391 if (server->server_type != SILC_ROUTER) {
4392 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4393 SILC_STATUS_ERR_AUTH_FAILED, 0);
4397 /* Get the username */
4398 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4400 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4401 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4406 /* Check username */
4407 username = silc_identifier_check(username, tmp_len, SILC_STRING_UTF8, 128,
4410 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4411 SILC_STATUS_ERR_BAD_USERNAME,
4416 /* Get the admin configuration */
4417 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4418 username, client->nickname);
4420 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4421 username, client->nickname);
4423 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4424 SILC_STATUS_ERR_AUTH_FAILED, 0);
4425 SILC_LOG_INFO(("SILCOPER authentication failed for username '%s' by "
4426 "nickname '%s' from %s", username,
4427 client->nickname, cmd->sock->hostname));
4432 /* Get the authentication payload */
4433 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4435 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4436 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4441 /* Verify the authentication data. If both passphrase and public key
4442 is set then try both of them. */
4443 if (admin->passphrase)
4444 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4445 admin->passphrase, admin->passphrase_len,
4446 idata->hash, client->id, SILC_ID_CLIENT);
4447 if (!result && admin->publickeys) {
4448 cached_key = silc_server_get_public_key(server, admin->publickeys);
4451 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4452 cached_key, 0, idata->hash,
4453 client->id, SILC_ID_CLIENT);
4456 /* Authentication failed */
4457 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4458 SILC_STATUS_ERR_AUTH_FAILED, 0);
4462 /* Client is now router operator */
4463 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4465 /* Update statistics */
4466 if (SILC_IS_LOCAL(client))
4467 server->stat.my_router_ops++;
4468 if (server->server_type == SILC_ROUTER)
4469 server->stat.router_ops++;
4471 /* Send UMODE change to primary router */
4472 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
4473 SILC_BROADCAST(server), client->id,
4476 /* Check if anyone is watching this nickname */
4477 if (server->server_type == SILC_ROUTER)
4478 silc_server_check_watcher_list(server, client, NULL,
4479 SILC_NOTIFY_TYPE_UMODE_CHANGE);
4481 /* Send reply to the sender */
4482 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4486 silc_free(username);
4487 silc_server_command_free(cmd);
4490 /* Server side of command BAN. This is used to manage the ban list of the
4491 channel. To add clients and remove clients from the ban list. */
4493 SILC_SERVER_CMD_FUNC(ban)
4495 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4496 SilcServer server = cmd->server;
4497 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4498 SilcBuffer packet, list, tmp2;
4499 SilcChannelEntry channel;
4500 SilcChannelClientEntry chl;
4501 SilcChannelID *channel_id = NULL;
4502 unsigned char *id, *tmp, *atype = NULL;
4503 SilcUInt32 id_len, len, len2;
4504 SilcArgumentPayload args;
4505 SilcHashTableList htl;
4507 SilcUInt16 argc = 0, ident = silc_command_get_ident(cmd->payload);
4508 SilcBufferStruct blist;
4510 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
4513 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4515 /* Get Channel ID */
4516 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4518 channel_id = silc_id_payload_parse_id(id, id_len, NULL);
4520 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4521 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4526 /* Get channel entry. The server must know about the channel since the
4527 client is expected to be on the channel. */
4528 channel = silc_idlist_find_channel_by_id(server->local_list,
4531 channel = silc_idlist_find_channel_by_id(server->global_list,
4534 silc_server_command_send_status_data(cmd, SILC_COMMAND_BAN,
4535 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
4541 /* Check whether this client is on the channel */
4542 if (!silc_server_client_on_channel(client, channel, &chl)) {
4543 silc_server_command_send_status_data(cmd, SILC_COMMAND_BAN,
4544 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
4549 /* The client must be at least channel operator. */
4550 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4551 silc_server_command_send_status_data(cmd, SILC_COMMAND_BAN,
4552 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0,
4557 /* Get the ban information */
4558 tmp = silc_argument_get_arg_type(cmd->args, 3, &len2);
4559 if (tmp && len2 > 2) {
4560 /* Parse the arguments to see they are constructed correctly */
4561 SILC_GET16_MSB(argc, tmp);
4562 args = silc_argument_payload_parse(tmp + 2, len2 - 2, argc);
4564 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4565 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4570 /* Get the type of action */
4571 atype = silc_argument_get_arg_type(cmd->args, 2, &len);
4572 if (atype && len == 1) {
4573 if (atype[0] == 0x00) {
4574 /* Allocate hash table for ban list if it doesn't exist yet */
4575 if (!channel->ban_list)
4577 silc_hash_table_alloc(0, silc_hash_ptr,
4579 silc_server_inviteban_destruct, channel,
4582 /* Check for resource limit */
4583 if (silc_hash_table_count(channel->ban_list) > 64) {
4584 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4585 SILC_STATUS_ERR_RESOURCE_LIMIT,
4591 /* Now add or delete the information. */
4592 silc_server_inviteban_process(server, channel->ban_list,
4593 (SilcUInt8)atype[0], args);
4595 silc_argument_payload_free(args);
4598 /* Encode ban list */
4600 if (channel->ban_list && silc_hash_table_count(channel->ban_list)) {
4601 list = silc_buffer_alloc_size(2);
4602 silc_buffer_format(list,
4603 SILC_STR_UI_SHORT(silc_hash_table_count(
4604 channel->ban_list)),
4606 silc_hash_table_list(channel->ban_list, &htl);
4607 while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2))
4608 list = silc_argument_payload_encode_one(list, tmp2->data, tmp2->len,
4610 silc_hash_table_list_reset(&htl);
4613 /* Send BAN notify type to local servers (but not clients) and to
4615 if (atype && tmp && len2) {
4616 silc_buffer_set(&blist, tmp, len2);
4618 /* Send to local servers if we are router */
4619 if (server->server_type == SILC_ROUTER)
4620 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, FALSE,
4621 SILC_NOTIFY_TYPE_BAN, 3,
4624 tmp ? blist.data : NULL,
4625 tmp ? blist.len : 0);
4627 /* Send to network. */
4628 silc_server_send_notify_ban(server, SILC_PRIMARY_ROUTE(server),
4629 SILC_BROADCAST(server), channel, atype,
4633 /* Send the reply back to the client */
4635 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4636 SILC_STATUS_OK, 0, ident, 2,
4638 3, list ? list->data : NULL,
4639 list ? list->len : 0);
4640 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4641 packet->data, packet->len, FALSE);
4643 silc_buffer_free(packet);
4644 silc_buffer_free(list);
4647 silc_free(channel_id);
4648 silc_server_command_free(cmd);
4651 /* Server side command of LEAVE. Removes client from a channel. */
4653 SILC_SERVER_CMD_FUNC(leave)
4655 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4656 SilcServer server = cmd->server;
4657 SilcSocketConnection sock = cmd->sock;
4658 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4659 SilcChannelID *id = NULL;
4660 SilcChannelEntry channel;
4664 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !id_entry)
4667 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4669 /* Get Channel ID */
4670 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4672 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4673 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4676 id = silc_id_payload_parse_id(tmp, len, NULL);
4678 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4679 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4683 /* Get channel entry */
4684 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4686 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4688 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4689 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
4695 /* Check whether this client is on the channel */
4696 if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
4697 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4698 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
4703 /* Notify routers that they should remove this client from their list
4704 of clients on the channel. Send LEAVE notify type. */
4705 silc_server_send_notify_leave(server, SILC_PRIMARY_ROUTE(server),
4706 SILC_BROADCAST(server), channel, id_entry->id);
4708 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4709 SILC_STATUS_OK, 0, 2, tmp, len);
4711 /* Remove client from channel */
4712 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4714 /* If the channel does not exist anymore we won't send anything */
4717 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4718 /* Re-generate channel key */
4719 if (!silc_server_create_channel_key(server, channel, 0))
4722 /* Send the channel key */
4723 silc_server_send_channel_key(server, NULL, channel,
4724 server->server_type == SILC_ROUTER ?
4725 FALSE : !server->standalone);
4730 silc_server_command_free(cmd);
4733 /* Server side of command USERS. Resolves clients and their USERS currently
4734 joined on the requested channel. The list of Client ID's and their modes
4735 on the channel is sent back. */
4737 SILC_SERVER_CMD_FUNC(users)
4739 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4740 SilcServer server = cmd->server;
4741 SilcChannelEntry channel;
4742 SilcChannelID *id = NULL;
4743 SilcBuffer packet, idp;
4744 unsigned char *channel_id;
4745 SilcUInt32 channel_id_len;
4746 SilcBuffer client_id_list;
4747 SilcBuffer client_mode_list;
4748 unsigned char lc[4];
4749 SilcUInt32 list_count = 0;
4750 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4751 char *channel_name = NULL;
4753 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
4755 /* Get Channel ID */
4756 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4758 /* Get channel name */
4759 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
4761 if (!channel_id && !channel_name) {
4762 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4763 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4767 /* Check channel name */
4769 channel_name = silc_identifier_check(channel_name, strlen(channel_name),
4770 SILC_STRING_UTF8, 256, NULL);
4771 if (!channel_name) {
4772 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4773 SILC_STATUS_ERR_BAD_CHANNEL, 0);
4778 /* Check Channel ID */
4780 id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
4782 silc_server_command_send_status_data(cmd, SILC_COMMAND_USERS,
4783 SILC_STATUS_ERR_BAD_CHANNEL_ID, 0,
4784 2, channel_id, channel_id_len);
4789 /* If we are server and we don't know about this channel we will send
4790 the command to our router. If we know about the channel then we also
4791 have the list of users already. */
4793 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4795 channel = silc_idlist_find_channel_by_name(server->local_list,
4796 channel_name, NULL);
4798 if (!channel || (!server->standalone && (channel->disabled ||
4799 !channel->users_resolved))) {
4800 if (server->server_type != SILC_ROUTER && !server->standalone &&
4804 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4805 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4807 /* Send USERS command */
4808 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
4809 SILC_PACKET_COMMAND, cmd->packet->flags,
4810 tmpbuf->data, tmpbuf->len, TRUE);
4812 /* Reprocess this packet after received reply */
4813 silc_server_command_pending(server, SILC_COMMAND_USERS,
4814 silc_command_get_ident(cmd->payload),
4815 silc_server_command_users,
4816 silc_server_command_dup(cmd));
4817 cmd->pending = TRUE;
4818 silc_command_set_ident(cmd->payload, ident);
4819 silc_buffer_free(tmpbuf);
4824 /* Check the global list as well. */
4826 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4828 channel = silc_idlist_find_channel_by_name(server->global_list,
4829 channel_name, NULL);
4831 /* Channel really does not exist */
4833 silc_server_command_send_status_data(
4834 cmd, SILC_COMMAND_USERS,
4835 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID, 0,
4836 2, channel_id, channel_id_len);
4838 silc_server_command_send_status_data(
4839 cmd, SILC_COMMAND_USERS,
4840 SILC_STATUS_ERR_NO_SUCH_CHANNEL, 0,
4841 2, channel_name, strlen(channel_name));
4846 /* If the channel is private or secret do not send anything, unless the
4847 user requesting this command is on the channel or is server */
4848 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
4849 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
4850 && !silc_server_client_on_channel(cmd->sock->user_data, channel,
4852 silc_server_command_send_status_data(cmd, SILC_COMMAND_USERS,
4853 SILC_STATUS_ERR_NO_SUCH_CHANNEL, 0,
4854 2, channel->channel_name,
4855 strlen(channel->channel_name));
4860 /* Get the users list */
4861 if (!silc_server_get_users_on_channel(server, channel, &client_id_list,
4862 &client_mode_list, &list_count)) {
4864 client_id_list = NULL;
4865 client_mode_list = NULL;
4869 SILC_PUT32_MSB(list_count, lc);
4872 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
4873 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
4874 SILC_STATUS_OK, 0, ident, 4,
4875 2, idp->data, idp->len,
4878 client_id_list->data : NULL,
4880 client_id_list->len : 0,
4881 5, client_mode_list ?
4882 client_mode_list->data : NULL,
4884 client_mode_list->len : 0);
4885 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4886 packet->data, packet->len, FALSE);
4888 silc_buffer_free(idp);
4889 silc_buffer_free(packet);
4891 silc_buffer_free(client_id_list);
4892 if (client_mode_list)
4893 silc_buffer_free(client_mode_list);
4897 silc_free(channel_name);
4898 silc_server_command_free(cmd);
4901 /* Server side of command GETKEY. This fetches the client's public key
4902 from the server where to the client is connected. */
4904 SILC_SERVER_CMD_FUNC(getkey)
4906 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4907 SilcServer server = cmd->server;
4909 SilcClientEntry client;
4910 SilcServerEntry server_entry;
4911 SilcClientID *client_id = NULL;
4912 SilcServerID *server_id = NULL;
4913 SilcIDPayload idp = NULL;
4914 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4917 SilcBuffer pk = NULL;
4919 SilcPublicKey public_key;
4921 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4923 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4924 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4928 idp = silc_id_payload_parse(tmp, tmp_len);
4930 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4931 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4936 id_type = silc_id_payload_get_type(idp);
4937 if (id_type == SILC_ID_CLIENT) {
4938 client_id = silc_id_payload_get_id(idp);
4940 /* If the client is not found from local list there is no chance it
4941 would be locally connected client so send the command further. */
4942 client = silc_idlist_find_client_by_id(server->local_list,
4943 client_id, TRUE, NULL);
4945 client = silc_idlist_find_client_by_id(server->global_list,
4946 client_id, TRUE, NULL);
4948 if ((!client && !cmd->pending && !server->standalone) ||
4949 (client && !client->connection && !cmd->pending &&
4950 !(client->mode & SILC_UMODE_DETACHED)) ||
4951 (client && !client->data.public_key && !cmd->pending)) {
4953 SilcUInt16 old_ident;
4954 SilcSocketConnection dest_sock;
4956 dest_sock = silc_server_get_client_route(server, NULL, 0,
4957 client_id, NULL, NULL);
4961 old_ident = silc_command_get_ident(cmd->payload);
4962 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4963 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4965 silc_server_packet_send(server, dest_sock,
4966 SILC_PACKET_COMMAND, cmd->packet->flags,
4967 tmpbuf->data, tmpbuf->len, TRUE);
4969 /* Reprocess this packet after received reply from router */
4970 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
4971 silc_command_get_ident(cmd->payload),
4972 silc_server_command_getkey,
4973 silc_server_command_dup(cmd));
4974 cmd->pending = TRUE;
4975 silc_command_set_ident(cmd->payload, old_ident);
4976 silc_buffer_free(tmpbuf);
4981 silc_server_command_send_status_data(cmd, SILC_COMMAND_GETKEY,
4982 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
4983 0, 2, tmp, tmp_len);
4987 /* The client is locally connected, just get the public key and
4988 send it back. If they key does not exist then do not send it,
4989 send just OK reply */
4990 public_key = client->data.public_key;
4992 pk = silc_pkcs_public_key_payload_encode(public_key);
4993 } else if (id_type == SILC_ID_SERVER) {
4994 server_id = silc_id_payload_get_id(idp);
4996 /* If the server is not found from local list there is no chance it
4997 would be locally connected server so send the command further. */
4998 server_entry = silc_idlist_find_server_by_id(server->local_list,
4999 server_id, TRUE, NULL);
5001 server_entry = silc_idlist_find_server_by_id(server->global_list,
5002 server_id, TRUE, NULL);
5004 if (server_entry != server->id_entry &&
5005 ((!server_entry && !cmd->pending && !server->standalone) ||
5006 (server_entry && !server_entry->connection && !cmd->pending &&
5007 !server->standalone) ||
5008 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5009 !server->standalone))) {
5011 SilcUInt16 old_ident;
5013 old_ident = silc_command_get_ident(cmd->payload);
5014 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5015 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5017 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5018 SILC_PACKET_COMMAND, cmd->packet->flags,
5019 tmpbuf->data, tmpbuf->len, TRUE);
5021 /* Reprocess this packet after received reply from router */
5022 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5023 silc_command_get_ident(cmd->payload),
5024 silc_server_command_getkey,
5025 silc_server_command_dup(cmd));
5026 cmd->pending = TRUE;
5027 silc_command_set_ident(cmd->payload, old_ident);
5028 silc_buffer_free(tmpbuf);
5032 if (!server_entry) {
5033 silc_server_command_send_status_data(cmd, SILC_COMMAND_GETKEY,
5034 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
5035 0, 2, tmp, tmp_len);
5039 /* If they key does not exist then do not send it, send just OK reply */
5040 public_key = (!server_entry->data.public_key ?
5041 (server_entry == server->id_entry ? server->public_key :
5042 NULL) : server_entry->data.public_key);
5044 pk = silc_pkcs_public_key_payload_encode(public_key);
5049 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5050 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5051 SILC_STATUS_OK, 0, ident, 2,
5053 3, pk ? pk->data : NULL,
5055 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5056 packet->data, packet->len, FALSE);
5057 silc_buffer_free(packet);
5061 silc_id_payload_free(idp);
5062 silc_buffer_free(pk);
5063 silc_free(client_id);
5064 silc_free(server_id);
5065 silc_server_command_free(cmd);
5069 /* Private range commands, specific to this implementation */
5071 /* Server side command of CONNECT. Connects us to the specified remote
5072 server or router. */
5074 SILC_SERVER_CMD_FUNC(connect)
5076 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5077 SilcServer server = cmd->server;
5078 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5079 unsigned char *tmp, *host;
5081 SilcUInt32 port = SILC_PORT;
5083 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
5086 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
5088 /* Check whether client has the permissions. */
5089 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5090 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5091 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5092 SILC_STATUS_ERR_NO_SERVER_PRIV, 0);
5096 if (server->server_type == SILC_ROUTER && !server->backup_router &&
5097 client->mode & SILC_UMODE_SERVER_OPERATOR) {
5098 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5099 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
5103 /* Get the remote server */
5104 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5106 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5107 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5113 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5115 SILC_GET32_MSB(port, tmp);
5117 /* Create the connection. It is done with timeout and is async. */
5118 silc_server_create_connection(server, host, port);
5120 /* Send reply to the sender */
5121 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5125 silc_server_command_free(cmd);
5128 /* Server side command of CLOSE. Closes connection to a specified server. */
5130 SILC_SERVER_CMD_FUNC(close)
5132 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5133 SilcServer server = cmd->server;
5134 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5135 SilcServerEntry server_entry;
5136 SilcSocketConnection sock;
5139 unsigned char *name;
5140 SilcUInt32 port = SILC_PORT;
5142 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
5145 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
5147 /* Check whether client has the permissions. */
5148 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5149 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5150 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5151 SILC_STATUS_ERR_NO_SERVER_PRIV,
5156 /* Get the remote server */
5157 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5159 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5160 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5166 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5168 SILC_GET32_MSB(port, tmp);
5170 server_entry = silc_idlist_find_server_by_conn(server->local_list,
5171 name, port, TRUE, NULL);
5173 server_entry = silc_idlist_find_server_by_conn(server->global_list,
5174 name, port, TRUE, NULL);
5175 if (!server_entry) {
5176 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5177 SILC_STATUS_ERR_NO_SERVER_ID, 0);
5181 if (server_entry == server->id_entry) {
5182 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5183 SILC_STATUS_ERR_NO_SERVER_ID, 0);
5187 /* Send reply to the sender */
5188 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5191 /* Close the connection to the server */
5192 sock = (SilcSocketConnection)server_entry->connection;
5194 if (server_entry->server_type == SILC_BACKUP_ROUTER) {
5195 server->backup_closed = TRUE;
5196 silc_server_backup_del(server, server_entry);
5199 server->backup_noswitch = TRUE;
5200 if (server->router == server_entry) {
5201 server->id_entry->router = NULL;
5202 server->router = NULL;
5203 server->standalone = TRUE;
5205 silc_server_disconnect_remote(server, sock,
5206 SILC_STATUS_ERR_BANNED_FROM_SERVER,
5207 "Closed by administrator");
5208 if (sock->user_data)
5209 silc_server_free_sock_user_data(server, sock, NULL);
5210 server->backup_noswitch = FALSE;
5213 silc_server_command_free(cmd);
5216 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
5217 active connections. */
5219 SILC_SERVER_CMD_FUNC(shutdown)
5221 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5222 SilcServer server = cmd->server;
5223 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5225 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
5228 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
5230 /* Check whether client has the permission. */
5231 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5232 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5233 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5234 SILC_STATUS_ERR_NO_SERVER_PRIV,
5239 /* Send reply to the sender */
5240 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5243 /* Then, gracefully, or not, bring the server down. */
5244 silc_server_stop(server);
5248 silc_server_command_free(cmd);