5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2004 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;
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);
647 if (silc_server_name_bad_chars(nick, nick_len) == TRUE) {
648 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
649 SILC_STATUS_ERR_BAD_NICKNAME, 0);
653 /* Check for same nickname */
654 if (!strcmp(client->nickname, nick)) {
655 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
659 /* Create new Client ID */
660 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
662 cmd->server->md5hash, nick,
666 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
667 SILC_STATUS_ERR_BAD_NICKNAME, 0);
670 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
673 /* Send notify about nickname change to our router. We send the new
674 ID and ask to replace it with the old one. If we are router the
675 packet is broadcasted. Send NICK_CHANGE notify. */
676 silc_server_send_notify_nick_change(server, SILC_PRIMARY_ROUTE(server),
677 SILC_BROADCAST(server), client->id,
680 /* Check if anyone is watching the old nickname */
681 if (server->server_type == SILC_ROUTER)
682 silc_server_check_watcher_list(server, client, nick,
683 SILC_NOTIFY_TYPE_NICK_CHANGE);
685 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
687 /* Remove old cache entry */
688 silc_idcache_del_by_context(server->local_list->clients, client);
690 silc_free(client->id);
693 silc_free(client->nickname);
694 client->nickname = strdup(nick);
696 /* Update client cache */
697 silc_idcache_add(server->local_list->clients, client->nickname,
698 client->id, (void *)client, 0, NULL);
700 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
702 /* Send NICK_CHANGE notify to the client's channels */
703 silc_server_send_notify_on_channels(server, NULL, client,
704 SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
705 oidp->data, oidp->len,
706 nidp->data, nidp->len,
708 strlen(client->nickname));
710 /* Check if anyone is watching the new nickname */
711 if (server->server_type == SILC_ROUTER)
712 silc_server_check_watcher_list(server, client, NULL,
713 SILC_NOTIFY_TYPE_NICK_CHANGE);
716 /* Send the new Client ID as reply command back to client */
717 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
718 SILC_STATUS_OK, 0, ident, 2,
719 2, nidp->data, nidp->len,
720 3, nick, strlen(nick));
721 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
722 0, packet->data, packet->len, FALSE);
724 silc_buffer_free(packet);
725 silc_buffer_free(nidp);
727 silc_buffer_free(oidp);
730 silc_server_command_free(cmd);
733 /* Sends the LIST command reply */
736 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
737 SilcChannelEntry *lch,
738 SilcUInt32 lch_count,
739 SilcChannelEntry *gch,
740 SilcUInt32 gch_count)
743 SilcBuffer packet, idp;
744 SilcChannelEntry entry;
746 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
748 unsigned char usercount[4];
750 int valid_lcount = 0, valid_rcount = 0;
752 for (i = 0; i < lch_count; i++) {
753 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
758 for (i = 0; i < gch_count; i++) {
759 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
765 if (!lch_count && !gch_count) {
766 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
771 status = SILC_STATUS_OK;
772 if ((lch_count + gch_count) > 1)
773 status = SILC_STATUS_LIST_START;
776 for (i = 0, k = 0; i < lch_count; i++) {
782 status = SILC_STATUS_LIST_ITEM;
783 if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
784 status = SILC_STATUS_LIST_END;
786 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
788 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
790 memset(usercount, 0, sizeof(usercount));
792 topic = entry->topic;
793 users = silc_hash_table_count(entry->user_list);
794 SILC_PUT32_MSB(users, usercount);
799 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
801 2, idp->data, idp->len,
802 3, entry->channel_name,
803 strlen(entry->channel_name),
804 4, topic, topic ? strlen(topic) : 0,
806 silc_server_packet_send(cmd->server, cmd->sock,
807 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
809 silc_buffer_free(packet);
810 silc_buffer_free(idp);
815 for (i = 0, k = 0; i < gch_count; i++) {
821 status = SILC_STATUS_LIST_ITEM;
822 if (valid_rcount > 1 && k == valid_rcount - 1)
823 status = SILC_STATUS_LIST_END;
825 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
827 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
829 memset(usercount, 0, sizeof(usercount));
831 topic = entry->topic;
832 users = entry->user_count;
833 SILC_PUT32_MSB(users, usercount);
838 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
840 2, idp->data, idp->len,
841 3, entry->channel_name,
842 strlen(entry->channel_name),
843 4, topic, topic ? strlen(topic) : 0,
845 silc_server_packet_send(cmd->server, cmd->sock,
846 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
848 silc_buffer_free(packet);
849 silc_buffer_free(idp);
854 /* Server side of LIST command. This lists the channel of the requested
855 server. Secret channels are not listed. */
857 SILC_SERVER_CMD_FUNC(list)
859 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
860 SilcServer server = cmd->server;
861 SilcChannelID *channel_id = NULL;
864 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
865 SilcUInt32 lch_count = 0, gch_count = 0;
867 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
869 /* If we are normal server, send the command to router, since we
870 want to know all channels in the network. */
871 if (!cmd->pending && server->server_type != SILC_ROUTER &&
872 !server->standalone) {
874 SilcUInt16 old_ident;
876 old_ident = silc_command_get_ident(cmd->payload);
877 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
878 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
879 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
880 SILC_PACKET_COMMAND, cmd->packet->flags,
881 tmpbuf->data, tmpbuf->len, TRUE);
883 /* Reprocess this packet after received reply from router */
884 silc_server_command_pending(server, SILC_COMMAND_LIST,
885 silc_command_get_ident(cmd->payload),
886 silc_server_command_list,
887 silc_server_command_dup(cmd));
889 silc_command_set_ident(cmd->payload, old_ident);
890 silc_buffer_free(tmpbuf);
895 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
897 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
899 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
900 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
905 /* Get the channels from local list */
906 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
909 /* Get the channels from global list */
910 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
914 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
915 gchannels, gch_count);
917 silc_free(lchannels);
918 silc_free(gchannels);
921 silc_server_command_free(cmd);
924 /* Server side of TOPIC command. Sets topic for channel and/or returns
925 current topic to client. */
927 SILC_SERVER_CMD_FUNC(topic)
929 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
930 SilcServer server = cmd->server;
931 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
932 SilcChannelID *channel_id;
933 SilcChannelEntry channel;
934 SilcChannelClientEntry chl;
935 SilcBuffer packet, idp;
937 SilcUInt32 argc, tmp_len;
938 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
940 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
943 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
945 argc = silc_argument_get_arg_num(cmd->args);
948 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
950 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
951 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
954 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
956 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
957 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
961 /* Check whether the channel exists */
962 channel = silc_idlist_find_channel_by_id(server->local_list,
965 channel = silc_idlist_find_channel_by_id(server->global_list,
968 silc_server_command_send_status_data(cmd, SILC_COMMAND_TOPIC,
969 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
977 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
979 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
980 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
985 if (strlen(tmp) > 256) {
986 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
987 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
992 /* See whether the client is on channel and has rights to change topic */
993 if (!silc_server_client_on_channel(client, channel, &chl)) {
994 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
995 silc_server_command_send_status_data(cmd, SILC_COMMAND_TOPIC,
996 SILC_STATUS_ERR_NOT_ON_CHANNEL,
1001 if (channel->mode & SILC_CHANNEL_MODE_TOPIC &&
1002 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
1003 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
1004 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1005 silc_server_command_send_status_data(cmd, SILC_COMMAND_TOPIC,
1006 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
1007 0, 2, tmp, tmp_len);
1011 if (!channel->topic || strcmp(channel->topic, tmp)) {
1012 /* Set the topic for channel */
1013 silc_free(channel->topic);
1014 channel->topic = strdup(tmp);
1016 /* Send TOPIC_SET notify type to the network */
1017 silc_server_send_notify_topic_set(server, SILC_PRIMARY_ROUTE(server),
1018 SILC_BROADCAST(server), channel,
1019 client->id, SILC_ID_CLIENT,
1022 /* Send notify about topic change to all clients on the channel */
1023 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1024 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
1025 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
1026 idp->data, idp->len,
1028 strlen(channel->topic));
1029 silc_buffer_free(idp);
1033 /* Send the topic to client as reply packet */
1034 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1035 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1036 SILC_STATUS_OK, 0, ident, 2,
1037 2, idp->data, idp->len,
1040 strlen(channel->topic) : 0);
1041 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1042 0, packet->data, packet->len, FALSE);
1044 silc_buffer_free(packet);
1045 silc_buffer_free(idp);
1046 silc_free(channel_id);
1049 silc_server_command_free(cmd);
1052 /* Server side of INVITE command. Invites some client to join some channel.
1053 This command is also used to manage the invite list of the channel. */
1055 SILC_SERVER_CMD_FUNC(invite)
1057 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1058 SilcServer server = cmd->server;
1059 SilcSocketConnection sock = cmd->sock, dest_sock;
1060 SilcChannelClientEntry chl;
1061 SilcClientEntry sender, dest;
1062 SilcClientID *dest_id = NULL;
1063 SilcChannelEntry channel;
1064 SilcChannelID *channel_id = NULL;
1065 SilcIDListData idata;
1066 SilcArgumentPayload args;
1067 SilcHashTableList htl;
1068 SilcBuffer packet, list, tmp2;
1069 SilcBufferStruct alist;
1070 unsigned char *tmp, *atype = NULL;
1071 SilcUInt32 len, type, len2;
1072 SilcUInt16 argc = 0, ident = silc_command_get_ident(cmd->payload);
1074 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
1076 /* Get Channel ID */
1077 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1079 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1080 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
1083 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
1085 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1086 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
1090 /* Get the channel entry */
1091 channel = silc_idlist_find_channel_by_id(server->local_list,
1094 channel = silc_idlist_find_channel_by_id(server->global_list,
1097 silc_server_command_send_status_data(cmd, SILC_COMMAND_INVITE,
1098 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
1104 /* Check whether the sender of this command is on the channel. */
1105 sender = (SilcClientEntry)sock->user_data;
1106 if (!sender || !silc_server_client_on_channel(sender, channel, &chl)) {
1107 silc_server_command_send_status_data(cmd, SILC_COMMAND_INVITE,
1108 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
1113 /* Check whether the channel is invite-only channel. If yes then the
1114 sender of this command must be at least channel operator. */
1115 if (channel->mode & SILC_CHANNEL_MODE_INVITE &&
1116 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
1117 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
1118 silc_server_command_send_status_data(cmd, SILC_COMMAND_INVITE,
1119 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
1124 /* Get destination client ID */
1125 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1129 dest_id = silc_id_payload_parse_id(tmp, len, NULL);
1131 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1132 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
1136 /* Get the client entry */
1137 dest = silc_server_query_client(server, dest_id, FALSE, &resolve);
1139 if (server->server_type != SILC_SERVER || !resolve || cmd->pending) {
1140 silc_server_command_send_status_data(
1141 cmd, SILC_COMMAND_INVITE,
1142 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0,
1147 /* The client info is being resolved. Reprocess this packet after
1148 receiving the reply to the query. */
1149 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1151 silc_server_command_invite,
1152 silc_server_command_dup(cmd));
1153 cmd->pending = TRUE;
1157 /* Check whether the requested client is already on the channel. */
1158 if (silc_server_client_on_channel(dest, channel, NULL)) {
1159 atype = silc_argument_get_arg_type(cmd->args, 1, &len2);
1160 silc_server_command_send_status_data2(cmd, SILC_COMMAND_INVITE,
1161 SILC_STATUS_ERR_USER_ON_CHANNEL,
1167 /* Get route to the client */
1168 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id,
1171 silc_server_command_send_status_data(cmd, SILC_COMMAND_INVITE,
1172 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1177 /* Add the client to the invite list */
1179 /* Allocate hash table for invite list if it doesn't exist yet */
1180 if (!channel->invite_list)
1181 channel->invite_list =
1182 silc_hash_table_alloc(0, silc_hash_ptr,
1184 silc_server_inviteban_destruct, channel, TRUE);
1186 /* Check if the ID is in the list already */
1187 silc_hash_table_list(channel->invite_list, &htl);
1188 while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) {
1189 if (type == 3 && !memcmp(tmp2->data, tmp, len)) {
1194 silc_hash_table_list_reset(&htl);
1196 /* Add new Client ID to invite list */
1198 list = silc_buffer_alloc_size(len);
1199 silc_buffer_put(list, tmp, len);
1200 silc_hash_table_add(channel->invite_list, (void *)3, list);
1203 if (!(dest->mode & SILC_UMODE_BLOCK_INVITE)) {
1204 /* Send notify to the client that is invited to the channel */
1205 SilcBuffer idp, idp2;
1206 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1207 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1208 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
1210 SILC_NOTIFY_TYPE_INVITE, 3,
1211 idp->data, idp->len,
1212 channel->channel_name,
1213 strlen(channel->channel_name),
1214 idp2->data, idp2->len);
1215 silc_buffer_free(idp);
1216 silc_buffer_free(idp2);
1220 /* Get the invite information */
1221 tmp = silc_argument_get_arg_type(cmd->args, 4, &len2);
1222 if (tmp && len2 > 2) {
1223 /* Parse the arguments to see they are constructed correctly */
1224 SILC_GET16_MSB(argc, tmp);
1225 args = silc_argument_payload_parse(tmp + 2, len2 - 2, argc);
1227 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1228 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1233 /* Get the type of action */
1234 atype = silc_argument_get_arg_type(cmd->args, 3, &len);
1235 if (atype && len == 1) {
1236 if (atype[0] == 0x00) {
1237 /* Allocate hash table for invite list if it doesn't exist yet */
1238 if (!channel->invite_list)
1239 channel->invite_list =
1240 silc_hash_table_alloc(0, silc_hash_ptr,
1242 silc_server_inviteban_destruct, channel,
1245 /* Check for resource limit */
1246 if (silc_hash_table_count(channel->invite_list) > 64) {
1247 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1248 SILC_STATUS_ERR_RESOURCE_LIMIT,
1254 /* Now add or delete the information. */
1255 silc_server_inviteban_process(server, channel->invite_list,
1256 (SilcUInt8)atype[0], args);
1258 silc_argument_payload_free(args);
1261 /* Encode invite list */
1263 if (channel->invite_list && silc_hash_table_count(channel->invite_list)) {
1264 list = silc_buffer_alloc_size(2);
1265 silc_buffer_format(list,
1266 SILC_STR_UI_SHORT(silc_hash_table_count(
1267 channel->invite_list)),
1269 silc_hash_table_list(channel->invite_list, &htl);
1270 while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2))
1271 list = silc_argument_payload_encode_one(list, tmp2->data, tmp2->len,
1273 silc_hash_table_list_reset(&htl);
1276 /* The notify is sent to local servers (not clients), and to network. */
1277 if (atype && tmp && len2) {
1278 silc_buffer_set(&alist, tmp, len2);
1280 /* Send to local servers if we are router */
1281 if (server->server_type == SILC_ROUTER) {
1282 SilcBuffer idp, idp2;
1283 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1284 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1285 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, FALSE,
1286 SILC_NOTIFY_TYPE_INVITE, 5,
1287 idp->data, idp->len,
1288 channel->channel_name,
1289 strlen(channel->channel_name),
1290 idp2->data, idp2->len,
1292 tmp ? alist.data : NULL,
1293 tmp ? alist.len : 0);
1294 silc_buffer_free(idp);
1295 silc_buffer_free(idp2);
1298 /* Send to network */
1299 silc_server_send_notify_invite(server, SILC_PRIMARY_ROUTE(server),
1300 SILC_BROADCAST(server), channel,
1302 tmp ? &alist : NULL);
1305 /* Send invite list back only if the list was modified, or no arguments
1308 argc = silc_argument_get_arg_num(cmd->args);
1311 if (silc_argument_get_arg_type(cmd->args, 3, &len))
1314 /* Send command reply */
1315 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1316 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
1317 SILC_STATUS_OK, 0, ident, 2,
1321 type && list ? list->len : 0);
1322 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1323 packet->data, packet->len, FALSE);
1324 silc_buffer_free(packet);
1325 silc_buffer_free(list);
1329 silc_free(channel_id);
1330 silc_server_command_free(cmd);
1334 SilcSocketConnection sock;
1338 /* Quits connection to client. This gets called if client won't
1339 close the connection even when it has issued QUIT command. */
1341 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
1343 SilcServer server = app_context;
1344 QuitInternal q = (QuitInternal)context;
1346 if (q->sock->user_data) {
1347 /* Free all client specific data, such as client entry and entires
1348 on channels this client may be on. */
1349 silc_server_free_client_data(server, q->sock, q->sock->user_data,
1351 q->sock->user_data = NULL;
1354 if (!SILC_IS_DISCONNECTED(q->sock))
1355 /* Close the connection on our side */
1356 silc_server_close_connection(server, q->sock);
1358 silc_socket_free(q->sock);
1359 silc_free(q->signoff);
1363 /* Quits SILC session. This is the normal way to disconnect client. */
1365 SILC_SERVER_CMD_FUNC(quit)
1367 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1368 SilcServer server = cmd->server;
1369 SilcSocketConnection sock = cmd->sock;
1371 unsigned char *tmp = NULL;
1374 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
1376 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1380 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1384 q = silc_calloc(1, sizeof(*q));
1385 q->sock = silc_socket_dup(sock);
1386 q->signoff = tmp ? strdup(tmp) : NULL;
1388 /* We quit the connection with little timeout */
1389 silc_schedule_task_add(server->schedule, sock->sock,
1390 silc_server_command_quit_cb, (void *)q,
1391 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1394 silc_server_command_free(cmd);
1397 /* Server side of command KILL. This command is used by router operator
1398 to remove an client from the SILC Network temporarily. */
1400 SILC_SERVER_CMD_FUNC(kill)
1402 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1403 SilcServer server = cmd->server;
1404 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1405 SilcClientEntry remote_client;
1406 SilcClientID *client_id = NULL;
1407 unsigned char *tmp, *comment, *auth;
1408 SilcUInt32 tmp_len, tmp_len2, auth_len;
1410 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 3);
1412 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
1415 /* Get authentication payload if present */
1416 auth = silc_argument_get_arg_type(cmd->args, 3, &auth_len);
1419 /* Router operator killing */
1421 /* KILL command works only on router */
1422 if (server->server_type != SILC_ROUTER) {
1423 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1424 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
1428 /* Check whether client has the permissions. */
1429 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
1430 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1431 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
1436 /* Get the client ID */
1437 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1439 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1440 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1444 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1446 silc_server_command_send_status_data(cmd, SILC_COMMAND_KILL,
1447 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1448 0, 2, tmp, tmp_len);
1452 /* Get the client entry */
1453 remote_client = silc_idlist_find_client_by_id(server->local_list,
1454 client_id, TRUE, NULL);
1455 if (!remote_client) {
1456 remote_client = silc_idlist_find_client_by_id(server->global_list,
1457 client_id, TRUE, NULL);
1458 if (!remote_client) {
1459 silc_server_command_send_status_data(cmd, SILC_COMMAND_KILL,
1460 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1461 0, 2, tmp, tmp_len);
1467 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
1468 if (comment && tmp_len2 > 128) {
1470 comment[127] = '\0';
1473 /* If authentication data is provided then verify that killing is
1475 if (auth && auth_len) {
1476 SilcSocketConnection sock;
1478 if (!SILC_IS_LOCAL(remote_client) || !remote_client->data.public_key) {
1479 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1480 SILC_STATUS_ERR_OPERATION_ALLOWED,
1485 /* Verify the signature */
1486 if (!silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
1487 remote_client->data.public_key, 0,
1488 server->sha1hash, remote_client->id,
1490 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1491 SILC_STATUS_ERR_AUTH_FAILED, 0);
1495 /* Send reply to the sender */
1496 silc_server_command_send_status_data(cmd, SILC_COMMAND_KILL,
1500 /* Do normal signoff for the destination client */
1501 sock = remote_client->connection;
1502 silc_server_remove_from_channels(server, NULL, remote_client,
1503 TRUE, (char *)"Killed", TRUE, TRUE);
1504 silc_server_free_client_data(server, NULL, remote_client, TRUE,
1506 (unsigned char *)"Killed");
1508 silc_server_close_connection(server, sock);
1510 /* Router operator killing */
1512 /* Send reply to the sender */
1513 silc_server_command_send_status_data(cmd, SILC_COMMAND_KILL,
1517 /* Check if anyone is watching this nickname */
1518 if (server->server_type == SILC_ROUTER)
1519 silc_server_check_watcher_list(server, client, NULL,
1520 SILC_NOTIFY_TYPE_KILLED);
1522 /* Now do the killing */
1523 silc_server_kill_client(server, remote_client, comment, client->id,
1528 silc_free(client_id);
1529 silc_server_command_free(cmd);
1532 /* Server side of command INFO. This sends information about us to
1533 the client. If client requested specific server we will send the
1534 command to that server. */
1536 SILC_SERVER_CMD_FUNC(info)
1538 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1539 SilcServer server = cmd->server;
1540 SilcBuffer packet, idp;
1543 char *dest_server, *server_info = NULL, *server_name;
1544 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1545 SilcServerEntry entry = NULL;
1546 SilcServerID *server_id = NULL;
1548 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
1550 /* Get server name */
1551 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1554 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1556 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1558 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1559 SILC_STATUS_ERR_NO_SERVER_ID, 0);
1565 /* Check whether we have this server cached */
1566 entry = silc_idlist_find_server_by_id(server->local_list,
1567 server_id, TRUE, NULL);
1569 entry = silc_idlist_find_server_by_id(server->global_list,
1570 server_id, TRUE, NULL);
1571 if (!entry && server->server_type != SILC_SERVER) {
1572 silc_server_command_send_status_data(cmd, SILC_COMMAND_INFO,
1573 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
1574 0, 2, tmp, tmp_len);
1580 /* Some buggy servers has sent request to router about themselves. */
1581 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
1584 if ((!dest_server && !server_id && !entry) || (entry &&
1585 entry == server->id_entry) ||
1586 (dest_server && !cmd->pending &&
1587 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
1588 /* Send our reply */
1589 char info_string[256];
1591 memset(info_string, 0, sizeof(info_string));
1592 snprintf(info_string, sizeof(info_string),
1593 "location: %s server: %s admin: %s <%s>",
1594 server->config->server_info->location,
1595 server->config->server_info->server_type,
1596 server->config->server_info->admin,
1597 server->config->server_info->email);
1599 server_info = info_string;
1600 entry = server->id_entry;
1602 /* Check whether we have this server cached */
1603 if (!entry && dest_server) {
1604 entry = silc_idlist_find_server_by_name(server->global_list,
1605 dest_server, TRUE, NULL);
1607 entry = silc_idlist_find_server_by_name(server->local_list,
1608 dest_server, TRUE, NULL);
1612 if (!cmd->pending &&
1613 server->server_type != SILC_SERVER && entry && !entry->server_info) {
1614 /* Send to the server */
1616 SilcUInt16 old_ident;
1618 old_ident = silc_command_get_ident(cmd->payload);
1619 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1620 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1622 silc_server_packet_send(server, entry->connection,
1623 SILC_PACKET_COMMAND, cmd->packet->flags,
1624 tmpbuf->data, tmpbuf->len, TRUE);
1626 /* Reprocess this packet after received reply from router */
1627 silc_server_command_pending(server, SILC_COMMAND_INFO,
1628 silc_command_get_ident(cmd->payload),
1629 silc_server_command_info,
1630 silc_server_command_dup(cmd));
1631 cmd->pending = TRUE;
1632 silc_command_set_ident(cmd->payload, old_ident);
1633 silc_buffer_free(tmpbuf);
1637 if (!entry && !cmd->pending && !server->standalone) {
1638 /* Send to the primary router */
1640 SilcUInt16 old_ident;
1642 old_ident = silc_command_get_ident(cmd->payload);
1643 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1644 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1646 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
1647 SILC_PACKET_COMMAND, cmd->packet->flags,
1648 tmpbuf->data, tmpbuf->len, TRUE);
1650 /* Reprocess this packet after received reply from router */
1651 silc_server_command_pending(server, SILC_COMMAND_INFO,
1652 silc_command_get_ident(cmd->payload),
1653 silc_server_command_info,
1654 silc_server_command_dup(cmd));
1655 cmd->pending = TRUE;
1656 silc_command_set_ident(cmd->payload, old_ident);
1657 silc_buffer_free(tmpbuf);
1662 silc_free(server_id);
1666 silc_server_command_send_status_data(cmd, SILC_COMMAND_INFO,
1667 SILC_STATUS_ERR_NO_SUCH_SERVER, 0,
1669 strlen(dest_server));
1673 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1675 server_info = entry->server_info;
1676 server_name = entry->server_name;
1678 /* Send the reply */
1679 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
1680 SILC_STATUS_OK, 0, ident, 3,
1681 2, idp->data, idp->len,
1683 strlen(server_name),
1686 strlen(server_info) : 0);
1687 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1688 packet->data, packet->len, FALSE);
1690 silc_buffer_free(packet);
1691 silc_buffer_free(idp);
1694 silc_server_command_free(cmd);
1697 /* Server side of command PING. This just replies to the ping. */
1699 SILC_SERVER_CMD_FUNC(ping)
1701 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1702 SilcServer server = cmd->server;
1705 SilcServerID *server_id = NULL;
1707 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PING, cmd, 1, 1);
1710 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1712 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1713 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1717 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1721 if (SILC_ID_SERVER_COMPARE(server_id, server->id)) {
1722 /* Send our reply */
1723 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1726 silc_server_command_send_status_data(cmd, SILC_COMMAND_PING,
1727 SILC_STATUS_ERR_NO_SUCH_SERVER_ID, 0,
1733 silc_free(server_id);
1734 silc_server_command_free(cmd);
1737 /* Server side of command STATS. */
1739 SILC_SERVER_CMD_FUNC(stats)
1741 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1742 SilcServer server = cmd->server;
1743 SilcServerID *server_id;
1746 SilcBuffer packet, stats;
1747 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1750 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1);
1753 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1755 silc_server_command_send_status_reply(cmd, SILC_COMMAND_STATS,
1756 SILC_STATUS_ERR_NO_SERVER_ID, 0);
1759 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1763 /* The ID must be ours */
1764 if (!SILC_ID_SERVER_COMPARE(server->id, server_id)) {
1765 silc_server_command_send_status_data(cmd, SILC_COMMAND_STATS,
1766 SILC_STATUS_ERR_NO_SUCH_SERVER_ID, 0,
1768 silc_free(server_id);
1771 silc_free(server_id);
1773 /* If we are router then just send everything we got. If we are normal
1774 server then we'll send this to our router to get all the latest
1775 statistical information. */
1776 if (!cmd->pending && server->server_type != SILC_ROUTER &&
1777 !server->standalone) {
1778 /* Send request to our router */
1779 SilcBuffer idp = silc_id_payload_encode(server->router->id,
1781 packet = silc_command_payload_encode_va(SILC_COMMAND_STATS,
1782 ++server->cmd_ident, 1,
1783 1, idp->data, idp->len);
1784 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
1785 SILC_PACKET_COMMAND, 0, packet->data,
1786 packet->len, FALSE);
1788 /* Reprocess this packet after received reply from router */
1789 silc_server_command_pending(server, SILC_COMMAND_STATS,
1791 silc_server_command_stats,
1792 silc_server_command_dup(cmd));
1793 cmd->pending = TRUE;
1794 silc_buffer_free(packet);
1795 silc_buffer_free(idp);
1799 /* Send our reply to sender */
1800 uptime = time(NULL) - server->starttime;
1802 stats = silc_buffer_alloc_size(60);
1803 silc_buffer_format(stats,
1804 SILC_STR_UI_INT(server->starttime),
1805 SILC_STR_UI_INT(uptime),
1806 SILC_STR_UI_INT(server->stat.my_clients),
1807 SILC_STR_UI_INT(server->stat.my_channels),
1808 SILC_STR_UI_INT(server->stat.my_server_ops),
1809 SILC_STR_UI_INT(server->stat.my_router_ops),
1810 SILC_STR_UI_INT(server->stat.cell_clients),
1811 SILC_STR_UI_INT(server->stat.cell_channels),
1812 SILC_STR_UI_INT(server->stat.cell_servers),
1813 SILC_STR_UI_INT(server->stat.clients),
1814 SILC_STR_UI_INT(server->stat.channels),
1815 SILC_STR_UI_INT(server->stat.servers),
1816 SILC_STR_UI_INT(server->stat.routers),
1817 SILC_STR_UI_INT(server->stat.server_ops),
1818 SILC_STR_UI_INT(server->stat.router_ops),
1821 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_STATS,
1822 SILC_STATUS_OK, 0, ident, 2,
1824 3, stats->data, stats->len);
1825 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1826 0, packet->data, packet->len, FALSE);
1827 silc_buffer_free(packet);
1828 silc_buffer_free(stats);
1831 silc_server_command_free(cmd);
1834 /* Internal routine to join channel. The channel sent to this function
1835 has been either created or resolved from ID lists. This joins the sent
1836 client to the channel. */
1838 static void silc_server_command_join_channel(SilcServer server,
1839 SilcServerCommandContext cmd,
1840 SilcChannelEntry channel,
1841 SilcClientID *client_id,
1845 const unsigned char *auth,
1846 SilcUInt32 auth_len,
1847 const unsigned char *cauth,
1848 SilcUInt32 cauth_len)
1850 SilcSocketConnection sock = cmd->sock;
1852 SilcUInt32 tmp_len, user_count;
1853 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4], ulimit[4];
1854 SilcClientEntry client;
1855 SilcChannelClientEntry chl;
1856 SilcBuffer reply, chidp, clidp, keyp = NULL;
1857 SilcBuffer user_list, mode_list, invite_list, ban_list;
1858 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1859 char check[512], check2[512];
1860 bool founder = FALSE;
1862 SilcBuffer fkey = NULL, chpklist = NULL;
1865 SILC_LOG_DEBUG(("Joining client to channel"));
1870 /* Get the client entry */
1871 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1872 client = (SilcClientEntry)sock->user_data;
1876 client = silc_server_query_client(server, client_id, FALSE,
1879 if (!resolve || cmd->pending) {
1880 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1881 silc_server_command_send_status_data(
1882 cmd, SILC_COMMAND_JOIN,
1883 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0,
1888 /* The client info is being resolved. Reprocess this packet after
1889 receiving the reply to the query. */
1890 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1892 silc_server_command_join,
1893 silc_server_command_dup(cmd));
1894 cmd->pending = TRUE;
1898 if (!client->data.public_key &&
1899 (auth || cauth || channel->ban_list ||
1900 (channel->mode & SILC_CHANNEL_MODE_INVITE))) {
1901 if (cmd->pending == 2)
1904 /* We must retrieve the client's public key by sending
1905 GETKEY command. Reprocess this packet after receiving the key */
1906 clidp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
1907 silc_server_send_command(server, cmd->sock,
1908 SILC_COMMAND_GETKEY, ++server->cmd_ident,
1909 1, 1, clidp->data, clidp->len);
1910 silc_buffer_free(clidp);
1911 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
1913 silc_server_command_join,
1914 silc_server_command_dup(cmd));
1919 cmd->pending = FALSE;
1923 * Check founder auth payload if provided. If client can gain founder
1924 * privileges it can override various conditions on joining the channel,
1925 * and can have directly the founder mode set on the channel.
1927 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1928 SilcIDListData idata = (SilcIDListData)client;
1929 SilcChannelClientEntry chl2;
1930 SilcHashTableList htl;
1932 if (channel->founder_key && idata->public_key &&
1933 silc_pkcs_public_key_compare(channel->founder_key,
1934 idata->public_key)) {
1935 /* Check whether the client is to become founder */
1936 if (silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
1937 channel->founder_key, 0, server->sha1hash,
1938 client->id, SILC_ID_CLIENT)) {
1940 /* There cannot be anyone else as founder on the channel now. This
1941 client is definitely the founder due to this authentication */
1942 silc_hash_table_list(channel->user_list, &htl);
1943 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
1944 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
1945 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
1946 silc_server_force_cumode_change(server, NULL, channel, chl2,
1950 silc_hash_table_list_reset(&htl);
1952 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
1959 * Check channel modes
1963 memset(check, 0, sizeof(check));
1964 memset(check2, 0, sizeof(check2));
1965 silc_strncat(check, sizeof(check),
1966 client->nickname, strlen(client->nickname));
1967 silc_strncat(check, sizeof(check), "!", 1);
1968 silc_strncat(check, sizeof(check),
1969 client->username, strlen(client->username));
1970 if (!strchr(client->username, '@')) {
1971 silc_strncat(check, sizeof(check), "@", 1);
1972 silc_strncat(check, sizeof(check),
1973 cmd->sock->hostname, strlen(cmd->sock->hostname));
1976 silc_strncat(check2, sizeof(check2),
1977 client->nickname, strlen(client->nickname));
1978 if (!strchr(client->nickname, '@')) {
1979 silc_strncat(check2, sizeof(check2), "@", 1);
1980 silc_strncat(check2, sizeof(check2),
1981 SILC_IS_LOCAL(client) ? server->server_name :
1982 client->router->server_name,
1983 SILC_IS_LOCAL(client) ? strlen(server->server_name) :
1984 strlen(client->router->server_name));
1986 silc_strncat(check2, sizeof(check2), "!", 1);
1987 silc_strncat(check2, sizeof(check2),
1988 client->username, strlen(client->username));
1989 if (!strchr(client->username, '@')) {
1990 silc_strncat(check2, sizeof(check2), "@", 1);
1991 silc_strncat(check2, sizeof(check2),
1992 cmd->sock->hostname, strlen(cmd->sock->hostname));
1995 /* Check invite list if channel is invite-only channel */
1996 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1997 if (!channel->invite_list ||
1998 !silc_hash_table_count(channel->invite_list) ||
1999 (!silc_server_inviteban_match(server, channel->invite_list,
2001 !silc_server_inviteban_match(server, channel->invite_list,
2002 2, client->data.public_key) &&
2003 !silc_server_inviteban_match(server, channel->invite_list,
2004 1, client->nickname) &&
2005 !silc_server_inviteban_match(server, channel->invite_list,
2007 !silc_server_inviteban_match(server, channel->invite_list,
2009 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2010 silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
2011 SILC_STATUS_ERR_NOT_INVITED, 0,
2012 2, chidp->data, chidp->len);
2013 silc_buffer_free(chidp);
2018 /* Check ban list if it exists. If the client's nickname, server,
2019 username and/or hostname is in the ban list the access to the
2020 channel is denied. */
2021 if (channel->ban_list && silc_hash_table_count(channel->ban_list)) {
2022 if (silc_server_inviteban_match(server, channel->ban_list,
2024 silc_server_inviteban_match(server, channel->ban_list,
2025 2, client->data.public_key) ||
2026 silc_server_inviteban_match(server, channel->ban_list,
2027 1, client->nickname) ||
2028 silc_server_inviteban_match(server, channel->ban_list,
2030 silc_server_inviteban_match(server, channel->ban_list,
2032 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2033 silc_server_command_send_status_data(
2034 cmd, SILC_COMMAND_JOIN,
2035 SILC_STATUS_ERR_BANNED_FROM_CHANNEL, 0,
2036 2, chidp->data, chidp->len);
2037 silc_buffer_free(chidp);
2042 /* Check user count limit if set. */
2043 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
2044 if (silc_hash_table_count(channel->user_list) + 1 >
2045 channel->user_limit) {
2046 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2047 silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
2048 SILC_STATUS_ERR_CHANNEL_IS_FULL,
2049 0, 2, chidp->data, chidp->len);
2050 silc_buffer_free(chidp);
2056 /* Check the channel passphrase if set. */
2057 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2058 /* Get passphrase */
2059 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2061 passphrase = silc_memdup(tmp, tmp_len);
2063 if (!passphrase || !channel->passphrase ||
2064 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
2065 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2066 silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
2067 SILC_STATUS_ERR_BAD_PASSWORD, 0,
2068 2, chidp->data, chidp->len);
2069 silc_buffer_free(chidp);
2074 /* Verify channel authentication with channel public keys if set. */
2075 if (channel->mode & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
2076 if (!silc_server_verify_channel_auth(server, channel, client->id,
2077 cauth, cauth_len)) {
2078 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2079 SILC_STATUS_ERR_PERM_DENIED, 0);
2085 * Client is allowed to join to the channel. Make it happen.
2088 /* Check whether the client already is on the channel */
2089 if (silc_server_client_on_channel(client, channel, NULL)) {
2090 clidp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
2091 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2092 silc_server_command_send_status_data2(cmd, SILC_COMMAND_JOIN,
2093 SILC_STATUS_ERR_USER_ON_CHANNEL, 0,
2094 2, clidp->data, clidp->len,
2095 3, chidp->data, chidp->len);
2096 silc_buffer_free(clidp);
2097 silc_buffer_free(chidp);
2101 /* Generate new channel key as protocol dictates */
2103 if (!silc_server_create_channel_key(server, channel, 0))
2106 /* Send the channel key. This is broadcasted to the channel but is not
2107 sent to the client who is joining to the channel. */
2108 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
2109 silc_server_send_channel_key(server, NULL, channel,
2110 server->server_type == SILC_ROUTER ?
2111 FALSE : !server->standalone);
2114 /* Join the client to the channel by adding it to channel's user list.
2115 Add also the channel to client entry's channels list for fast cross-
2117 chl = silc_calloc(1, sizeof(*chl));
2119 chl->client = client;
2120 chl->channel = channel;
2121 silc_hash_table_add(channel->user_list, client, chl);
2122 silc_hash_table_add(client->channels, channel, chl);
2123 channel->user_count++;
2124 channel->disabled = FALSE;
2126 /* Get users on the channel */
2127 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
2130 /* Encode Client ID Payload of the original client who wants to join */
2131 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2133 /* Encode command reply packet */
2134 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2135 SILC_PUT32_MSB(channel->mode, mode);
2136 SILC_PUT32_MSB(created, tmp2);
2137 SILC_PUT32_MSB(user_count, tmp3);
2138 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2139 SILC_PUT32_MSB(channel->user_limit, ulimit);
2141 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
2142 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
2143 cipher = silc_cipher_get_name(channel->channel_key);
2144 keyp = silc_channel_key_payload_encode(silc_id_get_len(channel->id,
2147 strlen(cipher), cipher,
2148 channel->key_len / 8, channel->key);
2152 if (channel->founder_key)
2153 fkey = silc_pkcs_public_key_payload_encode(channel->founder_key);
2155 /* Encode invite list */
2157 if (channel->invite_list && silc_hash_table_count(channel->invite_list)) {
2158 SilcHashTableList htl;
2160 invite_list = silc_buffer_alloc_size(2);
2161 silc_buffer_format(invite_list,
2162 SILC_STR_UI_SHORT(silc_hash_table_count(
2163 channel->invite_list)),
2166 silc_hash_table_list(channel->invite_list, &htl);
2167 while (silc_hash_table_get(&htl, (void *)&tmp_len, (void *)&reply))
2168 invite_list = silc_argument_payload_encode_one(invite_list,
2170 reply->len, tmp_len);
2171 silc_hash_table_list_reset(&htl);
2174 /* Encode ban list */
2176 if (channel->ban_list && silc_hash_table_count(channel->ban_list)) {
2177 SilcHashTableList htl;
2179 ban_list = silc_buffer_alloc_size(2);
2180 silc_buffer_format(ban_list,
2181 SILC_STR_UI_SHORT(silc_hash_table_count(
2182 channel->ban_list)),
2185 silc_hash_table_list(channel->ban_list, &htl);
2186 while (silc_hash_table_get(&htl, (void *)&tmp_len, (void *)&reply))
2187 ban_list = silc_argument_payload_encode_one(ban_list,
2189 reply->len, tmp_len);
2190 silc_hash_table_list_reset(&htl);
2193 if (channel->channel_pubkeys)
2194 chpklist = silc_server_get_channel_pk_list(server, channel, FALSE, FALSE);
2197 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2198 SILC_STATUS_OK, 0, ident, 16,
2199 2, channel->channel_name,
2200 strlen(channel->channel_name),
2201 3, chidp->data, chidp->len,
2202 4, clidp->data, clidp->len,
2205 7, keyp ? keyp->data : NULL,
2206 keyp ? keyp->len : 0,
2207 8, ban_list ? ban_list->data : NULL,
2208 ban_list ? ban_list->len : 0,
2209 9, invite_list ? invite_list->data :
2211 invite_list ? invite_list->len : 0,
2214 strlen(channel->topic) : 0,
2215 11, silc_hmac_get_name(channel->hmac),
2216 strlen(silc_hmac_get_name(channel->
2219 13, user_list->data, user_list->len,
2220 14, mode_list->data,
2222 15, fkey ? fkey->data : NULL,
2223 fkey ? fkey->len : 0,
2224 16, chpklist ? chpklist->data : NULL,
2225 chpklist ? chpklist->len : 0,
2226 17, (channel->mode &
2227 SILC_CHANNEL_MODE_ULIMIT ?
2230 SILC_CHANNEL_MODE_ULIMIT ?
2231 sizeof(ulimit) : 0));
2233 /* Send command reply */
2234 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
2235 reply->data, reply->len, FALSE);
2237 /* Send JOIN notify to locally connected clients on the channel. If
2238 we are normal server then router will send or have sent JOIN notify
2239 already. However since we've added the client already to our channel
2240 we'll ignore it (in packet_receive.c) so we must send it here. If
2241 we are router then this will send it to local clients and local
2243 SILC_LOG_DEBUG(("Send JOIN notify to channel"));
2244 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
2245 SILC_NOTIFY_TYPE_JOIN, 2,
2246 clidp->data, clidp->len,
2247 chidp->data, chidp->len);
2249 /* Update statistics */
2250 server->stat.my_chanclients++;
2251 if (server->server_type == SILC_ROUTER) {
2252 server->stat.cell_chanclients++;
2253 server->stat.chanclients++;
2256 if (!cmd->pending) {
2257 /* Send JOIN notify packet to our primary router */
2258 silc_server_send_notify_join(server, SILC_PRIMARY_ROUTE(server),
2259 SILC_BROADCAST(server), channel, client->id);
2262 /* Distribute the channel key to all backup routers. */
2263 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
2264 keyp->data, keyp->len, FALSE, TRUE);
2266 /* If client became founder by providing correct founder auth data
2267 notify the mode change to the channel. */
2269 SILC_PUT32_MSB(chl->mode, mode);
2270 SILC_LOG_DEBUG(("Send CUMODE_CHANGE notify to channel"));
2271 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
2272 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
2273 clidp->data, clidp->len,
2274 mode, 4, clidp->data, clidp->len,
2275 fkey ? fkey->data : NULL,
2276 fkey ? fkey->len : 0);
2280 /* Set CUMODE notify type to network */
2282 silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
2283 SILC_BROADCAST(server), channel,
2284 chl->mode, client->id, SILC_ID_CLIENT,
2285 client->id, channel->founder_key);
2287 silc_buffer_free(reply);
2288 silc_buffer_free(clidp);
2289 silc_buffer_free(chidp);
2290 silc_buffer_free(keyp);
2291 silc_buffer_free(user_list);
2292 silc_buffer_free(mode_list);
2293 silc_buffer_free(fkey);
2294 silc_buffer_free(chpklist);
2295 silc_buffer_free(invite_list);
2296 silc_buffer_free(ban_list);
2300 memset(passphrase, 0, strlen(passphrase));
2301 silc_free(passphrase);
2304 /* Server side of command JOIN. Joins client into requested channel. If
2305 the channel does not exist it will be created. */
2307 SILC_SERVER_CMD_FUNC(join)
2309 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2310 SilcServer server = cmd->server;
2311 unsigned char *auth, *cauth;
2312 SilcUInt32 tmp_len, auth_len, cauth_len;
2313 char *tmp, *channel_name = NULL, *cipher, *hmac;
2314 SilcChannelEntry channel;
2315 SilcUInt32 umode = 0;
2316 bool created = FALSE, create_key = TRUE;
2317 SilcClientID *client_id;
2319 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 7);
2321 /* Get channel name */
2322 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2324 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2325 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2332 channel_name[255] = '\0';
2334 if (silc_server_name_bad_chchars(channel_name, tmp_len) == TRUE) {
2335 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2336 SILC_STATUS_ERR_BAD_CHANNEL, 0);
2340 /* Get Client ID of the client who is joining to the channel */
2341 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2343 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2344 SILC_STATUS_ERR_NO_CLIENT_ID,
2348 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2350 silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
2351 SILC_STATUS_ERR_BAD_CLIENT_ID, 0,
2356 /* Get cipher, hmac name and auth payload */
2357 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2358 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2359 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
2360 cauth = silc_argument_get_arg_type(cmd->args, 7, &cauth_len);
2362 /* See if the channel exists */
2363 channel = silc_idlist_find_channel_by_name(server->local_list,
2364 channel_name, NULL);
2366 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2367 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2369 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2370 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2375 silc_free(client_id);
2376 client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
2379 (channel->disabled && server->server_type != SILC_ROUTER)) {
2380 /* Channel not found or not valid */
2382 /* If we are standalone server we don't have a router, we just create
2383 the channel by ourselves (unless it existed). */
2384 if (server->standalone) {
2386 channel = silc_server_create_new_channel(server, server->id, cipher,
2387 hmac, channel_name, TRUE);
2389 silc_server_command_send_status_data(
2390 cmd, SILC_COMMAND_JOIN,
2391 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
2392 0, 2, cipher, strlen(cipher));
2393 silc_free(client_id);
2397 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2403 /* The channel does not exist on our server. If we are normal server
2404 we will send JOIN command to our router which will handle the
2405 joining procedure (either creates the channel if it doesn't exist
2406 or joins the client to it). */
2407 if (server->server_type != SILC_ROUTER) {
2409 SilcUInt16 old_ident;
2411 /* If this is pending command callback then we've resolved
2412 it and it didn't work, return since we've notified the
2413 client already in the command reply callback. */
2415 silc_free(client_id);
2419 old_ident = silc_command_get_ident(cmd->payload);
2420 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2421 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2423 /* Send JOIN command to our router */
2424 silc_server_packet_send(server, (SilcSocketConnection)
2425 SILC_PRIMARY_ROUTE(server),
2426 SILC_PACKET_COMMAND, cmd->packet->flags,
2427 tmpbuf->data, tmpbuf->len, TRUE);
2429 /* Reprocess this packet after received reply from router */
2430 silc_server_command_pending(server, SILC_COMMAND_JOIN,
2431 silc_command_get_ident(cmd->payload),
2432 silc_server_command_join,
2433 silc_server_command_dup(cmd));
2434 cmd->pending = TRUE;
2435 silc_command_set_ident(cmd->payload, old_ident);
2436 silc_buffer_free(tmpbuf);
2437 silc_free(client_id);
2441 /* We are router and the channel does not seem exist so we will check
2442 our global list as well for the channel. */
2443 channel = silc_idlist_find_channel_by_name(server->global_list,
2444 channel_name, NULL);
2446 /* Channel really does not exist, create it */
2447 channel = silc_server_create_new_channel(server, server->id, cipher,
2448 hmac, channel_name, TRUE);
2450 silc_server_command_send_status_data(
2451 cmd, SILC_COMMAND_JOIN,
2452 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
2453 2, cipher, strlen(cipher));
2454 silc_free(client_id);
2458 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2466 /* Channel not found */
2468 /* If the command came from router and we are normal server then
2469 something went wrong with the joining as the channel was not found.
2470 We can't do anything else but ignore this. */
2471 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
2472 server->server_type != SILC_ROUTER) {
2473 silc_free(client_id);
2477 /* We are router and the channel does not seem exist so we will check
2478 our global list as well for the channel. */
2479 channel = silc_idlist_find_channel_by_name(server->global_list,
2480 channel_name, NULL);
2482 /* Channel really does not exist, create it */
2483 channel = silc_server_create_new_channel(server, server->id, cipher,
2484 hmac, channel_name, TRUE);
2486 silc_server_command_send_status_data(
2487 cmd, SILC_COMMAND_JOIN,
2488 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
2489 2, cipher, strlen(cipher));
2490 silc_free(client_id);
2494 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2501 /* Check whether the channel was created by our router */
2502 if (cmd->pending && context2) {
2503 SilcServerCommandReplyContext reply = context2;
2505 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
2506 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
2507 SILC_GET32_MSB(created, tmp);
2508 if (silc_argument_get_arg_type(reply->args, 7, NULL))
2509 create_key = FALSE; /* Router returned the key already */
2511 if (silc_command_get_status(reply->payload, NULL, NULL) &&
2512 channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2513 /* Save channel passphrase, if user provided it successfully */
2516 pa = silc_argument_get_arg_type(cmd->args, 3, &pa_len);
2518 silc_free(channel->passphrase);
2519 channel->passphrase = silc_memdup(pa, pa_len);
2524 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
2525 !channel->disabled && !silc_hash_table_count(channel->user_list))
2529 /* If the channel does not have global users and is also empty the client
2530 will be the channel founder and operator. */
2531 if (!channel->disabled &&
2532 !channel->global_users && !silc_hash_table_count(channel->user_list))
2533 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2535 /* Join to the channel */
2536 silc_server_command_join_channel(server, cmd, channel, client_id,
2537 created, create_key, umode,
2538 auth, auth_len, cauth, cauth_len);
2540 silc_free(client_id);
2543 silc_server_command_free(cmd);
2546 /* Server side of command MOTD. Sends server's current "message of the
2547 day" to the client. */
2549 SILC_SERVER_CMD_FUNC(motd)
2551 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2552 SilcServer server = cmd->server;
2553 SilcBuffer packet, idp;
2554 char *motd, *dest_server;
2555 SilcUInt32 motd_len;
2556 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2558 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
2560 /* Get server name */
2561 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2563 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2564 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2569 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
2572 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
2574 if (server->config && server->config->server_info &&
2575 server->config->server_info->motd_file) {
2577 motd = silc_file_readfile(server->config->server_info->motd_file,
2583 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
2586 2, idp->data, idp->len,
2590 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
2593 2, idp->data, idp->len);
2596 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2597 packet->data, packet->len, FALSE);
2598 silc_buffer_free(packet);
2599 silc_buffer_free(idp);
2601 SilcServerEntry entry;
2603 /* Check whether we have this server cached */
2604 entry = silc_idlist_find_server_by_name(server->global_list,
2605 dest_server, TRUE, NULL);
2607 entry = silc_idlist_find_server_by_name(server->local_list,
2608 dest_server, TRUE, NULL);
2611 if (server->server_type != SILC_SERVER && !cmd->pending &&
2612 entry && !entry->motd) {
2613 /* Send to the server */
2615 SilcUInt16 old_ident;
2617 old_ident = silc_command_get_ident(cmd->payload);
2618 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2619 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2621 silc_server_packet_send(server, entry->connection,
2622 SILC_PACKET_COMMAND, cmd->packet->flags,
2623 tmpbuf->data, tmpbuf->len, TRUE);
2625 /* Reprocess this packet after received reply from router */
2626 silc_server_command_pending(server, SILC_COMMAND_MOTD,
2627 silc_command_get_ident(cmd->payload),
2628 silc_server_command_motd,
2629 silc_server_command_dup(cmd));
2630 cmd->pending = TRUE;
2631 silc_command_set_ident(cmd->payload, old_ident);
2632 silc_buffer_free(tmpbuf);
2636 /* Send to primary router only if we don't know the server
2637 * the client requested or if the server is not locally connected */
2638 if ((!entry || !(entry->data.status & SILC_IDLIST_STATUS_LOCAL))
2639 && !cmd->pending && !server->standalone) {
2640 /* Send to the primary router */
2642 SilcUInt16 old_ident;
2644 old_ident = silc_command_get_ident(cmd->payload);
2645 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2646 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2648 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
2649 SILC_PACKET_COMMAND, cmd->packet->flags,
2650 tmpbuf->data, tmpbuf->len, TRUE);
2652 /* Reprocess this packet after received reply from router */
2653 silc_server_command_pending(server, SILC_COMMAND_MOTD,
2654 silc_command_get_ident(cmd->payload),
2655 silc_server_command_motd,
2656 silc_server_command_dup(cmd));
2657 cmd->pending = TRUE;
2658 silc_command_set_ident(cmd->payload, old_ident);
2659 silc_buffer_free(tmpbuf);
2664 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2665 SILC_STATUS_ERR_NO_SUCH_SERVER, 0,
2667 strlen(dest_server));
2671 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2672 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
2673 SILC_STATUS_OK, 0, ident, 2,
2674 2, idp->data, idp->len,
2677 strlen(entry->motd) : 0);
2678 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2679 packet->data, packet->len, FALSE);
2680 silc_buffer_free(packet);
2681 silc_buffer_free(idp);
2685 silc_server_command_free(cmd);
2688 /* Server side of command UMODE. Client can use this command to set/unset
2689 user mode. Client actually cannot set itself to be as server/router
2690 operator so this can be used only to unset the modes. */
2692 SILC_SERVER_CMD_FUNC(umode)
2694 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2695 SilcServer server = cmd->server;
2696 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2698 unsigned char *tmp_mask, m[4];
2699 SilcUInt32 mask = 0;
2700 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2701 bool set_mask = FALSE;
2703 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
2706 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2);
2708 /* Get the client's mode mask */
2709 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2711 SILC_GET32_MSB(mask, tmp_mask);
2716 /* Check that mode changing is allowed. */
2717 if (!silc_server_check_umode_rights(server, client, mask)) {
2718 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2719 SILC_STATUS_ERR_PERM_DENIED, 0);
2723 /* Anonymous mode cannot be set by client */
2724 if (mask & SILC_UMODE_ANONYMOUS &&
2725 !(client->mode & SILC_UMODE_ANONYMOUS)) {
2726 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2727 SILC_STATUS_ERR_PERM_DENIED, 0);
2731 /* Update statistics */
2732 if (mask & SILC_UMODE_GONE) {
2733 if (!(client->mode & SILC_UMODE_GONE))
2734 server->stat.my_aways++;
2736 if (client->mode & SILC_UMODE_GONE)
2737 server->stat.my_aways--;
2740 /* If the client has anonymous mode set, preserve it. */
2741 if (client->mode & SILC_UMODE_ANONYMOUS)
2742 mask |= SILC_UMODE_ANONYMOUS;
2744 /* Change the mode */
2745 client->mode = mask;
2747 /* Send UMODE change to primary router */
2748 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
2749 SILC_BROADCAST(server), client->id,
2752 /* Check if anyone is watching this nickname */
2753 if (server->server_type == SILC_ROUTER)
2754 silc_server_check_watcher_list(server, client, NULL,
2755 SILC_NOTIFY_TYPE_UMODE_CHANGE);
2758 /* Send command reply to sender */
2759 SILC_PUT32_MSB(client->mode, m);
2760 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
2761 SILC_STATUS_OK, 0, ident, 1,
2763 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2764 packet->data, packet->len, FALSE);
2765 silc_buffer_free(packet);
2768 silc_server_command_free(cmd);
2771 /* Server side command of CMODE. Changes channel mode */
2773 SILC_SERVER_CMD_FUNC(cmode)
2775 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2776 SilcServer server = cmd->server;
2777 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2778 SilcIDListData idata = (SilcIDListData)client;
2779 SilcChannelID *channel_id = NULL;
2780 SilcChannelEntry channel;
2781 SilcChannelClientEntry chl;
2782 SilcBuffer packet, cidp;
2783 unsigned char *tmp, *tmp_id, *tmp_mask, *chpkdata = NULL;
2784 char *cipher = NULL, *hmac = NULL, *passphrase = NULL, ulimit[4];
2785 SilcUInt32 mode_mask = 0, old_mask = 0, tmp_len, tmp_len2, chpklen;
2786 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2787 bool set_mask = FALSE, set_chpk = FALSE;
2788 SilcPublicKey founder_key = NULL;
2789 SilcBuffer fkey = NULL, chpklist = NULL;
2790 SilcBufferStruct chpk;
2793 silc_server_command_free(cmd);
2797 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 9);
2799 /* Get Channel ID */
2800 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2802 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2803 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2804 silc_server_command_free(cmd);
2807 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
2809 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2810 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2811 silc_server_command_free(cmd);
2815 /* Get channel entry */
2816 channel = silc_idlist_find_channel_by_id(server->local_list,
2819 channel = silc_idlist_find_channel_by_id(server->global_list,
2822 silc_server_command_send_status_data(cmd, SILC_COMMAND_CMODE,
2823 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
2824 0, 2, tmp_id, tmp_len2);
2825 silc_free(channel_id);
2826 silc_server_command_free(cmd);
2830 old_mask = channel->mode;
2832 /* Get the channel mode mask */
2833 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2835 SILC_GET32_MSB(mode_mask, tmp_mask);
2839 /* Check whether this client is on the channel */
2840 if (!silc_server_client_on_channel(client, channel, &chl)) {
2841 silc_server_command_send_status_data(cmd, SILC_COMMAND_CMODE,
2842 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
2843 2, tmp_id, tmp_len2);
2847 /* Check that client has rights to change any requested channel modes */
2848 if (set_mask && !silc_server_check_cmode_rights(server, channel, chl,
2850 SILC_LOG_DEBUG(("Client does not have rights to change mode"));
2851 silc_server_command_send_status_data(
2852 cmd, SILC_COMMAND_CMODE,
2853 (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) ?
2854 SILC_STATUS_ERR_NO_CHANNEL_PRIV :
2855 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV), 0,
2856 2, tmp_id, tmp_len2);
2860 /* If mode mask was not sent as argument then merely return the current
2861 mode mask, founder key and channel public key list to the sender. */
2864 SILC_PUT32_MSB(channel->mode, m);
2865 if (channel->founder_key)
2866 fkey = silc_pkcs_public_key_payload_encode(channel->founder_key);
2867 if (channel->channel_pubkeys)
2868 chpklist = silc_server_get_channel_pk_list(server, channel,
2871 silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2872 SILC_STATUS_OK, 0, ident, 4,
2873 2, tmp_id, tmp_len2,
2875 4, fkey ? fkey->data : NULL,
2876 fkey ? fkey->len : 0,
2877 5, chpklist ? chpklist->data : NULL,
2878 chpklist ? chpklist->len : 0);
2879 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2880 packet->data, packet->len, FALSE);
2881 silc_buffer_free(packet);
2886 * Check the modes. Modes that requires nothing special operation are
2890 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2891 /* Channel uses private keys to protect traffic. Client(s) has set the
2892 key locally they want to use, server does not know that key. */
2893 /* Nothing interesting to do here */
2895 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2896 /* The mode is removed and we need to generate and distribute
2897 new channel key. Clients are not using private channel keys
2898 anymore after this. */
2900 /* Re-generate channel key */
2901 if (!silc_server_create_channel_key(server, channel, 0))
2904 /* Send the channel key. This sends it to our local clients and if
2905 we are normal server to our router as well. */
2906 silc_server_send_channel_key(server, NULL, channel,
2907 server->server_type == SILC_ROUTER ?
2908 FALSE : !server->standalone);
2910 cipher = (char *)silc_cipher_get_name(channel->channel_key);
2911 hmac = (char *)silc_hmac_get_name(channel->hmac);
2915 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2916 /* User limit is set on channel */
2917 SilcUInt32 user_limit;
2919 /* Get user limit */
2920 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2922 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2923 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2924 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
2928 SILC_GET32_MSB(user_limit, tmp);
2929 channel->user_limit = user_limit;
2932 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2933 /* User limit mode is unset. Remove user limit */
2934 channel->user_limit = 0;
2937 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
2938 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
2939 /* Passphrase has been set to channel */
2941 /* Get the passphrase */
2942 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
2944 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2945 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
2949 /* Save the passphrase */
2950 passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
2953 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2954 /* Passphrase mode is unset. remove the passphrase */
2955 silc_free(channel->passphrase);
2956 channel->passphrase = NULL;
2960 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
2961 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
2962 /* Cipher to use protect the traffic */
2963 SilcCipher newkey, oldkey;
2966 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
2968 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2969 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
2973 /* Delete old cipher and allocate the new one */
2974 if (!silc_cipher_alloc(cipher, &newkey)) {
2975 silc_server_command_send_status_data(
2976 cmd, SILC_COMMAND_CMODE,
2977 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
2978 2, cipher, strlen(cipher));
2982 oldkey = channel->channel_key;
2983 channel->channel_key = newkey;
2985 /* Re-generate channel key */
2986 if (!silc_server_create_channel_key(server, channel, 0)) {
2987 /* We don't have new key, revert to old one */
2988 channel->channel_key = oldkey;
2992 /* Remove old channel key for good */
2993 silc_cipher_free(oldkey);
2995 /* Send the channel key. This sends it to our local clients and if
2996 we are normal server to our router as well. */
2997 silc_server_send_channel_key(server, NULL, channel,
2998 server->server_type == SILC_ROUTER ?
2999 FALSE : !server->standalone);
3002 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3003 /* Cipher mode is unset. Remove the cipher and revert back to
3005 SilcCipher newkey, oldkey;
3006 cipher = channel->cipher;
3008 /* Delete old cipher and allocate default one */
3009 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
3010 silc_server_command_send_status_data(
3011 cmd, SILC_COMMAND_CMODE,
3012 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
3013 2, cipher, strlen(cipher));
3017 oldkey = channel->channel_key;
3018 channel->channel_key = newkey;
3020 /* Re-generate channel key */
3021 if (!silc_server_create_channel_key(server, channel, 0)) {
3022 /* We don't have new key, revert to old one */
3023 channel->channel_key = oldkey;
3027 /* Remove old channel key for good */
3028 silc_cipher_free(oldkey);
3030 /* Send the channel key. This sends it to our local clients and if
3031 we are normal server to our router as well. */
3032 silc_server_send_channel_key(server, NULL, channel,
3033 server->server_type == SILC_ROUTER ?
3034 FALSE : !server->standalone);
3038 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3039 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3040 /* HMAC to use protect the traffic */
3041 unsigned char hash[32];
3045 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3047 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3048 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3052 /* Delete old hmac and allocate the new one */
3053 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
3054 silc_server_command_send_status_data(
3055 cmd, SILC_COMMAND_CMODE,
3056 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
3057 2, hmac, strlen(hmac));
3061 silc_hmac_free(channel->hmac);
3062 channel->hmac = newhmac;
3064 /* Set the HMAC key out of current channel key. The client must do
3066 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
3067 channel->key_len / 8, hash);
3068 silc_hmac_set_key(channel->hmac, hash,
3069 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3070 memset(hash, 0, sizeof(hash));
3073 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
3074 /* Hmac mode is unset. Remove the hmac and revert back to
3077 unsigned char hash[32];
3078 hmac = channel->hmac_name;
3080 /* Delete old hmac and allocate default one */
3081 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
3082 silc_server_command_send_status_data(
3083 cmd, SILC_COMMAND_CMODE,
3084 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
3085 2, hmac, strlen(hmac));
3089 silc_hmac_free(channel->hmac);
3090 channel->hmac = newhmac;
3092 /* Set the HMAC key out of current channel key. The client must do
3094 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
3095 channel->key_len / 8,
3097 silc_hmac_set_key(channel->hmac, hash,
3098 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3099 memset(hash, 0, sizeof(hash));
3103 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3104 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3105 /* Check if the founder public key was received */
3106 founder_key = idata->public_key;
3107 tmp = silc_argument_get_arg_type(cmd->args, 8, &tmp_len);
3109 if (!silc_pkcs_public_key_payload_decode(tmp, tmp_len, &founder_key)) {
3110 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3111 SILC_STATUS_ERR_AUTH_FAILED,
3116 /* If key was not sent and the channel mode has already founder
3117 then the key was not to be changed. */
3118 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)
3122 /* Set the founder authentication */
3123 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
3125 silc_server_command_send_status_reply(
3126 cmd, SILC_COMMAND_CMODE,
3127 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3131 /* Verify the payload before setting the mode */
3132 if (!silc_auth_verify_data(tmp, tmp_len, SILC_AUTH_PUBLIC_KEY,
3133 founder_key, 0, server->sha1hash,
3134 client->id, SILC_ID_CLIENT)) {
3135 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3136 SILC_STATUS_ERR_AUTH_FAILED,
3141 /* Save the public key */
3142 if (channel->founder_key)
3143 silc_pkcs_public_key_free(channel->founder_key);
3144 if (silc_argument_get_arg_type(cmd->args, 8, NULL))
3145 channel->founder_key = founder_key;
3147 channel->founder_key = silc_pkcs_public_key_copy(founder_key);
3148 if (!channel->founder_key) {
3149 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3150 SILC_STATUS_ERR_AUTH_FAILED,
3155 fkey = silc_pkcs_public_key_payload_encode(channel->founder_key);
3157 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3158 SILC_STATUS_ERR_AUTH_FAILED,
3160 silc_pkcs_public_key_free(channel->founder_key);
3161 channel->founder_key = NULL;
3166 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3167 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3168 if (channel->founder_key)
3169 silc_pkcs_public_key_free(channel->founder_key);
3170 channel->founder_key = NULL;
3176 if (mode_mask & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
3177 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3180 chpkdata = silc_argument_get_arg_type(cmd->args, 9, &chpklen);
3182 if (!chpkdata && channel->mode & SILC_CHANNEL_MODE_CHANNEL_AUTH)
3187 /* Process the channel public key(s) */
3188 st = silc_server_set_channel_pk_list(server, NULL, channel,
3190 if (st != SILC_STATUS_OK) {
3191 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE, st, 0);
3196 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3197 if (channel->mode & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
3198 if (channel->channel_pubkeys)
3199 silc_hash_table_free(channel->channel_pubkeys);
3200 channel->channel_pubkeys = NULL;
3207 /* Finally, set the mode */
3208 old_mask = channel->mode = mode_mask;
3210 /* Send CMODE_CHANGE notify. */
3211 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3212 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT)
3213 SILC_PUT32_MSB(channel->user_limit, ulimit);
3214 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
3215 SILC_NOTIFY_TYPE_CMODE_CHANGE, 8,
3216 cidp->data, cidp->len,
3218 cipher, cipher ? strlen(cipher) : 0,
3219 hmac, hmac ? strlen(hmac) : 0,
3220 passphrase, passphrase ?
3221 strlen(passphrase) : 0,
3222 fkey ? fkey->data : NULL,
3223 fkey ? fkey->len : 0,
3224 chpkdata ? chpkdata : NULL,
3225 chpkdata ? chpklen : 0,
3226 mode_mask & SILC_CHANNEL_MODE_ULIMIT ?
3228 mode_mask & SILC_CHANNEL_MODE_ULIMIT ?
3229 sizeof(ulimit) : 0);
3231 /* Set CMODE notify type to network */
3232 if (chpkdata && chpklen)
3233 silc_buffer_set(&chpk, chpkdata, chpklen);
3234 silc_server_send_notify_cmode(server, SILC_PRIMARY_ROUTE(server),
3235 SILC_BROADCAST(server), channel,
3236 mode_mask, client->id, SILC_ID_CLIENT,
3237 cipher, hmac, passphrase, founder_key,
3238 chpkdata ? &chpk : NULL);
3241 chpklist = silc_server_get_channel_pk_list(server, channel, FALSE, FALSE);
3243 /* Send command reply to sender */
3244 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3245 SILC_STATUS_OK, 0, ident, 5,
3246 2, tmp_id, tmp_len2,
3248 4, fkey ? fkey->data : NULL,
3249 fkey ? fkey->len : 0,
3250 5, chpklist ? chpklist->data :
3251 NULL, chpklist ? chpklist->len
3254 SILC_CHANNEL_MODE_ULIMIT ?
3257 SILC_CHANNEL_MODE_ULIMIT ?
3258 sizeof(ulimit) : 0));
3260 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3261 packet->data, packet->len, FALSE);
3263 silc_buffer_free(packet);
3264 silc_buffer_free(cidp);
3267 channel->mode = old_mask;
3268 silc_buffer_free(chpklist);
3269 silc_buffer_free(fkey);
3270 silc_free(channel_id);
3271 silc_server_command_free(cmd);
3274 /* Server side of CUMODE command. Changes client's mode on a channel. */
3276 SILC_SERVER_CMD_FUNC(cumode)
3278 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3279 SilcServer server = cmd->server;
3280 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3281 SilcChannelID *channel_id = NULL;
3282 SilcClientID *client_id = NULL;
3283 SilcChannelEntry channel;
3284 SilcClientEntry target_client;
3285 SilcChannelClientEntry chl;
3286 SilcBuffer packet, idp;
3287 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
3288 SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
3290 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3291 SilcPublicKey founder_key = NULL;
3292 SilcBuffer fkey = NULL;
3297 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
3299 /* Get Channel ID */
3300 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3302 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3303 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3306 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
3308 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3309 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3313 /* Get channel entry */
3314 channel = silc_idlist_find_channel_by_id(server->local_list,
3317 channel = silc_idlist_find_channel_by_id(server->global_list,
3320 silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3321 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
3322 0, 2, tmp_ch_id, tmp_ch_len);
3327 /* Check whether sender is on the channel */
3328 if (!silc_server_client_on_channel(client, channel, &chl)) {
3329 silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3330 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
3331 2, tmp_ch_id, tmp_ch_len);
3334 sender_mask = chl->mode;
3336 /* Get the target client's channel mode mask */
3337 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3339 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3340 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3344 SILC_GET32_MSB(target_mask, tmp_mask);
3346 /* Get target Client ID */
3347 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3349 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3350 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
3353 client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
3355 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3356 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
3360 /* Get target client's entry */
3361 target_client = silc_idlist_find_client_by_id(server->local_list,
3362 client_id, TRUE, NULL);
3364 target_client = silc_idlist_find_client_by_id(server->global_list,
3365 client_id, TRUE, NULL);
3367 if (target_client != client &&
3368 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
3369 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
3370 silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3371 SILC_STATUS_ERR_NOT_YOU, 0,
3372 2, tmp_ch_id, tmp_ch_len);
3376 /* Check whether target client is on the channel */
3377 if (target_client != client) {
3378 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
3379 silc_server_command_send_status_data2(
3380 cmd, SILC_COMMAND_CUMODE,
3381 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL, 0,
3383 3, tmp_ch_id, tmp_ch_len);
3392 /* If the target client is founder, no one else can change their mode
3394 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
3395 silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3396 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
3397 0, 2, tmp_ch_id, tmp_ch_len);
3401 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
3402 if (target_client != client) {
3403 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3404 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
3409 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
3410 /* The client tries to claim the founder rights. */
3411 unsigned char *tmp_auth;
3412 SilcUInt32 tmp_auth_len;
3413 SilcChannelClientEntry chl2;
3414 SilcHashTableList htl;
3416 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
3417 !channel->founder_key) {
3418 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3419 SILC_STATUS_ERR_AUTH_FAILED, 0);
3423 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
3425 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3426 SILC_STATUS_ERR_AUTH_FAILED, 0);
3430 /* Verify the authentication payload */
3431 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len, SILC_AUTH_PUBLIC_KEY,
3432 channel->founder_key, 0, server->sha1hash,
3433 client->id, SILC_ID_CLIENT)) {
3434 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3435 SILC_STATUS_ERR_AUTH_FAILED, 0);
3440 founder_key = channel->founder_key;
3441 fkey = silc_pkcs_public_key_payload_encode(founder_key);
3443 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3444 SILC_STATUS_ERR_AUTH_FAILED, 0);
3448 /* There cannot be anyone else as founder on the channel now. This
3449 client is definitely the founder due to this authentication. This
3450 is done only on router, not on server, since server cannot know
3451 whether router will accept this mode change or not. XXX This
3452 probably shouldn't be done anymore at all, may cause problems in
3453 router-router connections too (maybe just AUTH_FAILED error should
3454 be returned). -Pekka */
3455 if (server->server_type == SILC_ROUTER) {
3456 silc_hash_table_list(channel->user_list, &htl);
3457 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
3458 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
3459 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3460 silc_server_force_cumode_change(server, NULL, channel, chl2,
3464 silc_hash_table_list_reset(&htl);
3467 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
3470 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3471 if (target_client == client) {
3472 /* Remove channel founder rights from itself */
3473 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3476 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3477 SILC_STATUS_ERR_NOT_YOU, 0);
3483 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
3484 /* Promote to operator */
3485 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3486 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3487 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3488 silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3489 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
3490 0, 2, tmp_ch_id, tmp_ch_len);
3494 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
3498 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
3499 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3500 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3501 silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3502 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
3503 0, 2, tmp_ch_id, tmp_ch_len);
3507 /* Demote to normal user */
3508 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
3513 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
3514 if (target_client != client) {
3515 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3516 SILC_STATUS_ERR_NOT_YOU, 0);
3520 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
3521 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
3525 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
3526 if (target_client != client) {
3527 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3528 SILC_STATUS_ERR_NOT_YOU, 0);
3532 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
3537 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
3538 if (target_client != client) {
3539 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3540 SILC_STATUS_ERR_NOT_YOU, 0);
3544 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)) {
3545 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
3549 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
3550 if (target_client != client) {
3551 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3552 SILC_STATUS_ERR_NOT_YOU, 0);
3556 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
3561 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
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_ROBOTS)) {
3569 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
3573 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
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_ROBOTS;
3585 if (target_mask & SILC_CHANNEL_UMODE_QUIET) {
3586 if (!(chl->mode & SILC_CHANNEL_UMODE_QUIET)) {
3587 if (client == target_client) {
3588 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3589 SILC_STATUS_ERR_PERM_DENIED, 0);
3592 chl->mode |= SILC_CHANNEL_UMODE_QUIET;
3596 if (chl->mode & SILC_CHANNEL_UMODE_QUIET) {
3597 if (client == target_client) {
3598 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3599 SILC_STATUS_ERR_PERM_DENIED, 0);
3602 chl->mode &= ~SILC_CHANNEL_UMODE_QUIET;
3607 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3608 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3610 /* Send notify to channel, notify only if mode was actually changed. */
3612 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
3613 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
3614 idp->data, idp->len,
3617 fkey ? fkey->data : NULL,
3618 fkey ? fkey->len : 0);
3620 /* Set CUMODE notify type to network */
3621 silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
3622 SILC_BROADCAST(server), channel,
3623 target_mask, client->id, SILC_ID_CLIENT,
3624 target_client->id, founder_key);
3627 /* Send command reply to sender */
3628 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
3629 SILC_STATUS_OK, 0, ident, 3,
3631 3, tmp_ch_id, tmp_ch_len,
3632 4, tmp_id, tmp_len);
3633 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3634 packet->data, packet->len, FALSE);
3636 silc_buffer_free(packet);
3637 silc_buffer_free(idp);
3640 silc_free(channel_id);
3641 silc_free(client_id);
3642 silc_buffer_free(fkey);
3643 silc_server_command_free(cmd);
3646 /* Server side of KICK command. Kicks client out of channel. */
3648 SILC_SERVER_CMD_FUNC(kick)
3650 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3651 SilcServer server = cmd->server;
3652 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3653 SilcClientEntry target_client;
3654 SilcChannelID *channel_id;
3655 SilcClientID *client_id;
3656 SilcChannelEntry channel;
3657 SilcChannelClientEntry chl;
3658 SilcBuffer idp, packet;
3659 SilcUInt32 tmp_len, target_idp_len, clen;
3660 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3661 unsigned char *tmp, *comment, *target_idp;
3666 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
3668 /* Get Channel ID */
3669 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3671 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3672 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3675 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3677 silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3678 SILC_STATUS_ERR_BAD_CHANNEL_ID, 0,
3683 /* Get channel entry */
3684 channel = silc_idlist_find_channel_by_id(server->local_list,
3687 channel = silc_idlist_find_channel_by_id(server->local_list,
3690 silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3691 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
3692 0, 2, tmp, tmp_len);
3697 /* Check whether sender is on the channel */
3698 if (!silc_server_client_on_channel(client, channel, &chl)) {
3699 silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3700 SILC_STATUS_ERR_NOT_ON_CHANNEL,
3701 0, 2, tmp, tmp_len);
3705 /* Check that the kicker is channel operator or channel founder */
3706 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
3707 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
3708 silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3709 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
3710 0, 2, tmp, tmp_len);
3714 /* Get target Client ID */
3715 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
3717 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3718 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
3721 client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
3723 silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3724 SILC_STATUS_ERR_BAD_CLIENT_ID,
3725 0, 2, target_idp, target_idp_len);
3729 /* Get target client's entry */
3730 target_client = silc_idlist_find_client_by_id(server->local_list,
3731 client_id, TRUE, NULL);
3732 if (!target_client) {
3733 target_client = silc_idlist_find_client_by_id(server->global_list,
3734 client_id, TRUE, NULL);
3737 /* Check whether target client is on the channel */
3738 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
3739 silc_server_command_send_status_data2(cmd, SILC_COMMAND_KICK,
3740 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL,
3741 0, 2, target_idp, target_idp_len,
3746 /* Check that the target client is not channel founder. Channel founder
3747 cannot be kicked from the channel. */
3748 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3749 silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3750 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
3751 0, 2, tmp, tmp_len);
3756 comment = silc_argument_get_arg_type(cmd->args, 3, &clen);
3761 /* Send the reply back to the client */
3763 silc_command_reply_payload_encode_va(SILC_COMMAND_KICK,
3764 SILC_STATUS_OK, 0, ident, 2,
3766 3, target_idp, target_idp_len);
3767 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3768 packet->data, packet->len, FALSE);
3769 silc_buffer_free(packet);
3771 /* Send KICKED notify to local clients on the channel */
3772 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3773 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
3774 SILC_NOTIFY_TYPE_KICKED, 3,
3775 target_idp, target_idp_len,
3776 comment, comment ? strlen(comment) : 0,
3777 idp->data, idp->len);
3778 silc_buffer_free(idp);
3780 /* Send KICKED notify to primary route */
3781 silc_server_send_notify_kicked(server, SILC_PRIMARY_ROUTE(server),
3782 SILC_BROADCAST(server), channel,
3783 target_client->id, client->id, comment);
3785 /* Remove the client from channel's invite list */
3786 if (channel->invite_list && silc_hash_table_count(channel->invite_list)) {
3788 silc_argument_payload_encode_one(NULL, target_idp, target_idp_len, 3);
3789 SilcArgumentPayload args =
3790 silc_argument_payload_parse(ab->data, ab->len, 1);
3791 silc_server_inviteban_process(server, channel->invite_list, 1, args);
3792 silc_buffer_free(ab);
3793 silc_argument_payload_free(args);
3796 /* Remove the client from the channel. If the channel does not exist
3797 after removing the client then the client kicked itself off the channel
3798 and we don't have to send anything after that. */
3799 if (!silc_server_remove_from_one_channel(server, NULL, channel,
3800 target_client, FALSE))
3803 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3804 /* Re-generate channel key */
3805 if (!silc_server_create_channel_key(server, channel, 0))
3808 /* Send the channel key to the channel. The key of course is not sent
3809 to the client who was kicked off the channel. */
3810 silc_server_send_channel_key(server, target_client->connection, channel,
3811 server->server_type == SILC_ROUTER ?
3812 FALSE : !server->standalone);
3816 silc_server_command_free(cmd);
3819 /* Server side of OPER command. Client uses this comand to obtain server
3820 operator privileges to this server/router. */
3822 SILC_SERVER_CMD_FUNC(oper)
3824 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3825 SilcServer server = cmd->server;
3826 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3827 unsigned char *username, *auth;
3829 SilcServerConfigAdmin *admin;
3830 SilcIDListData idata = (SilcIDListData)client;
3831 bool result = FALSE;
3832 SilcPublicKey cached_key;
3834 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
3837 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
3839 /* Get the username */
3840 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3842 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3843 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3848 /* Get the admin configuration */
3849 admin = silc_server_config_find_admin(server, cmd->sock->ip,
3850 username, client->nickname);
3852 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
3853 username, client->nickname);
3855 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3856 SILC_STATUS_ERR_AUTH_FAILED,
3858 SILC_LOG_INFO(("OPER authentication failed for username '%s' by "
3859 "nickname '%s' from %s", username,
3860 client->nickname, cmd->sock->hostname));
3865 /* Get the authentication payload */
3866 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3868 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3869 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3874 /* Verify the authentication data. If both passphrase and public key
3875 is set then try both of them. */
3876 if (admin->passphrase)
3877 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
3878 admin->passphrase, admin->passphrase_len,
3879 idata->hash, client->id, SILC_ID_CLIENT);
3880 if (!result && admin->publickeys) {
3881 cached_key = silc_server_get_public_key(server, admin->publickeys);
3884 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
3885 cached_key, 0, idata->hash,
3886 client->id, SILC_ID_CLIENT);
3889 /* Authentication failed */
3890 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3891 SILC_STATUS_ERR_AUTH_FAILED,
3896 /* Client is now server operator */
3897 client->mode |= SILC_UMODE_SERVER_OPERATOR;
3899 /* Update statistics */
3900 if (SILC_IS_LOCAL(client))
3901 server->stat.my_server_ops++;
3902 if (server->server_type == SILC_ROUTER)
3903 server->stat.server_ops++;
3905 /* Send UMODE change to primary router */
3906 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
3907 SILC_BROADCAST(server), client->id,
3910 /* Check if anyone is watching this nickname */
3911 if (server->server_type == SILC_ROUTER)
3912 silc_server_check_watcher_list(server, client, NULL,
3913 SILC_NOTIFY_TYPE_UMODE_CHANGE);
3915 /* Send reply to the sender */
3916 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3920 silc_server_command_free(cmd);
3923 SILC_TASK_CALLBACK(silc_server_command_detach_cb)
3925 SilcServer server = app_context;
3926 QuitInternal q = (QuitInternal)context;
3927 SilcClientID *client_id = (SilcClientID *)q->sock;
3928 SilcClientEntry client;
3929 SilcSocketConnection sock;
3931 client = silc_idlist_find_client_by_id(server->local_list, client_id,
3933 if (client && client->connection) {
3934 sock = client->connection;
3936 /* If there is pending outgoing data for the client then purge it
3937 to the network before closing connection. */
3938 silc_server_packet_queue_purge(server, sock);
3940 /* Close the connection on our side */
3941 client->router = NULL;
3942 client->connection = NULL;
3943 sock->user_data = NULL;
3944 silc_server_close_connection(server, sock);
3947 silc_free(client_id);
3951 SILC_TASK_CALLBACK(silc_server_command_detach_timeout)
3953 SilcServer server = app_context;
3954 QuitInternal q = (QuitInternal)context;
3955 SilcClientID *client_id = (SilcClientID *)q->sock;
3956 SilcClientEntry client;
3958 client = silc_idlist_find_client_by_id(server->local_list, client_id,
3960 if (client && client->mode & SILC_UMODE_DETACHED) {
3961 SILC_LOG_DEBUG(("Detach timeout"));
3962 silc_server_free_client_data(server, NULL, client, TRUE,
3966 silc_free(client_id);
3970 /* Server side of DETACH command. Detached the client from the network
3971 by closing the connection but preserving the session. */
3973 SILC_SERVER_CMD_FUNC(detach)
3975 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3976 SilcServer server = cmd->server;
3977 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3980 if (server->config->detach_disabled) {
3981 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
3982 SILC_STATUS_ERR_OPERATION_ALLOWED,
3987 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
3990 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
3992 /* Remove operator privileges, since the client may resume in some
3993 other server which to it does not have operator privileges. */
3994 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
3995 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
3997 /* Send the user mode notify to notify that client is detached */
3998 client->mode |= SILC_UMODE_DETACHED;
3999 client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
4000 client->data.status &= ~SILC_IDLIST_STATUS_NOATTR;
4001 client->last_command = 0;
4002 client->fast_command = 0;
4003 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
4004 SILC_BROADCAST(server), client->id,
4006 server->stat.my_detached++;
4008 /* Check if anyone is watching this nickname */
4009 if (server->server_type == SILC_ROUTER)
4010 silc_server_check_watcher_list(server, client, NULL,
4011 SILC_NOTIFY_TYPE_UMODE_CHANGE);
4013 q = silc_calloc(1, sizeof(*q));
4014 q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
4015 silc_schedule_task_add(server->schedule, 0, silc_server_command_detach_cb,
4016 q, 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
4018 if (server->config->detach_timeout) {
4019 q = silc_calloc(1, sizeof(*q));
4020 q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
4021 silc_schedule_task_add(server->schedule, 0,
4022 silc_server_command_detach_timeout,
4023 q, server->config->detach_timeout * 60,
4024 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
4027 /* Send reply to the sender */
4028 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
4032 silc_server_command_free(cmd);
4035 /* Server side of WATCH command. */
4037 SILC_SERVER_CMD_FUNC(watch)
4039 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4040 SilcServer server = cmd->server;
4041 char *add_nick, *del_nick;
4042 SilcUInt32 add_nick_len, del_nick_len, tmp_len, pk_len;
4044 unsigned char hash[16], *tmp, *pk;
4045 SilcClientEntry client;
4046 SilcClientID *client_id = NULL;
4048 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WATCH, cmd, 1, 3);
4050 if (server->server_type != SILC_ROUTER && !server->standalone) {
4051 if (!cmd->pending) {
4052 /* Send the command to router */
4054 SilcUInt16 old_ident;
4056 SILC_LOG_DEBUG(("Forwarding WATCH to router"));
4058 old_ident = silc_command_get_ident(cmd->payload);
4059 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4060 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4062 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
4063 SILC_PACKET_COMMAND, cmd->packet->flags,
4064 tmpbuf->data, tmpbuf->len, TRUE);
4066 /* Reprocess this packet after received reply from router */
4067 silc_server_command_pending(server, SILC_COMMAND_WATCH,
4068 silc_command_get_ident(cmd->payload),
4069 silc_server_command_watch,
4070 silc_server_command_dup(cmd));
4071 cmd->pending = TRUE;
4072 silc_command_set_ident(cmd->payload, old_ident);
4073 silc_buffer_free(tmpbuf);
4074 } else if (context2) {
4075 /* Received reply from router, just send same data to the client. */
4076 SilcServerCommandReplyContext reply = context2;
4079 SILC_LOG_DEBUG(("Received reply to WATCH from router"));
4080 silc_command_get_status(reply->payload, &status, NULL);
4081 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, status,
4088 /* We are router and keep the watch list for local cell */
4090 /* Get the client ID */
4091 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4093 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4094 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4098 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4100 silc_server_command_send_status_data(cmd, SILC_COMMAND_WATCH,
4101 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
4102 0, 2, tmp, tmp_len);
4106 /* Get the client entry which must be in local list */
4107 client = silc_idlist_find_client_by_id(server->local_list,
4108 client_id, TRUE, NULL);
4110 silc_server_command_send_status_data(cmd, SILC_COMMAND_WATCH,
4111 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0,
4116 /* Take public key for watching by public key */
4117 pk = silc_argument_get_arg_type(cmd->args, 4, &pk_len);
4120 add_nick = silc_argument_get_arg_type(cmd->args, 2, &add_nick_len);
4121 del_nick = silc_argument_get_arg_type(cmd->args, 3, &del_nick_len);
4122 if (!add_nick && !del_nick && !pk) {
4123 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4124 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4129 if (add_nick && add_nick_len > 128)
4130 add_nick[128] = '\0';
4131 if (del_nick && del_nick_len > 128)
4132 del_nick[128] = '\0';
4134 memset(nick, 0, sizeof(nick));
4136 /* Add new nickname to be watched in our cell */
4138 if (silc_server_name_bad_chars(add_nick, strlen(add_nick)) == TRUE) {
4139 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4140 SILC_STATUS_ERR_BAD_NICKNAME, 0);
4144 /* Hash the nick, we have the hash saved, not nicks because we can
4145 do one to one mapping to the nick from Client ID hash this way. */
4146 silc_to_lower(add_nick, nick, sizeof(nick) - 1);
4147 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
4149 /* Check whether this client is already watching this nickname */
4150 if (silc_hash_table_find_by_context(server->watcher_list, hash,
4152 /* Nickname is alredy being watched for this client */
4153 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4154 SILC_STATUS_ERR_NICKNAME_IN_USE,
4159 /* Get the nickname from the watcher list and use the same key in
4160 new entries as well. If key doesn't exist then create it. */
4161 if (!silc_hash_table_find(server->watcher_list, hash, (void *)&tmp, NULL))
4162 tmp = silc_memdup(hash, CLIENTID_HASH_LEN);
4164 /* Add the client to the watcher list with the specified nickname hash. */
4165 silc_hash_table_add(server->watcher_list, tmp, client);
4168 /* Delete nickname from watch list */
4170 if (silc_server_name_bad_chars(del_nick, strlen(del_nick)) == TRUE) {
4171 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4172 SILC_STATUS_ERR_BAD_NICKNAME, 0);
4176 /* Hash the nick, we have the hash saved, not nicks because we can
4177 do one to one mapping to the nick from Client ID hash this way. */
4178 silc_to_lower(del_nick, nick, sizeof(nick) - 1);
4179 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
4181 /* Check that this client is watching for this nickname */
4182 if (!silc_hash_table_find_by_context(server->watcher_list, hash,
4183 client, (void *)&tmp)) {
4184 /* Nickname is alredy being watched for this client */
4185 silc_server_command_send_status_data(cmd, SILC_COMMAND_WATCH,
4186 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
4187 2, nick, strlen(nick));
4191 /* Delete the nickname from the watcher list. */
4192 silc_hash_table_del_by_context(server->watcher_list, hash, client);
4194 /* Now check whether there still exists entries with this key, if not
4195 then free the key to not leak memory. */
4196 if (!silc_hash_table_find(server->watcher_list, hash, NULL, NULL))
4200 /* Add/del public key */
4203 SilcArgumentPayload pkargs;
4205 SilcPublicKey public_key, pkkey;
4208 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4209 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4214 /* Get the argument from the Argument List Payload */
4215 SILC_GET16_MSB(pkargc, pk);
4216 pkargs = silc_argument_payload_parse(pk + 2, pk_len - 2, pkargc);
4218 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4219 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4224 pk = silc_argument_get_next_arg(pkargs, &type, &pk_len);
4226 if (!silc_pkcs_public_key_payload_decode(pk, pk_len, &public_key))
4232 /* Add public key to watch list */
4234 /* Check whether this client is already watching this public key */
4235 if (silc_hash_table_find_by_context(server->watcher_list_pk,
4236 public_key, client, NULL)) {
4237 silc_pkcs_public_key_free(public_key);
4238 silc_server_command_send_status_reply(
4239 cmd, SILC_COMMAND_WATCH,
4240 SILC_STATUS_ERR_NICKNAME_IN_USE, 0);
4244 /* Get the public key from the watcher list and use the same key in
4245 new entries as well. If key doesn't exist then create it. */
4247 if (!silc_hash_table_find(server->watcher_list_pk, public_key,
4248 (void *)&pkkey, NULL))
4251 silc_pkcs_public_key_free(public_key);
4253 /* Add the client to the watcher list with the specified public
4255 silc_hash_table_add(server->watcher_list_pk, pkkey, client);
4257 } else if (type == 0x01) {
4258 /* Delete public key from watch list */
4260 /* Check that this client is watching this public key */
4261 if (silc_hash_table_find_by_context(server->watcher_list_pk,
4264 silc_pkcs_public_key_free(public_key);
4265 silc_server_command_send_status_reply(
4266 cmd, SILC_COMMAND_WATCH,
4267 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4271 /* Delete the public key from the watcher list. */
4272 silc_hash_table_del_by_context(server->watcher_list_pk,
4273 public_key, client);
4275 /* Now check whether there still exists entries with this key, if
4276 not then free the key to not leak memory. */
4277 if (!silc_hash_table_find(server->watcher_list_pk, hash, NULL, NULL))
4278 silc_pkcs_public_key_free(pkkey);
4279 silc_pkcs_public_key_free(public_key);
4282 pk = silc_argument_get_next_arg(pkargs, &type, &pk_len);
4286 /* Distribute the watch list to backup routers too */
4287 if (server->backup) {
4289 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4290 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4291 silc_server_backup_send(server, NULL, SILC_PACKET_COMMAND,
4292 cmd->packet->flags, tmpbuf->data, tmpbuf->len,
4294 silc_buffer_free(tmpbuf);
4297 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4301 silc_free(client_id);
4302 silc_server_command_free(cmd);
4305 /* Server side of SILCOPER command. Client uses this comand to obtain router
4306 operator privileges to this router. */
4308 SILC_SERVER_CMD_FUNC(silcoper)
4310 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4311 SilcServer server = cmd->server;
4312 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4313 unsigned char *username, *auth;
4315 SilcServerConfigAdmin *admin;
4316 SilcIDListData idata = (SilcIDListData)client;
4317 bool result = FALSE;
4318 SilcPublicKey cached_key;
4320 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
4323 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4325 if (server->server_type != SILC_ROUTER) {
4326 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4327 SILC_STATUS_ERR_AUTH_FAILED, 0);
4331 /* Get the username */
4332 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4334 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4335 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4340 /* Get the admin configuration */
4341 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4342 username, client->nickname);
4344 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4345 username, client->nickname);
4347 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4348 SILC_STATUS_ERR_AUTH_FAILED, 0);
4349 SILC_LOG_INFO(("SILCOPER authentication failed for username '%s' by "
4350 "nickname '%s' from %s", username,
4351 client->nickname, cmd->sock->hostname));
4356 /* Get the authentication payload */
4357 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4359 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4360 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4365 /* Verify the authentication data. If both passphrase and public key
4366 is set then try both of them. */
4367 if (admin->passphrase)
4368 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4369 admin->passphrase, admin->passphrase_len,
4370 idata->hash, client->id, SILC_ID_CLIENT);
4371 if (!result && admin->publickeys) {
4372 cached_key = silc_server_get_public_key(server, admin->publickeys);
4375 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4376 cached_key, 0, idata->hash,
4377 client->id, SILC_ID_CLIENT);
4380 /* Authentication failed */
4381 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4382 SILC_STATUS_ERR_AUTH_FAILED, 0);
4386 /* Client is now router operator */
4387 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4389 /* Update statistics */
4390 if (SILC_IS_LOCAL(client))
4391 server->stat.my_router_ops++;
4392 if (server->server_type == SILC_ROUTER)
4393 server->stat.router_ops++;
4395 /* Send UMODE change to primary router */
4396 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
4397 SILC_BROADCAST(server), client->id,
4400 /* Check if anyone is watching this nickname */
4401 if (server->server_type == SILC_ROUTER)
4402 silc_server_check_watcher_list(server, client, NULL,
4403 SILC_NOTIFY_TYPE_UMODE_CHANGE);
4405 /* Send reply to the sender */
4406 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4410 silc_server_command_free(cmd);
4413 /* Server side of command BAN. This is used to manage the ban list of the
4414 channel. To add clients and remove clients from the ban list. */
4416 SILC_SERVER_CMD_FUNC(ban)
4418 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4419 SilcServer server = cmd->server;
4420 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4421 SilcBuffer packet, list, tmp2;
4422 SilcChannelEntry channel;
4423 SilcChannelClientEntry chl;
4424 SilcChannelID *channel_id = NULL;
4425 unsigned char *id, *tmp, *atype = NULL;
4426 SilcUInt32 id_len, len, len2;
4427 SilcArgumentPayload args;
4428 SilcHashTableList htl;
4430 SilcUInt16 argc = 0, ident = silc_command_get_ident(cmd->payload);
4431 SilcBufferStruct blist;
4433 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
4436 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4438 /* Get Channel ID */
4439 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4441 channel_id = silc_id_payload_parse_id(id, id_len, NULL);
4443 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4444 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4449 /* Get channel entry. The server must know about the channel since the
4450 client is expected to be on the channel. */
4451 channel = silc_idlist_find_channel_by_id(server->local_list,
4454 channel = silc_idlist_find_channel_by_id(server->global_list,
4457 silc_server_command_send_status_data(cmd, SILC_COMMAND_BAN,
4458 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
4464 /* Check whether this client is on the channel */
4465 if (!silc_server_client_on_channel(client, channel, &chl)) {
4466 silc_server_command_send_status_data(cmd, SILC_COMMAND_BAN,
4467 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
4472 /* The client must be at least channel operator. */
4473 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4474 silc_server_command_send_status_data(cmd, SILC_COMMAND_BAN,
4475 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0,
4480 /* Get the ban information */
4481 tmp = silc_argument_get_arg_type(cmd->args, 3, &len2);
4482 if (tmp && len2 > 2) {
4483 /* Parse the arguments to see they are constructed correctly */
4484 SILC_GET16_MSB(argc, tmp);
4485 args = silc_argument_payload_parse(tmp + 2, len2 - 2, argc);
4487 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4488 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4493 /* Get the type of action */
4494 atype = silc_argument_get_arg_type(cmd->args, 2, &len);
4495 if (atype && len == 1) {
4496 if (atype[0] == 0x00) {
4497 /* Allocate hash table for ban list if it doesn't exist yet */
4498 if (!channel->ban_list)
4500 silc_hash_table_alloc(0, silc_hash_ptr,
4502 silc_server_inviteban_destruct, channel,
4505 /* Check for resource limit */
4506 if (silc_hash_table_count(channel->ban_list) > 64) {
4507 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4508 SILC_STATUS_ERR_RESOURCE_LIMIT,
4514 /* Now add or delete the information. */
4515 silc_server_inviteban_process(server, channel->ban_list,
4516 (SilcUInt8)atype[0], args);
4518 silc_argument_payload_free(args);
4521 /* Encode ban list */
4523 if (channel->ban_list && silc_hash_table_count(channel->ban_list)) {
4524 list = silc_buffer_alloc_size(2);
4525 silc_buffer_format(list,
4526 SILC_STR_UI_SHORT(silc_hash_table_count(
4527 channel->ban_list)),
4529 silc_hash_table_list(channel->ban_list, &htl);
4530 while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2))
4531 list = silc_argument_payload_encode_one(list, tmp2->data, tmp2->len,
4533 silc_hash_table_list_reset(&htl);
4536 /* Send BAN notify type to local servers (but not clients) and to
4538 if (atype && tmp && len2) {
4539 silc_buffer_set(&blist, tmp, len2);
4541 /* Send to local servers if we are router */
4542 if (server->server_type == SILC_ROUTER)
4543 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, FALSE,
4544 SILC_NOTIFY_TYPE_BAN, 3,
4547 tmp ? blist.data : NULL,
4548 tmp ? blist.len : 0);
4550 /* Send to network. */
4551 silc_server_send_notify_ban(server, SILC_PRIMARY_ROUTE(server),
4552 SILC_BROADCAST(server), channel, atype,
4556 /* Send the reply back to the client */
4558 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4559 SILC_STATUS_OK, 0, ident, 2,
4561 3, list ? list->data : NULL,
4562 list ? list->len : 0);
4563 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4564 packet->data, packet->len, FALSE);
4566 silc_buffer_free(packet);
4567 silc_buffer_free(list);
4570 silc_free(channel_id);
4571 silc_server_command_free(cmd);
4574 /* Server side command of LEAVE. Removes client from a channel. */
4576 SILC_SERVER_CMD_FUNC(leave)
4578 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4579 SilcServer server = cmd->server;
4580 SilcSocketConnection sock = cmd->sock;
4581 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4582 SilcChannelID *id = NULL;
4583 SilcChannelEntry channel;
4587 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !id_entry)
4590 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4592 /* Get Channel ID */
4593 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4595 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4596 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4599 id = silc_id_payload_parse_id(tmp, len, NULL);
4601 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4602 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4606 /* Get channel entry */
4607 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4609 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4611 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4612 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
4618 /* Check whether this client is on the channel */
4619 if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
4620 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4621 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
4626 /* Notify routers that they should remove this client from their list
4627 of clients on the channel. Send LEAVE notify type. */
4628 silc_server_send_notify_leave(server, SILC_PRIMARY_ROUTE(server),
4629 SILC_BROADCAST(server), channel, id_entry->id);
4631 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4632 SILC_STATUS_OK, 0, 2, tmp, len);
4634 /* Remove client from channel */
4635 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4637 /* If the channel does not exist anymore we won't send anything */
4640 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4641 /* Re-generate channel key */
4642 if (!silc_server_create_channel_key(server, channel, 0))
4645 /* Send the channel key */
4646 silc_server_send_channel_key(server, NULL, channel,
4647 server->server_type == SILC_ROUTER ?
4648 FALSE : !server->standalone);
4653 silc_server_command_free(cmd);
4656 /* Server side of command USERS. Resolves clients and their USERS currently
4657 joined on the requested channel. The list of Client ID's and their modes
4658 on the channel is sent back. */
4660 SILC_SERVER_CMD_FUNC(users)
4662 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4663 SilcServer server = cmd->server;
4664 SilcChannelEntry channel;
4665 SilcChannelID *id = NULL;
4666 SilcBuffer packet, idp;
4667 unsigned char *channel_id;
4668 SilcUInt32 channel_id_len;
4669 SilcBuffer client_id_list;
4670 SilcBuffer client_mode_list;
4671 unsigned char lc[4];
4672 SilcUInt32 list_count = 0;
4673 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4676 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
4678 /* Get Channel ID */
4679 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4681 /* Get channel name */
4682 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
4684 if (!channel_id && !channel_name) {
4685 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4686 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4691 id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
4693 silc_server_command_send_status_data(cmd, SILC_COMMAND_USERS,
4694 SILC_STATUS_ERR_BAD_CHANNEL_ID, 0,
4695 2, channel_id, channel_id_len);
4700 /* If we are server and we don't know about this channel we will send
4701 the command to our router. If we know about the channel then we also
4702 have the list of users already. */
4704 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4706 channel = silc_idlist_find_channel_by_name(server->local_list,
4707 channel_name, NULL);
4709 if (!channel || (!server->standalone && (channel->disabled ||
4710 !channel->users_resolved))) {
4711 if (server->server_type != SILC_ROUTER && !server->standalone &&
4715 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4716 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4718 /* Send USERS command */
4719 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
4720 SILC_PACKET_COMMAND, cmd->packet->flags,
4721 tmpbuf->data, tmpbuf->len, TRUE);
4723 /* Reprocess this packet after received reply */
4724 silc_server_command_pending(server, SILC_COMMAND_USERS,
4725 silc_command_get_ident(cmd->payload),
4726 silc_server_command_users,
4727 silc_server_command_dup(cmd));
4728 cmd->pending = TRUE;
4729 silc_command_set_ident(cmd->payload, ident);
4730 silc_buffer_free(tmpbuf);
4735 /* Check the global list as well. */
4737 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4739 channel = silc_idlist_find_channel_by_name(server->global_list,
4740 channel_name, NULL);
4742 /* Channel really does not exist */
4744 silc_server_command_send_status_data(
4745 cmd, SILC_COMMAND_USERS,
4746 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID, 0,
4747 2, channel_id, channel_id_len);
4749 silc_server_command_send_status_data(
4750 cmd, SILC_COMMAND_USERS,
4751 SILC_STATUS_ERR_NO_SUCH_CHANNEL, 0,
4752 2, channel_name, strlen(channel_name));
4757 /* If the channel is private or secret do not send anything, unless the
4758 user requesting this command is on the channel or is server */
4759 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
4760 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
4761 && !silc_server_client_on_channel(cmd->sock->user_data, channel,
4763 silc_server_command_send_status_data(cmd, SILC_COMMAND_USERS,
4764 SILC_STATUS_ERR_NO_SUCH_CHANNEL, 0,
4765 2, channel->channel_name,
4766 strlen(channel->channel_name));
4771 /* Get the users list */
4772 if (!silc_server_get_users_on_channel(server, channel, &client_id_list,
4773 &client_mode_list, &list_count)) {
4775 client_id_list = NULL;
4776 client_mode_list = NULL;
4780 SILC_PUT32_MSB(list_count, lc);
4783 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
4784 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
4785 SILC_STATUS_OK, 0, ident, 4,
4786 2, idp->data, idp->len,
4789 client_id_list->data : NULL,
4791 client_id_list->len : 0,
4792 5, client_mode_list ?
4793 client_mode_list->data : NULL,
4795 client_mode_list->len : 0);
4796 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4797 packet->data, packet->len, FALSE);
4799 silc_buffer_free(idp);
4800 silc_buffer_free(packet);
4802 silc_buffer_free(client_id_list);
4803 if (client_mode_list)
4804 silc_buffer_free(client_mode_list);
4808 silc_server_command_free(cmd);
4811 /* Server side of command GETKEY. This fetches the client's public key
4812 from the server where to the client is connected. */
4814 SILC_SERVER_CMD_FUNC(getkey)
4816 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4817 SilcServer server = cmd->server;
4819 SilcClientEntry client;
4820 SilcServerEntry server_entry;
4821 SilcClientID *client_id = NULL;
4822 SilcServerID *server_id = NULL;
4823 SilcIDPayload idp = NULL;
4824 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4827 SilcBuffer pk = NULL;
4829 SilcPublicKey public_key;
4831 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4833 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4834 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4838 idp = silc_id_payload_parse(tmp, tmp_len);
4840 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4841 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4846 id_type = silc_id_payload_get_type(idp);
4847 if (id_type == SILC_ID_CLIENT) {
4848 client_id = silc_id_payload_get_id(idp);
4850 /* If the client is not found from local list there is no chance it
4851 would be locally connected client so send the command further. */
4852 client = silc_idlist_find_client_by_id(server->local_list,
4853 client_id, TRUE, NULL);
4855 client = silc_idlist_find_client_by_id(server->global_list,
4856 client_id, TRUE, NULL);
4858 if ((!client && !cmd->pending && !server->standalone) ||
4859 (client && !client->connection && !cmd->pending &&
4860 !(client->mode & SILC_UMODE_DETACHED)) ||
4861 (client && !client->data.public_key && !cmd->pending)) {
4863 SilcUInt16 old_ident;
4864 SilcSocketConnection dest_sock;
4866 dest_sock = silc_server_get_client_route(server, NULL, 0,
4867 client_id, NULL, NULL);
4871 old_ident = silc_command_get_ident(cmd->payload);
4872 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4873 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4875 silc_server_packet_send(server, dest_sock,
4876 SILC_PACKET_COMMAND, cmd->packet->flags,
4877 tmpbuf->data, tmpbuf->len, TRUE);
4879 /* Reprocess this packet after received reply from router */
4880 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
4881 silc_command_get_ident(cmd->payload),
4882 silc_server_command_getkey,
4883 silc_server_command_dup(cmd));
4884 cmd->pending = TRUE;
4885 silc_command_set_ident(cmd->payload, old_ident);
4886 silc_buffer_free(tmpbuf);
4891 silc_server_command_send_status_data(cmd, SILC_COMMAND_GETKEY,
4892 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
4893 0, 2, tmp, tmp_len);
4897 /* The client is locally connected, just get the public key and
4898 send it back. If they key does not exist then do not send it,
4899 send just OK reply */
4900 public_key = client->data.public_key;
4902 pk = silc_pkcs_public_key_payload_encode(public_key);
4903 } else if (id_type == SILC_ID_SERVER) {
4904 server_id = silc_id_payload_get_id(idp);
4906 /* If the server is not found from local list there is no chance it
4907 would be locally connected server so send the command further. */
4908 server_entry = silc_idlist_find_server_by_id(server->local_list,
4909 server_id, TRUE, NULL);
4911 server_entry = silc_idlist_find_server_by_id(server->global_list,
4912 server_id, TRUE, NULL);
4914 if (server_entry != server->id_entry &&
4915 ((!server_entry && !cmd->pending && !server->standalone) ||
4916 (server_entry && !server_entry->connection && !cmd->pending &&
4917 !server->standalone) ||
4918 (server_entry && !server_entry->data.public_key && !cmd->pending &&
4919 !server->standalone))) {
4921 SilcUInt16 old_ident;
4923 old_ident = silc_command_get_ident(cmd->payload);
4924 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4925 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4927 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
4928 SILC_PACKET_COMMAND, cmd->packet->flags,
4929 tmpbuf->data, tmpbuf->len, TRUE);
4931 /* Reprocess this packet after received reply from router */
4932 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
4933 silc_command_get_ident(cmd->payload),
4934 silc_server_command_getkey,
4935 silc_server_command_dup(cmd));
4936 cmd->pending = TRUE;
4937 silc_command_set_ident(cmd->payload, old_ident);
4938 silc_buffer_free(tmpbuf);
4942 if (!server_entry) {
4943 silc_server_command_send_status_data(cmd, SILC_COMMAND_GETKEY,
4944 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
4945 0, 2, tmp, tmp_len);
4949 /* If they key does not exist then do not send it, send just OK reply */
4950 public_key = (!server_entry->data.public_key ?
4951 (server_entry == server->id_entry ? server->public_key :
4952 NULL) : server_entry->data.public_key);
4954 pk = silc_pkcs_public_key_payload_encode(public_key);
4959 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4960 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
4961 SILC_STATUS_OK, 0, ident, 2,
4963 3, pk ? pk->data : NULL,
4965 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4966 packet->data, packet->len, FALSE);
4967 silc_buffer_free(packet);
4971 silc_id_payload_free(idp);
4972 silc_buffer_free(pk);
4973 silc_free(client_id);
4974 silc_free(server_id);
4975 silc_server_command_free(cmd);
4979 /* Private range commands, specific to this implementation */
4981 /* Server side command of CONNECT. Connects us to the specified remote
4982 server or router. */
4984 SILC_SERVER_CMD_FUNC(connect)
4986 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4987 SilcServer server = cmd->server;
4988 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4989 unsigned char *tmp, *host;
4991 SilcUInt32 port = SILC_PORT;
4993 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
4996 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
4998 /* Check whether client has the permissions. */
4999 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5000 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5001 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5002 SILC_STATUS_ERR_NO_SERVER_PRIV, 0);
5006 if (server->server_type == SILC_ROUTER && !server->backup_router &&
5007 client->mode & SILC_UMODE_SERVER_OPERATOR) {
5008 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5009 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
5013 /* Get the remote server */
5014 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5016 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5017 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5023 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5025 SILC_GET32_MSB(port, tmp);
5027 /* Create the connection. It is done with timeout and is async. */
5028 silc_server_create_connection(server, host, port);
5030 /* Send reply to the sender */
5031 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5035 silc_server_command_free(cmd);
5038 /* Server side command of CLOSE. Closes connection to a specified server. */
5040 SILC_SERVER_CMD_FUNC(close)
5042 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5043 SilcServer server = cmd->server;
5044 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5045 SilcServerEntry server_entry;
5046 SilcSocketConnection sock;
5049 unsigned char *name;
5050 SilcUInt32 port = SILC_PORT;
5052 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
5055 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
5057 /* Check whether client has the permissions. */
5058 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5059 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5060 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5061 SILC_STATUS_ERR_NO_SERVER_PRIV,
5066 /* Get the remote server */
5067 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5069 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5070 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5076 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5078 SILC_GET32_MSB(port, tmp);
5080 server_entry = silc_idlist_find_server_by_conn(server->local_list,
5081 name, port, TRUE, NULL);
5083 server_entry = silc_idlist_find_server_by_conn(server->global_list,
5084 name, port, TRUE, NULL);
5085 if (!server_entry) {
5086 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5087 SILC_STATUS_ERR_NO_SERVER_ID, 0);
5091 if (server_entry == server->id_entry) {
5092 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5093 SILC_STATUS_ERR_NO_SERVER_ID, 0);
5097 /* Send reply to the sender */
5098 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5101 /* Close the connection to the server */
5102 sock = (SilcSocketConnection)server_entry->connection;
5104 if (server_entry->server_type == SILC_BACKUP_ROUTER) {
5105 server->backup_closed = TRUE;
5106 silc_server_backup_del(server, server_entry);
5109 server->backup_noswitch = TRUE;
5110 if (server->router == server_entry) {
5111 server->id_entry->router = NULL;
5112 server->router = NULL;
5113 server->standalone = TRUE;
5115 silc_server_disconnect_remote(server, sock,
5116 SILC_STATUS_ERR_BANNED_FROM_SERVER,
5117 "Closed by administrator");
5118 if (sock->user_data)
5119 silc_server_free_sock_user_data(server, sock, NULL);
5120 server->backup_noswitch = FALSE;
5123 silc_server_command_free(cmd);
5126 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
5127 active connections. */
5129 SILC_SERVER_CMD_FUNC(shutdown)
5131 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5132 SilcServer server = cmd->server;
5133 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5135 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
5138 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
5140 /* Check whether client has the permission. */
5141 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5142 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5143 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5144 SILC_STATUS_ERR_NO_SERVER_PRIV,
5149 /* Send reply to the sender */
5150 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5153 /* Then, gracefully, or not, bring the server down. */
5154 silc_server_stop(server);
5158 silc_server_command_free(cmd);