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 status = SILC_STATUS_OK;
766 if ((lch_count + gch_count) > 1)
767 status = SILC_STATUS_LIST_START;
770 for (i = 0, k = 0; i < lch_count; i++) {
776 status = SILC_STATUS_LIST_ITEM;
777 if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
778 status = SILC_STATUS_LIST_END;
780 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
782 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
784 memset(usercount, 0, sizeof(usercount));
786 topic = entry->topic;
787 users = silc_hash_table_count(entry->user_list);
788 SILC_PUT32_MSB(users, usercount);
793 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
795 2, idp->data, idp->len,
796 3, entry->channel_name,
797 strlen(entry->channel_name),
798 4, topic, topic ? strlen(topic) : 0,
800 silc_server_packet_send(cmd->server, cmd->sock,
801 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
803 silc_buffer_free(packet);
804 silc_buffer_free(idp);
809 for (i = 0, k = 0; i < gch_count; i++) {
815 status = SILC_STATUS_LIST_ITEM;
816 if (valid_rcount > 1 && k == valid_rcount - 1)
817 status = SILC_STATUS_LIST_END;
819 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
821 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
823 memset(usercount, 0, sizeof(usercount));
825 topic = entry->topic;
826 users = entry->user_count;
827 SILC_PUT32_MSB(users, usercount);
832 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
834 2, idp->data, idp->len,
835 3, entry->channel_name,
836 strlen(entry->channel_name),
837 4, topic, topic ? strlen(topic) : 0,
839 silc_server_packet_send(cmd->server, cmd->sock,
840 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
842 silc_buffer_free(packet);
843 silc_buffer_free(idp);
848 /* Server side of LIST command. This lists the channel of the requested
849 server. Secret channels are not listed. */
851 SILC_SERVER_CMD_FUNC(list)
853 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
854 SilcServer server = cmd->server;
855 SilcChannelID *channel_id = NULL;
858 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
859 SilcUInt32 lch_count = 0, gch_count = 0;
861 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
863 /* If we are normal server, send the command to router, since we
864 want to know all channels in the network. */
865 if (!cmd->pending && server->server_type != SILC_ROUTER &&
866 !server->standalone) {
868 SilcUInt16 old_ident;
870 old_ident = silc_command_get_ident(cmd->payload);
871 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
872 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
873 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
874 SILC_PACKET_COMMAND, cmd->packet->flags,
875 tmpbuf->data, tmpbuf->len, TRUE);
877 /* Reprocess this packet after received reply from router */
878 silc_server_command_pending(server, SILC_COMMAND_LIST,
879 silc_command_get_ident(cmd->payload),
880 silc_server_command_list,
881 silc_server_command_dup(cmd));
883 silc_command_set_ident(cmd->payload, old_ident);
884 silc_buffer_free(tmpbuf);
889 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
891 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
893 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
894 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
899 /* Get the channels from local list */
900 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
903 /* Get the channels from global list */
904 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
908 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
909 gchannels, gch_count);
911 silc_free(lchannels);
912 silc_free(gchannels);
915 silc_server_command_free(cmd);
918 /* Server side of TOPIC command. Sets topic for channel and/or returns
919 current topic to client. */
921 SILC_SERVER_CMD_FUNC(topic)
923 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
924 SilcServer server = cmd->server;
925 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
926 SilcChannelID *channel_id;
927 SilcChannelEntry channel;
928 SilcChannelClientEntry chl;
929 SilcBuffer packet, idp;
931 SilcUInt32 argc, tmp_len;
932 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
934 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
937 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
939 argc = silc_argument_get_arg_num(cmd->args);
942 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
944 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
945 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
948 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
950 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
951 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
955 /* Check whether the channel exists */
956 channel = silc_idlist_find_channel_by_id(server->local_list,
959 channel = silc_idlist_find_channel_by_id(server->global_list,
962 silc_server_command_send_status_data(cmd, SILC_COMMAND_TOPIC,
963 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
971 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
973 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
974 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
979 if (strlen(tmp) > 256) {
980 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
981 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
986 /* See whether the client is on channel and has rights to change topic */
987 if (!silc_server_client_on_channel(client, channel, &chl)) {
988 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
989 silc_server_command_send_status_data(cmd, SILC_COMMAND_TOPIC,
990 SILC_STATUS_ERR_NOT_ON_CHANNEL,
995 if (channel->mode & SILC_CHANNEL_MODE_TOPIC &&
996 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
997 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
998 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
999 silc_server_command_send_status_data(cmd, SILC_COMMAND_TOPIC,
1000 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
1001 0, 2, tmp, tmp_len);
1005 if (!channel->topic || strcmp(channel->topic, tmp)) {
1006 /* Set the topic for channel */
1007 silc_free(channel->topic);
1008 channel->topic = strdup(tmp);
1010 /* Send TOPIC_SET notify type to the network */
1011 silc_server_send_notify_topic_set(server, SILC_PRIMARY_ROUTE(server),
1012 SILC_BROADCAST(server), channel,
1013 client->id, SILC_ID_CLIENT,
1016 /* Send notify about topic change to all clients on the channel */
1017 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1018 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
1019 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
1020 idp->data, idp->len,
1022 strlen(channel->topic));
1023 silc_buffer_free(idp);
1027 /* Send the topic to client as reply packet */
1028 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1029 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1030 SILC_STATUS_OK, 0, ident, 2,
1031 2, idp->data, idp->len,
1034 strlen(channel->topic) : 0);
1035 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1036 0, packet->data, packet->len, FALSE);
1038 silc_buffer_free(packet);
1039 silc_buffer_free(idp);
1040 silc_free(channel_id);
1043 silc_server_command_free(cmd);
1046 /* Server side of INVITE command. Invites some client to join some channel.
1047 This command is also used to manage the invite list of the channel. */
1049 SILC_SERVER_CMD_FUNC(invite)
1051 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1052 SilcServer server = cmd->server;
1053 SilcSocketConnection sock = cmd->sock, dest_sock;
1054 SilcChannelClientEntry chl;
1055 SilcClientEntry sender, dest;
1056 SilcClientID *dest_id = NULL;
1057 SilcChannelEntry channel;
1058 SilcChannelID *channel_id = NULL;
1059 SilcIDListData idata;
1060 SilcArgumentPayload args;
1061 SilcHashTableList htl;
1062 SilcBuffer packet, list, tmp2;
1063 SilcBufferStruct alist;
1064 unsigned char *tmp, *atype = NULL;
1065 SilcUInt32 len, type, len2;
1066 SilcUInt16 argc = 0, ident = silc_command_get_ident(cmd->payload);
1068 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
1070 /* Get Channel ID */
1071 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1073 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1074 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
1077 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
1079 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1080 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
1084 /* Get the channel entry */
1085 channel = silc_idlist_find_channel_by_id(server->local_list,
1088 channel = silc_idlist_find_channel_by_id(server->global_list,
1091 silc_server_command_send_status_data(cmd, SILC_COMMAND_INVITE,
1092 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
1098 /* Check whether the sender of this command is on the channel. */
1099 sender = (SilcClientEntry)sock->user_data;
1100 if (!sender || !silc_server_client_on_channel(sender, channel, &chl)) {
1101 silc_server_command_send_status_data(cmd, SILC_COMMAND_INVITE,
1102 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
1107 /* Check whether the channel is invite-only channel. If yes then the
1108 sender of this command must be at least channel operator. */
1109 if (channel->mode & SILC_CHANNEL_MODE_INVITE &&
1110 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
1111 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
1112 silc_server_command_send_status_data(cmd, SILC_COMMAND_INVITE,
1113 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
1118 /* Get destination client ID */
1119 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1123 dest_id = silc_id_payload_parse_id(tmp, len, NULL);
1125 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1126 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
1130 /* Get the client entry */
1131 dest = silc_server_query_client(server, dest_id, FALSE, &resolve);
1133 if (server->server_type != SILC_SERVER || !resolve || cmd->pending) {
1134 silc_server_command_send_status_data(
1135 cmd, SILC_COMMAND_INVITE,
1136 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0,
1141 /* The client info is being resolved. Reprocess this packet after
1142 receiving the reply to the query. */
1143 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1145 silc_server_command_invite,
1146 silc_server_command_dup(cmd));
1147 cmd->pending = TRUE;
1151 /* Check whether the requested client is already on the channel. */
1152 if (silc_server_client_on_channel(dest, channel, NULL)) {
1153 atype = silc_argument_get_arg_type(cmd->args, 1, &len2);
1154 silc_server_command_send_status_data2(cmd, SILC_COMMAND_INVITE,
1155 SILC_STATUS_ERR_USER_ON_CHANNEL,
1161 /* Get route to the client */
1162 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id,
1165 silc_server_command_send_status_data(cmd, SILC_COMMAND_INVITE,
1166 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1171 /* Add the client to the invite list */
1173 /* Allocate hash table for invite list if it doesn't exist yet */
1174 if (!channel->invite_list)
1175 channel->invite_list =
1176 silc_hash_table_alloc(0, silc_hash_ptr,
1178 silc_server_inviteban_destruct, channel, TRUE);
1180 /* Check if the ID is in the list already */
1181 silc_hash_table_list(channel->invite_list, &htl);
1182 while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) {
1183 if (type == 3 && !memcmp(tmp2->data, tmp, len)) {
1188 silc_hash_table_list_reset(&htl);
1190 /* Add new Client ID to invite list */
1192 list = silc_buffer_alloc_size(len);
1193 silc_buffer_put(list, tmp, len);
1194 silc_hash_table_add(channel->invite_list, (void *)3, list);
1197 if (!(dest->mode & SILC_UMODE_BLOCK_INVITE)) {
1198 /* Send notify to the client that is invited to the channel */
1199 SilcBuffer idp, idp2;
1200 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1201 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1202 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
1204 SILC_NOTIFY_TYPE_INVITE, 3,
1205 idp->data, idp->len,
1206 channel->channel_name,
1207 strlen(channel->channel_name),
1208 idp2->data, idp2->len);
1209 silc_buffer_free(idp);
1210 silc_buffer_free(idp2);
1214 /* Get the invite information */
1215 tmp = silc_argument_get_arg_type(cmd->args, 4, &len2);
1216 if (tmp && len2 > 2) {
1217 /* Parse the arguments to see they are constructed correctly */
1218 SILC_GET16_MSB(argc, tmp);
1219 args = silc_argument_payload_parse(tmp + 2, len2 - 2, argc);
1221 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1222 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1227 /* Get the type of action */
1228 atype = silc_argument_get_arg_type(cmd->args, 3, &len);
1229 if (atype && len == 1) {
1230 if (atype[0] == 0x00) {
1231 /* Allocate hash table for invite list if it doesn't exist yet */
1232 if (!channel->invite_list)
1233 channel->invite_list =
1234 silc_hash_table_alloc(0, silc_hash_ptr,
1236 silc_server_inviteban_destruct, channel,
1239 /* Check for resource limit */
1240 if (silc_hash_table_count(channel->invite_list) > 64) {
1241 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1242 SILC_STATUS_ERR_RESOURCE_LIMIT,
1248 /* Now add or delete the information. */
1249 silc_server_inviteban_process(server, channel->invite_list,
1250 (SilcUInt8)atype[0], args);
1252 silc_argument_payload_free(args);
1255 /* Encode invite list */
1257 if (channel->invite_list && silc_hash_table_count(channel->invite_list)) {
1258 list = silc_buffer_alloc_size(2);
1259 silc_buffer_format(list,
1260 SILC_STR_UI_SHORT(silc_hash_table_count(
1261 channel->invite_list)),
1263 silc_hash_table_list(channel->invite_list, &htl);
1264 while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2))
1265 list = silc_argument_payload_encode_one(list, tmp2->data, tmp2->len,
1267 silc_hash_table_list_reset(&htl);
1270 /* The notify is sent to local servers (not clients), and to network. */
1271 if (atype && tmp && len2) {
1272 silc_buffer_set(&alist, tmp, len2);
1274 /* Send to local servers if we are router */
1275 if (server->server_type == SILC_ROUTER) {
1276 SilcBuffer idp, idp2;
1277 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1278 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1279 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, FALSE,
1280 SILC_NOTIFY_TYPE_INVITE, 5,
1281 idp->data, idp->len,
1282 channel->channel_name,
1283 strlen(channel->channel_name),
1284 idp2->data, idp2->len,
1286 tmp ? alist.data : NULL,
1287 tmp ? alist.len : 0);
1288 silc_buffer_free(idp);
1289 silc_buffer_free(idp2);
1292 /* Send to network */
1293 silc_server_send_notify_invite(server, SILC_PRIMARY_ROUTE(server),
1294 SILC_BROADCAST(server), channel,
1296 tmp ? &alist : NULL);
1299 /* Send invite list back only if the list was modified, or no arguments
1302 argc = silc_argument_get_arg_num(cmd->args);
1305 if (silc_argument_get_arg_type(cmd->args, 3, &len))
1308 /* Send command reply */
1309 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1310 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
1311 SILC_STATUS_OK, 0, ident, 2,
1315 type && list ? list->len : 0);
1316 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1317 packet->data, packet->len, FALSE);
1318 silc_buffer_free(packet);
1319 silc_buffer_free(list);
1323 silc_free(channel_id);
1324 silc_server_command_free(cmd);
1328 SilcSocketConnection sock;
1332 /* Quits connection to client. This gets called if client won't
1333 close the connection even when it has issued QUIT command. */
1335 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
1337 SilcServer server = app_context;
1338 QuitInternal q = (QuitInternal)context;
1340 if (q->sock->user_data) {
1341 /* Free all client specific data, such as client entry and entires
1342 on channels this client may be on. */
1343 silc_server_free_client_data(server, q->sock, q->sock->user_data,
1345 q->sock->user_data = NULL;
1348 if (!SILC_IS_DISCONNECTED(q->sock))
1349 /* Close the connection on our side */
1350 silc_server_close_connection(server, q->sock);
1352 silc_socket_free(q->sock);
1353 silc_free(q->signoff);
1357 /* Quits SILC session. This is the normal way to disconnect client. */
1359 SILC_SERVER_CMD_FUNC(quit)
1361 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1362 SilcServer server = cmd->server;
1363 SilcSocketConnection sock = cmd->sock;
1365 unsigned char *tmp = NULL;
1368 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
1370 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1374 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1378 q = silc_calloc(1, sizeof(*q));
1379 q->sock = silc_socket_dup(sock);
1380 q->signoff = tmp ? strdup(tmp) : NULL;
1382 /* We quit the connection with little timeout */
1383 silc_schedule_task_add(server->schedule, sock->sock,
1384 silc_server_command_quit_cb, (void *)q,
1385 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1388 silc_server_command_free(cmd);
1391 /* Server side of command KILL. This command is used by router operator
1392 to remove an client from the SILC Network temporarily. */
1394 SILC_SERVER_CMD_FUNC(kill)
1396 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1397 SilcServer server = cmd->server;
1398 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1399 SilcClientEntry remote_client;
1400 SilcClientID *client_id = NULL;
1401 unsigned char *tmp, *comment, *auth;
1402 SilcUInt32 tmp_len, tmp_len2, auth_len;
1404 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 3);
1406 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
1409 /* Get authentication payload if present */
1410 auth = silc_argument_get_arg_type(cmd->args, 3, &auth_len);
1413 /* Router operator killing */
1415 /* KILL command works only on router */
1416 if (server->server_type != SILC_ROUTER) {
1417 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1418 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
1422 /* Check whether client has the permissions. */
1423 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
1424 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1425 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
1430 /* Get the client ID */
1431 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1433 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1434 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1438 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1440 silc_server_command_send_status_data(cmd, SILC_COMMAND_KILL,
1441 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1442 0, 2, tmp, tmp_len);
1446 /* Get the client entry */
1447 remote_client = silc_idlist_find_client_by_id(server->local_list,
1448 client_id, TRUE, NULL);
1449 if (!remote_client) {
1450 remote_client = silc_idlist_find_client_by_id(server->global_list,
1451 client_id, TRUE, NULL);
1452 if (!remote_client) {
1453 silc_server_command_send_status_data(cmd, SILC_COMMAND_KILL,
1454 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1455 0, 2, tmp, tmp_len);
1461 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
1462 if (comment && tmp_len2 > 128) {
1464 comment[127] = '\0';
1467 /* If authentication data is provided then verify that killing is
1469 if (auth && auth_len) {
1470 SilcSocketConnection sock;
1472 if (!SILC_IS_LOCAL(remote_client) || !remote_client->data.public_key) {
1473 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1474 SILC_STATUS_ERR_OPERATION_ALLOWED,
1479 /* Verify the signature */
1480 if (!silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
1481 remote_client->data.public_key, 0,
1482 server->sha1hash, remote_client->id,
1484 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1485 SILC_STATUS_ERR_AUTH_FAILED, 0);
1489 /* Send reply to the sender */
1490 silc_server_command_send_status_data(cmd, SILC_COMMAND_KILL,
1494 /* Do normal signoff for the destination client */
1495 sock = remote_client->connection;
1496 silc_server_remove_from_channels(server, NULL, remote_client,
1497 TRUE, (char *)"Killed", TRUE, TRUE);
1498 silc_server_free_client_data(server, NULL, remote_client, TRUE,
1500 (unsigned char *)"Killed");
1502 silc_server_close_connection(server, sock);
1504 /* Router operator killing */
1506 /* Send reply to the sender */
1507 silc_server_command_send_status_data(cmd, SILC_COMMAND_KILL,
1511 /* Check if anyone is watching this nickname */
1512 if (server->server_type == SILC_ROUTER)
1513 silc_server_check_watcher_list(server, client, NULL,
1514 SILC_NOTIFY_TYPE_KILLED);
1516 /* Now do the killing */
1517 silc_server_kill_client(server, remote_client, comment, client->id,
1522 silc_free(client_id);
1523 silc_server_command_free(cmd);
1526 /* Server side of command INFO. This sends information about us to
1527 the client. If client requested specific server we will send the
1528 command to that server. */
1530 SILC_SERVER_CMD_FUNC(info)
1532 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1533 SilcServer server = cmd->server;
1534 SilcBuffer packet, idp;
1537 char *dest_server, *server_info = NULL, *server_name;
1538 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1539 SilcServerEntry entry = NULL;
1540 SilcServerID *server_id = NULL;
1542 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
1544 /* Get server name */
1545 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1548 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1550 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1552 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1553 SILC_STATUS_ERR_NO_SERVER_ID, 0);
1559 /* Check whether we have this server cached */
1560 entry = silc_idlist_find_server_by_id(server->local_list,
1561 server_id, TRUE, NULL);
1563 entry = silc_idlist_find_server_by_id(server->global_list,
1564 server_id, TRUE, NULL);
1565 if (!entry && server->server_type != SILC_SERVER) {
1566 silc_server_command_send_status_data(cmd, SILC_COMMAND_INFO,
1567 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
1568 0, 2, tmp, tmp_len);
1574 /* Some buggy servers has sent request to router about themselves. */
1575 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
1578 if ((!dest_server && !server_id && !entry) || (entry &&
1579 entry == server->id_entry) ||
1580 (dest_server && !cmd->pending &&
1581 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
1582 /* Send our reply */
1583 char info_string[256];
1585 memset(info_string, 0, sizeof(info_string));
1586 snprintf(info_string, sizeof(info_string),
1587 "location: %s server: %s admin: %s <%s>",
1588 server->config->server_info->location,
1589 server->config->server_info->server_type,
1590 server->config->server_info->admin,
1591 server->config->server_info->email);
1593 server_info = info_string;
1594 entry = server->id_entry;
1596 /* Check whether we have this server cached */
1597 if (!entry && dest_server) {
1598 entry = silc_idlist_find_server_by_name(server->global_list,
1599 dest_server, TRUE, NULL);
1601 entry = silc_idlist_find_server_by_name(server->local_list,
1602 dest_server, TRUE, NULL);
1606 if (!cmd->pending &&
1607 server->server_type != SILC_SERVER && entry && !entry->server_info) {
1608 /* Send to the server */
1610 SilcUInt16 old_ident;
1612 old_ident = silc_command_get_ident(cmd->payload);
1613 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1614 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1616 silc_server_packet_send(server, entry->connection,
1617 SILC_PACKET_COMMAND, cmd->packet->flags,
1618 tmpbuf->data, tmpbuf->len, TRUE);
1620 /* Reprocess this packet after received reply from router */
1621 silc_server_command_pending(server, SILC_COMMAND_INFO,
1622 silc_command_get_ident(cmd->payload),
1623 silc_server_command_info,
1624 silc_server_command_dup(cmd));
1625 cmd->pending = TRUE;
1626 silc_command_set_ident(cmd->payload, old_ident);
1627 silc_buffer_free(tmpbuf);
1631 if (!entry && !cmd->pending && !server->standalone) {
1632 /* Send to the primary router */
1634 SilcUInt16 old_ident;
1636 old_ident = silc_command_get_ident(cmd->payload);
1637 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1638 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1640 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
1641 SILC_PACKET_COMMAND, cmd->packet->flags,
1642 tmpbuf->data, tmpbuf->len, TRUE);
1644 /* Reprocess this packet after received reply from router */
1645 silc_server_command_pending(server, SILC_COMMAND_INFO,
1646 silc_command_get_ident(cmd->payload),
1647 silc_server_command_info,
1648 silc_server_command_dup(cmd));
1649 cmd->pending = TRUE;
1650 silc_command_set_ident(cmd->payload, old_ident);
1651 silc_buffer_free(tmpbuf);
1656 silc_free(server_id);
1660 silc_server_command_send_status_data(cmd, SILC_COMMAND_INFO,
1661 SILC_STATUS_ERR_NO_SUCH_SERVER, 0,
1663 strlen(dest_server));
1667 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1669 server_info = entry->server_info;
1670 server_name = entry->server_name;
1672 /* Send the reply */
1673 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
1674 SILC_STATUS_OK, 0, ident, 3,
1675 2, idp->data, idp->len,
1677 strlen(server_name),
1680 strlen(server_info) : 0);
1681 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1682 packet->data, packet->len, FALSE);
1684 silc_buffer_free(packet);
1685 silc_buffer_free(idp);
1688 silc_server_command_free(cmd);
1691 /* Server side of command PING. This just replies to the ping. */
1693 SILC_SERVER_CMD_FUNC(ping)
1695 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1696 SilcServer server = cmd->server;
1699 SilcServerID *server_id = NULL;
1701 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PING, cmd, 1, 1);
1704 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1706 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1707 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1711 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1715 if (SILC_ID_SERVER_COMPARE(server_id, server->id)) {
1716 /* Send our reply */
1717 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1720 silc_server_command_send_status_data(cmd, SILC_COMMAND_PING,
1721 SILC_STATUS_ERR_NO_SUCH_SERVER_ID, 0,
1727 silc_free(server_id);
1728 silc_server_command_free(cmd);
1731 /* Server side of command STATS. */
1733 SILC_SERVER_CMD_FUNC(stats)
1735 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1736 SilcServer server = cmd->server;
1737 SilcServerID *server_id;
1740 SilcBuffer packet, stats;
1741 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1744 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1);
1747 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1749 silc_server_command_send_status_reply(cmd, SILC_COMMAND_STATS,
1750 SILC_STATUS_ERR_NO_SERVER_ID, 0);
1753 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1757 /* The ID must be ours */
1758 if (!SILC_ID_SERVER_COMPARE(server->id, server_id)) {
1759 silc_server_command_send_status_data(cmd, SILC_COMMAND_STATS,
1760 SILC_STATUS_ERR_NO_SUCH_SERVER_ID, 0,
1762 silc_free(server_id);
1765 silc_free(server_id);
1767 /* If we are router then just send everything we got. If we are normal
1768 server then we'll send this to our router to get all the latest
1769 statistical information. */
1770 if (!cmd->pending && server->server_type != SILC_ROUTER &&
1771 !server->standalone) {
1772 /* Send request to our router */
1773 SilcBuffer idp = silc_id_payload_encode(server->router->id,
1775 packet = silc_command_payload_encode_va(SILC_COMMAND_STATS,
1776 ++server->cmd_ident, 1,
1777 1, idp->data, idp->len);
1778 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
1779 SILC_PACKET_COMMAND, 0, packet->data,
1780 packet->len, FALSE);
1782 /* Reprocess this packet after received reply from router */
1783 silc_server_command_pending(server, SILC_COMMAND_STATS,
1785 silc_server_command_stats,
1786 silc_server_command_dup(cmd));
1787 cmd->pending = TRUE;
1788 silc_buffer_free(packet);
1789 silc_buffer_free(idp);
1793 /* Send our reply to sender */
1794 uptime = time(NULL) - server->starttime;
1796 stats = silc_buffer_alloc_size(60);
1797 silc_buffer_format(stats,
1798 SILC_STR_UI_INT(server->starttime),
1799 SILC_STR_UI_INT(uptime),
1800 SILC_STR_UI_INT(server->stat.my_clients),
1801 SILC_STR_UI_INT(server->stat.my_channels),
1802 SILC_STR_UI_INT(server->stat.my_server_ops),
1803 SILC_STR_UI_INT(server->stat.my_router_ops),
1804 SILC_STR_UI_INT(server->stat.cell_clients),
1805 SILC_STR_UI_INT(server->stat.cell_channels),
1806 SILC_STR_UI_INT(server->stat.cell_servers),
1807 SILC_STR_UI_INT(server->stat.clients),
1808 SILC_STR_UI_INT(server->stat.channels),
1809 SILC_STR_UI_INT(server->stat.servers),
1810 SILC_STR_UI_INT(server->stat.routers),
1811 SILC_STR_UI_INT(server->stat.server_ops),
1812 SILC_STR_UI_INT(server->stat.router_ops),
1815 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_STATS,
1816 SILC_STATUS_OK, 0, ident, 2,
1818 3, stats->data, stats->len);
1819 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1820 0, packet->data, packet->len, FALSE);
1821 silc_buffer_free(packet);
1822 silc_buffer_free(stats);
1825 silc_server_command_free(cmd);
1828 /* Internal routine to join channel. The channel sent to this function
1829 has been either created or resolved from ID lists. This joins the sent
1830 client to the channel. */
1832 static void silc_server_command_join_channel(SilcServer server,
1833 SilcServerCommandContext cmd,
1834 SilcChannelEntry channel,
1835 SilcClientID *client_id,
1839 const unsigned char *auth,
1840 SilcUInt32 auth_len,
1841 const unsigned char *cauth,
1842 SilcUInt32 cauth_len)
1844 SilcSocketConnection sock = cmd->sock;
1846 SilcUInt32 tmp_len, user_count;
1847 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4], ulimit[4];
1848 SilcClientEntry client;
1849 SilcChannelClientEntry chl;
1850 SilcBuffer reply, chidp, clidp, keyp = NULL;
1851 SilcBuffer user_list, mode_list, invite_list, ban_list;
1852 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1853 char check[512], check2[512];
1854 bool founder = FALSE;
1856 SilcBuffer fkey = NULL, chpklist = NULL;
1859 SILC_LOG_DEBUG(("Joining client to channel"));
1864 /* Get the client entry */
1865 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1866 client = (SilcClientEntry)sock->user_data;
1870 client = silc_server_query_client(server, client_id, FALSE,
1873 if (!resolve || cmd->pending) {
1874 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1875 silc_server_command_send_status_data(
1876 cmd, SILC_COMMAND_JOIN,
1877 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0,
1882 /* The client info is being resolved. Reprocess this packet after
1883 receiving the reply to the query. */
1884 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1886 silc_server_command_join,
1887 silc_server_command_dup(cmd));
1888 cmd->pending = TRUE;
1892 if (!client->data.public_key &&
1893 (auth || cauth || channel->ban_list ||
1894 (channel->mode & SILC_CHANNEL_MODE_INVITE))) {
1895 if (cmd->pending == 2)
1898 /* We must retrieve the client's public key by sending
1899 GETKEY command. Reprocess this packet after receiving the key */
1900 clidp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
1901 silc_server_send_command(server, cmd->sock,
1902 SILC_COMMAND_GETKEY, ++server->cmd_ident,
1903 1, 1, clidp->data, clidp->len);
1904 silc_buffer_free(clidp);
1905 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
1907 silc_server_command_join,
1908 silc_server_command_dup(cmd));
1913 cmd->pending = FALSE;
1917 * Check founder auth payload if provided. If client can gain founder
1918 * privileges it can override various conditions on joining the channel,
1919 * and can have directly the founder mode set on the channel.
1921 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1922 SilcIDListData idata = (SilcIDListData)client;
1923 SilcChannelClientEntry chl2;
1924 SilcHashTableList htl;
1926 if (channel->founder_key && idata->public_key &&
1927 silc_pkcs_public_key_compare(channel->founder_key,
1928 idata->public_key)) {
1929 /* Check whether the client is to become founder */
1930 if (silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
1931 channel->founder_key, 0, server->sha1hash,
1932 client->id, SILC_ID_CLIENT)) {
1934 /* There cannot be anyone else as founder on the channel now. This
1935 client is definitely the founder due to this authentication */
1936 silc_hash_table_list(channel->user_list, &htl);
1937 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
1938 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
1939 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
1940 silc_server_force_cumode_change(server, NULL, channel, chl2,
1944 silc_hash_table_list_reset(&htl);
1946 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
1953 * Check channel modes
1957 memset(check, 0, sizeof(check));
1958 memset(check2, 0, sizeof(check2));
1959 silc_strncat(check, sizeof(check),
1960 client->nickname, strlen(client->nickname));
1961 silc_strncat(check, sizeof(check), "!", 1);
1962 silc_strncat(check, sizeof(check),
1963 client->username, strlen(client->username));
1964 if (!strchr(client->username, '@')) {
1965 silc_strncat(check, sizeof(check), "@", 1);
1966 silc_strncat(check, sizeof(check),
1967 cmd->sock->hostname, strlen(cmd->sock->hostname));
1970 silc_strncat(check2, sizeof(check2),
1971 client->nickname, strlen(client->nickname));
1972 if (!strchr(client->nickname, '@')) {
1973 silc_strncat(check2, sizeof(check2), "@", 1);
1974 silc_strncat(check2, sizeof(check2),
1975 SILC_IS_LOCAL(client) ? server->server_name :
1976 client->router->server_name,
1977 SILC_IS_LOCAL(client) ? strlen(server->server_name) :
1978 strlen(client->router->server_name));
1980 silc_strncat(check2, sizeof(check2), "!", 1);
1981 silc_strncat(check2, sizeof(check2),
1982 client->username, strlen(client->username));
1983 if (!strchr(client->username, '@')) {
1984 silc_strncat(check2, sizeof(check2), "@", 1);
1985 silc_strncat(check2, sizeof(check2),
1986 cmd->sock->hostname, strlen(cmd->sock->hostname));
1989 /* Check invite list if channel is invite-only channel */
1990 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1991 if (!channel->invite_list ||
1992 !silc_hash_table_count(channel->invite_list) ||
1993 (!silc_server_inviteban_match(server, channel->invite_list,
1995 !silc_server_inviteban_match(server, channel->invite_list,
1996 2, client->data.public_key) &&
1997 !silc_server_inviteban_match(server, channel->invite_list,
1998 1, client->nickname) &&
1999 !silc_server_inviteban_match(server, channel->invite_list,
2001 !silc_server_inviteban_match(server, channel->invite_list,
2003 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2004 silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
2005 SILC_STATUS_ERR_NOT_INVITED, 0,
2006 2, chidp->data, chidp->len);
2007 silc_buffer_free(chidp);
2012 /* Check ban list if it exists. If the client's nickname, server,
2013 username and/or hostname is in the ban list the access to the
2014 channel is denied. */
2015 if (channel->ban_list && silc_hash_table_count(channel->ban_list)) {
2016 if (silc_server_inviteban_match(server, channel->ban_list,
2018 silc_server_inviteban_match(server, channel->ban_list,
2019 2, client->data.public_key) ||
2020 silc_server_inviteban_match(server, channel->ban_list,
2021 1, client->nickname) ||
2022 silc_server_inviteban_match(server, channel->ban_list,
2024 silc_server_inviteban_match(server, channel->ban_list,
2026 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2027 silc_server_command_send_status_data(
2028 cmd, SILC_COMMAND_JOIN,
2029 SILC_STATUS_ERR_BANNED_FROM_CHANNEL, 0,
2030 2, chidp->data, chidp->len);
2031 silc_buffer_free(chidp);
2036 /* Check user count limit if set. */
2037 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
2038 if (silc_hash_table_count(channel->user_list) + 1 >
2039 channel->user_limit) {
2040 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2041 silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
2042 SILC_STATUS_ERR_CHANNEL_IS_FULL,
2043 0, 2, chidp->data, chidp->len);
2044 silc_buffer_free(chidp);
2050 /* Check the channel passphrase if set. */
2051 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2052 /* Get passphrase */
2053 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2055 passphrase = silc_memdup(tmp, tmp_len);
2057 if (!passphrase || !channel->passphrase ||
2058 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
2059 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2060 silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
2061 SILC_STATUS_ERR_BAD_PASSWORD, 0,
2062 2, chidp->data, chidp->len);
2063 silc_buffer_free(chidp);
2068 /* Verify channel authentication with channel public keys if set. */
2069 if (channel->mode & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
2070 if (!silc_server_verify_channel_auth(server, channel, client->id,
2071 cauth, cauth_len)) {
2072 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2073 SILC_STATUS_ERR_PERM_DENIED, 0);
2079 * Client is allowed to join to the channel. Make it happen.
2082 /* Check whether the client already is on the channel */
2083 if (silc_server_client_on_channel(client, channel, NULL)) {
2084 clidp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
2085 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2086 silc_server_command_send_status_data2(cmd, SILC_COMMAND_JOIN,
2087 SILC_STATUS_ERR_USER_ON_CHANNEL, 0,
2088 2, clidp->data, clidp->len,
2089 3, chidp->data, chidp->len);
2090 silc_buffer_free(clidp);
2091 silc_buffer_free(chidp);
2095 /* Generate new channel key as protocol dictates */
2097 if (!silc_server_create_channel_key(server, channel, 0))
2100 /* Send the channel key. This is broadcasted to the channel but is not
2101 sent to the client who is joining to the channel. */
2102 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
2103 silc_server_send_channel_key(server, NULL, channel,
2104 server->server_type == SILC_ROUTER ?
2105 FALSE : !server->standalone);
2108 /* Join the client to the channel by adding it to channel's user list.
2109 Add also the channel to client entry's channels list for fast cross-
2111 chl = silc_calloc(1, sizeof(*chl));
2113 chl->client = client;
2114 chl->channel = channel;
2115 silc_hash_table_add(channel->user_list, client, chl);
2116 silc_hash_table_add(client->channels, channel, chl);
2117 channel->user_count++;
2118 channel->disabled = FALSE;
2120 /* Get users on the channel */
2121 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
2124 /* Encode Client ID Payload of the original client who wants to join */
2125 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2127 /* Encode command reply packet */
2128 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2129 SILC_PUT32_MSB(channel->mode, mode);
2130 SILC_PUT32_MSB(created, tmp2);
2131 SILC_PUT32_MSB(user_count, tmp3);
2132 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2133 SILC_PUT32_MSB(channel->user_limit, ulimit);
2135 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
2136 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
2137 cipher = silc_cipher_get_name(channel->channel_key);
2138 keyp = silc_channel_key_payload_encode(silc_id_get_len(channel->id,
2141 strlen(cipher), cipher,
2142 channel->key_len / 8, channel->key);
2146 if (channel->founder_key)
2147 fkey = silc_pkcs_public_key_payload_encode(channel->founder_key);
2149 /* Encode invite list */
2151 if (channel->invite_list && silc_hash_table_count(channel->invite_list)) {
2152 SilcHashTableList htl;
2154 invite_list = silc_buffer_alloc_size(2);
2155 silc_buffer_format(invite_list,
2156 SILC_STR_UI_SHORT(silc_hash_table_count(
2157 channel->invite_list)),
2160 silc_hash_table_list(channel->invite_list, &htl);
2161 while (silc_hash_table_get(&htl, (void *)&tmp_len, (void *)&reply))
2162 invite_list = silc_argument_payload_encode_one(invite_list,
2164 reply->len, tmp_len);
2165 silc_hash_table_list_reset(&htl);
2168 /* Encode ban list */
2170 if (channel->ban_list && silc_hash_table_count(channel->ban_list)) {
2171 SilcHashTableList htl;
2173 ban_list = silc_buffer_alloc_size(2);
2174 silc_buffer_format(ban_list,
2175 SILC_STR_UI_SHORT(silc_hash_table_count(
2176 channel->ban_list)),
2179 silc_hash_table_list(channel->ban_list, &htl);
2180 while (silc_hash_table_get(&htl, (void *)&tmp_len, (void *)&reply))
2181 ban_list = silc_argument_payload_encode_one(ban_list,
2183 reply->len, tmp_len);
2184 silc_hash_table_list_reset(&htl);
2187 if (channel->channel_pubkeys)
2188 chpklist = silc_server_get_channel_pk_list(server, channel, FALSE, FALSE);
2191 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2192 SILC_STATUS_OK, 0, ident, 16,
2193 2, channel->channel_name,
2194 strlen(channel->channel_name),
2195 3, chidp->data, chidp->len,
2196 4, clidp->data, clidp->len,
2199 7, keyp ? keyp->data : NULL,
2200 keyp ? keyp->len : 0,
2201 8, ban_list ? ban_list->data : NULL,
2202 ban_list ? ban_list->len : 0,
2203 9, invite_list ? invite_list->data :
2205 invite_list ? invite_list->len : 0,
2208 strlen(channel->topic) : 0,
2209 11, silc_hmac_get_name(channel->hmac),
2210 strlen(silc_hmac_get_name(channel->
2213 13, user_list->data, user_list->len,
2214 14, mode_list->data,
2216 15, fkey ? fkey->data : NULL,
2217 fkey ? fkey->len : 0,
2218 16, chpklist ? chpklist->data : NULL,
2219 chpklist ? chpklist->len : 0,
2220 17, (channel->mode &
2221 SILC_CHANNEL_MODE_ULIMIT ?
2224 SILC_CHANNEL_MODE_ULIMIT ?
2225 sizeof(ulimit) : 0));
2227 /* Send command reply */
2228 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
2229 reply->data, reply->len, FALSE);
2231 /* Send JOIN notify to locally connected clients on the channel. If
2232 we are normal server then router will send or have sent JOIN notify
2233 already. However since we've added the client already to our channel
2234 we'll ignore it (in packet_receive.c) so we must send it here. If
2235 we are router then this will send it to local clients and local
2237 SILC_LOG_DEBUG(("Send JOIN notify to channel"));
2238 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
2239 SILC_NOTIFY_TYPE_JOIN, 2,
2240 clidp->data, clidp->len,
2241 chidp->data, chidp->len);
2243 /* Update statistics */
2244 server->stat.my_chanclients++;
2245 if (server->server_type == SILC_ROUTER) {
2246 server->stat.cell_chanclients++;
2247 server->stat.chanclients++;
2250 if (!cmd->pending) {
2251 /* Send JOIN notify packet to our primary router */
2252 silc_server_send_notify_join(server, SILC_PRIMARY_ROUTE(server),
2253 SILC_BROADCAST(server), channel, client->id);
2256 /* Distribute the channel key to all backup routers. */
2257 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
2258 keyp->data, keyp->len, FALSE, TRUE);
2260 /* If client became founder by providing correct founder auth data
2261 notify the mode change to the channel. */
2263 SILC_PUT32_MSB(chl->mode, mode);
2264 SILC_LOG_DEBUG(("Send CUMODE_CHANGE notify to channel"));
2265 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
2266 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
2267 clidp->data, clidp->len,
2268 mode, 4, clidp->data, clidp->len,
2269 fkey ? fkey->data : NULL,
2270 fkey ? fkey->len : 0);
2274 /* Set CUMODE notify type to network */
2276 silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
2277 SILC_BROADCAST(server), channel,
2278 chl->mode, client->id, SILC_ID_CLIENT,
2279 client->id, channel->founder_key);
2281 silc_buffer_free(reply);
2282 silc_buffer_free(clidp);
2283 silc_buffer_free(chidp);
2284 silc_buffer_free(keyp);
2285 silc_buffer_free(user_list);
2286 silc_buffer_free(mode_list);
2287 silc_buffer_free(fkey);
2288 silc_buffer_free(chpklist);
2289 silc_buffer_free(invite_list);
2290 silc_buffer_free(ban_list);
2294 memset(passphrase, 0, strlen(passphrase));
2295 silc_free(passphrase);
2298 /* Server side of command JOIN. Joins client into requested channel. If
2299 the channel does not exist it will be created. */
2301 SILC_SERVER_CMD_FUNC(join)
2303 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2304 SilcServer server = cmd->server;
2305 unsigned char *auth, *cauth;
2306 SilcUInt32 tmp_len, auth_len, cauth_len;
2307 char *tmp, *channel_name = NULL, *cipher, *hmac;
2308 SilcChannelEntry channel;
2309 SilcUInt32 umode = 0;
2310 bool created = FALSE, create_key = TRUE;
2311 SilcClientID *client_id;
2313 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 7);
2315 /* Get channel name */
2316 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2318 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2319 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2326 channel_name[255] = '\0';
2328 if (silc_server_name_bad_chchars(channel_name, tmp_len) == TRUE) {
2329 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2330 SILC_STATUS_ERR_BAD_CHANNEL, 0);
2334 /* Get Client ID of the client who is joining to the channel */
2335 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2337 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2338 SILC_STATUS_ERR_NO_CLIENT_ID,
2342 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2344 silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
2345 SILC_STATUS_ERR_BAD_CLIENT_ID, 0,
2350 /* Get cipher, hmac name and auth payload */
2351 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2352 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2353 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
2354 cauth = silc_argument_get_arg_type(cmd->args, 7, &cauth_len);
2356 /* See if the channel exists */
2357 channel = silc_idlist_find_channel_by_name(server->local_list,
2358 channel_name, NULL);
2360 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2361 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2363 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2364 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2369 silc_free(client_id);
2370 client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
2373 (channel->disabled && server->server_type != SILC_ROUTER)) {
2374 /* Channel not found or not valid */
2376 /* If we are standalone server we don't have a router, we just create
2377 the channel by ourselves (unless it existed). */
2378 if (server->standalone) {
2380 channel = silc_server_create_new_channel(server, server->id, cipher,
2381 hmac, channel_name, TRUE);
2383 silc_server_command_send_status_data(
2384 cmd, SILC_COMMAND_JOIN,
2385 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
2386 0, 2, cipher, strlen(cipher));
2387 silc_free(client_id);
2391 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2397 /* The channel does not exist on our server. If we are normal server
2398 we will send JOIN command to our router which will handle the
2399 joining procedure (either creates the channel if it doesn't exist
2400 or joins the client to it). */
2401 if (server->server_type != SILC_ROUTER) {
2403 SilcUInt16 old_ident;
2405 /* If this is pending command callback then we've resolved
2406 it and it didn't work, return since we've notified the
2407 client already in the command reply callback. */
2409 silc_free(client_id);
2413 old_ident = silc_command_get_ident(cmd->payload);
2414 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2415 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2417 /* Send JOIN command to our router */
2418 silc_server_packet_send(server, (SilcSocketConnection)
2419 SILC_PRIMARY_ROUTE(server),
2420 SILC_PACKET_COMMAND, cmd->packet->flags,
2421 tmpbuf->data, tmpbuf->len, TRUE);
2423 /* Reprocess this packet after received reply from router */
2424 silc_server_command_pending(server, SILC_COMMAND_JOIN,
2425 silc_command_get_ident(cmd->payload),
2426 silc_server_command_join,
2427 silc_server_command_dup(cmd));
2428 cmd->pending = TRUE;
2429 silc_command_set_ident(cmd->payload, old_ident);
2430 silc_buffer_free(tmpbuf);
2431 silc_free(client_id);
2435 /* We are router and the channel does not seem exist so we will check
2436 our global list as well for the channel. */
2437 channel = silc_idlist_find_channel_by_name(server->global_list,
2438 channel_name, NULL);
2440 /* Channel really does not exist, create it */
2441 channel = silc_server_create_new_channel(server, server->id, cipher,
2442 hmac, channel_name, TRUE);
2444 silc_server_command_send_status_data(
2445 cmd, SILC_COMMAND_JOIN,
2446 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
2447 2, cipher, strlen(cipher));
2448 silc_free(client_id);
2452 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2460 /* Channel not found */
2462 /* If the command came from router and we are normal server then
2463 something went wrong with the joining as the channel was not found.
2464 We can't do anything else but ignore this. */
2465 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
2466 server->server_type != SILC_ROUTER) {
2467 silc_free(client_id);
2471 /* We are router and the channel does not seem exist so we will check
2472 our global list as well for the channel. */
2473 channel = silc_idlist_find_channel_by_name(server->global_list,
2474 channel_name, NULL);
2476 /* Channel really does not exist, create it */
2477 channel = silc_server_create_new_channel(server, server->id, cipher,
2478 hmac, channel_name, TRUE);
2480 silc_server_command_send_status_data(
2481 cmd, SILC_COMMAND_JOIN,
2482 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
2483 2, cipher, strlen(cipher));
2484 silc_free(client_id);
2488 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2495 /* Check whether the channel was created by our router */
2496 if (cmd->pending && context2) {
2497 SilcServerCommandReplyContext reply = context2;
2499 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
2500 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
2501 SILC_GET32_MSB(created, tmp);
2502 if (silc_argument_get_arg_type(reply->args, 7, NULL))
2503 create_key = FALSE; /* Router returned the key already */
2505 if (silc_command_get_status(reply->payload, NULL, NULL) &&
2506 channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2507 /* Save channel passphrase, if user provided it successfully */
2510 pa = silc_argument_get_arg_type(cmd->args, 3, &pa_len);
2512 silc_free(channel->passphrase);
2513 channel->passphrase = silc_memdup(pa, pa_len);
2518 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
2519 !channel->disabled && !silc_hash_table_count(channel->user_list))
2523 /* If the channel does not have global users and is also empty the client
2524 will be the channel founder and operator. */
2525 if (!channel->disabled &&
2526 !channel->global_users && !silc_hash_table_count(channel->user_list))
2527 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2529 /* Join to the channel */
2530 silc_server_command_join_channel(server, cmd, channel, client_id,
2531 created, create_key, umode,
2532 auth, auth_len, cauth, cauth_len);
2534 silc_free(client_id);
2537 silc_server_command_free(cmd);
2540 /* Server side of command MOTD. Sends server's current "message of the
2541 day" to the client. */
2543 SILC_SERVER_CMD_FUNC(motd)
2545 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2546 SilcServer server = cmd->server;
2547 SilcBuffer packet, idp;
2548 char *motd, *dest_server;
2549 SilcUInt32 motd_len;
2550 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2552 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
2554 /* Get server name */
2555 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2557 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2558 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2563 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
2566 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
2568 if (server->config && server->config->server_info &&
2569 server->config->server_info->motd_file) {
2571 motd = silc_file_readfile(server->config->server_info->motd_file,
2577 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
2580 2, idp->data, idp->len,
2584 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
2587 2, idp->data, idp->len);
2590 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2591 packet->data, packet->len, FALSE);
2592 silc_buffer_free(packet);
2593 silc_buffer_free(idp);
2595 SilcServerEntry entry;
2597 /* Check whether we have this server cached */
2598 entry = silc_idlist_find_server_by_name(server->global_list,
2599 dest_server, TRUE, NULL);
2601 entry = silc_idlist_find_server_by_name(server->local_list,
2602 dest_server, TRUE, NULL);
2605 if (server->server_type != SILC_SERVER && !cmd->pending &&
2606 entry && !entry->motd) {
2607 /* Send to the server */
2609 SilcUInt16 old_ident;
2611 old_ident = silc_command_get_ident(cmd->payload);
2612 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2613 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2615 silc_server_packet_send(server, entry->connection,
2616 SILC_PACKET_COMMAND, cmd->packet->flags,
2617 tmpbuf->data, tmpbuf->len, TRUE);
2619 /* Reprocess this packet after received reply from router */
2620 silc_server_command_pending(server, SILC_COMMAND_MOTD,
2621 silc_command_get_ident(cmd->payload),
2622 silc_server_command_motd,
2623 silc_server_command_dup(cmd));
2624 cmd->pending = TRUE;
2625 silc_command_set_ident(cmd->payload, old_ident);
2626 silc_buffer_free(tmpbuf);
2630 /* Send to primary router only if we don't know the server
2631 * the client requested or if the server is not locally connected */
2632 if ((!entry || !(entry->data.status & SILC_IDLIST_STATUS_LOCAL))
2633 && !cmd->pending && !server->standalone) {
2634 /* Send to the primary router */
2636 SilcUInt16 old_ident;
2638 old_ident = silc_command_get_ident(cmd->payload);
2639 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2640 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2642 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
2643 SILC_PACKET_COMMAND, cmd->packet->flags,
2644 tmpbuf->data, tmpbuf->len, TRUE);
2646 /* Reprocess this packet after received reply from router */
2647 silc_server_command_pending(server, SILC_COMMAND_MOTD,
2648 silc_command_get_ident(cmd->payload),
2649 silc_server_command_motd,
2650 silc_server_command_dup(cmd));
2651 cmd->pending = TRUE;
2652 silc_command_set_ident(cmd->payload, old_ident);
2653 silc_buffer_free(tmpbuf);
2658 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2659 SILC_STATUS_ERR_NO_SUCH_SERVER, 0,
2661 strlen(dest_server));
2665 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2666 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
2667 SILC_STATUS_OK, 0, ident, 2,
2668 2, idp->data, idp->len,
2671 strlen(entry->motd) : 0);
2672 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2673 packet->data, packet->len, FALSE);
2674 silc_buffer_free(packet);
2675 silc_buffer_free(idp);
2679 silc_server_command_free(cmd);
2682 /* Server side of command UMODE. Client can use this command to set/unset
2683 user mode. Client actually cannot set itself to be as server/router
2684 operator so this can be used only to unset the modes. */
2686 SILC_SERVER_CMD_FUNC(umode)
2688 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2689 SilcServer server = cmd->server;
2690 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2692 unsigned char *tmp_mask, m[4];
2693 SilcUInt32 mask = 0;
2694 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2695 bool set_mask = FALSE;
2697 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
2700 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2);
2702 /* Get the client's mode mask */
2703 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2705 SILC_GET32_MSB(mask, tmp_mask);
2710 /* Check that mode changing is allowed. */
2711 if (!silc_server_check_umode_rights(server, client, mask)) {
2712 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2713 SILC_STATUS_ERR_PERM_DENIED, 0);
2717 /* Anonymous mode cannot be set by client */
2718 if (mask & SILC_UMODE_ANONYMOUS &&
2719 !(client->mode & SILC_UMODE_ANONYMOUS)) {
2720 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2721 SILC_STATUS_ERR_PERM_DENIED, 0);
2725 /* Update statistics */
2726 if (mask & SILC_UMODE_GONE) {
2727 if (!(client->mode & SILC_UMODE_GONE))
2728 server->stat.my_aways++;
2730 if (client->mode & SILC_UMODE_GONE)
2731 server->stat.my_aways--;
2734 /* If the client has anonymous mode set, preserve it. */
2735 if (client->mode & SILC_UMODE_ANONYMOUS)
2736 mask |= SILC_UMODE_ANONYMOUS;
2738 /* Change the mode */
2739 client->mode = mask;
2741 /* Send UMODE change to primary router */
2742 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
2743 SILC_BROADCAST(server), client->id,
2746 /* Check if anyone is watching this nickname */
2747 if (server->server_type == SILC_ROUTER)
2748 silc_server_check_watcher_list(server, client, NULL,
2749 SILC_NOTIFY_TYPE_UMODE_CHANGE);
2752 /* Send command reply to sender */
2753 SILC_PUT32_MSB(client->mode, m);
2754 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
2755 SILC_STATUS_OK, 0, ident, 1,
2757 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2758 packet->data, packet->len, FALSE);
2759 silc_buffer_free(packet);
2762 silc_server_command_free(cmd);
2765 /* Server side command of CMODE. Changes channel mode */
2767 SILC_SERVER_CMD_FUNC(cmode)
2769 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2770 SilcServer server = cmd->server;
2771 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2772 SilcIDListData idata = (SilcIDListData)client;
2773 SilcChannelID *channel_id = NULL;
2774 SilcChannelEntry channel;
2775 SilcChannelClientEntry chl;
2776 SilcBuffer packet, cidp;
2777 unsigned char *tmp, *tmp_id, *tmp_mask, *chpkdata = NULL;
2778 char *cipher = NULL, *hmac = NULL, *passphrase = NULL, ulimit[4];
2779 SilcUInt32 mode_mask = 0, old_mask = 0, tmp_len, tmp_len2, chpklen;
2780 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2781 bool set_mask = FALSE, set_chpk = FALSE;
2782 SilcPublicKey founder_key = NULL;
2783 SilcBuffer fkey = NULL, chpklist = NULL;
2784 SilcBufferStruct chpk;
2787 silc_server_command_free(cmd);
2791 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 9);
2793 /* Get Channel ID */
2794 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2796 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2797 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2798 silc_server_command_free(cmd);
2801 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
2803 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2804 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2805 silc_server_command_free(cmd);
2809 /* Get channel entry */
2810 channel = silc_idlist_find_channel_by_id(server->local_list,
2813 channel = silc_idlist_find_channel_by_id(server->global_list,
2816 silc_server_command_send_status_data(cmd, SILC_COMMAND_CMODE,
2817 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
2818 0, 2, tmp_id, tmp_len2);
2819 silc_free(channel_id);
2820 silc_server_command_free(cmd);
2824 old_mask = channel->mode;
2826 /* Get the channel mode mask */
2827 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2829 SILC_GET32_MSB(mode_mask, tmp_mask);
2833 /* Check whether this client is on the channel */
2834 if (!silc_server_client_on_channel(client, channel, &chl)) {
2835 silc_server_command_send_status_data(cmd, SILC_COMMAND_CMODE,
2836 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
2837 2, tmp_id, tmp_len2);
2841 /* Check that client has rights to change any requested channel modes */
2842 if (set_mask && !silc_server_check_cmode_rights(server, channel, chl,
2844 SILC_LOG_DEBUG(("Client does not have rights to change mode"));
2845 silc_server_command_send_status_data(
2846 cmd, SILC_COMMAND_CMODE,
2847 (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) ?
2848 SILC_STATUS_ERR_NO_CHANNEL_PRIV :
2849 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV), 0,
2850 2, tmp_id, tmp_len2);
2854 /* If mode mask was not sent as argument then merely return the current
2855 mode mask, founder key and channel public key list to the sender. */
2858 SILC_PUT32_MSB(channel->mode, m);
2859 if (channel->founder_key)
2860 fkey = silc_pkcs_public_key_payload_encode(channel->founder_key);
2861 if (channel->channel_pubkeys)
2862 chpklist = silc_server_get_channel_pk_list(server, channel,
2865 silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2866 SILC_STATUS_OK, 0, ident, 4,
2867 2, tmp_id, tmp_len2,
2869 4, fkey ? fkey->data : NULL,
2870 fkey ? fkey->len : 0,
2871 5, chpklist ? chpklist->data : NULL,
2872 chpklist ? chpklist->len : 0);
2873 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2874 packet->data, packet->len, FALSE);
2875 silc_buffer_free(packet);
2880 * Check the modes. Modes that requires nothing special operation are
2884 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2885 /* Channel uses private keys to protect traffic. Client(s) has set the
2886 key locally they want to use, server does not know that key. */
2887 /* Nothing interesting to do here */
2889 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2890 /* The mode is removed and we need to generate and distribute
2891 new channel key. Clients are not using private channel keys
2892 anymore after this. */
2894 /* Re-generate channel key */
2895 if (!silc_server_create_channel_key(server, channel, 0))
2898 /* Send the channel key. This sends it to our local clients and if
2899 we are normal server to our router as well. */
2900 silc_server_send_channel_key(server, NULL, channel,
2901 server->server_type == SILC_ROUTER ?
2902 FALSE : !server->standalone);
2904 cipher = (char *)silc_cipher_get_name(channel->channel_key);
2905 hmac = (char *)silc_hmac_get_name(channel->hmac);
2909 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2910 /* User limit is set on channel */
2911 SilcUInt32 user_limit;
2913 /* Get user limit */
2914 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2916 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2917 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2918 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
2922 SILC_GET32_MSB(user_limit, tmp);
2923 channel->user_limit = user_limit;
2926 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2927 /* User limit mode is unset. Remove user limit */
2928 channel->user_limit = 0;
2931 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
2932 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
2933 /* Passphrase has been set to channel */
2935 /* Get the passphrase */
2936 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
2938 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2939 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
2943 /* Save the passphrase */
2944 passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
2947 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2948 /* Passphrase mode is unset. remove the passphrase */
2949 silc_free(channel->passphrase);
2950 channel->passphrase = NULL;
2954 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
2955 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
2956 /* Cipher to use protect the traffic */
2957 SilcCipher newkey, oldkey;
2960 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
2962 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2963 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
2967 /* Delete old cipher and allocate the new one */
2968 if (!silc_cipher_alloc(cipher, &newkey)) {
2969 silc_server_command_send_status_data(
2970 cmd, SILC_COMMAND_CMODE,
2971 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
2972 2, cipher, strlen(cipher));
2976 oldkey = channel->channel_key;
2977 channel->channel_key = newkey;
2979 /* Re-generate channel key */
2980 if (!silc_server_create_channel_key(server, channel, 0)) {
2981 /* We don't have new key, revert to old one */
2982 channel->channel_key = oldkey;
2986 /* Remove old channel key for good */
2987 silc_cipher_free(oldkey);
2989 /* Send the channel key. This sends it to our local clients and if
2990 we are normal server to our router as well. */
2991 silc_server_send_channel_key(server, NULL, channel,
2992 server->server_type == SILC_ROUTER ?
2993 FALSE : !server->standalone);
2996 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2997 /* Cipher mode is unset. Remove the cipher and revert back to
2999 SilcCipher newkey, oldkey;
3000 cipher = channel->cipher;
3002 /* Delete old cipher and allocate default one */
3003 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
3004 silc_server_command_send_status_data(
3005 cmd, SILC_COMMAND_CMODE,
3006 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
3007 2, cipher, strlen(cipher));
3011 oldkey = channel->channel_key;
3012 channel->channel_key = newkey;
3014 /* Re-generate channel key */
3015 if (!silc_server_create_channel_key(server, channel, 0)) {
3016 /* We don't have new key, revert to old one */
3017 channel->channel_key = oldkey;
3021 /* Remove old channel key for good */
3022 silc_cipher_free(oldkey);
3024 /* Send the channel key. This sends it to our local clients and if
3025 we are normal server to our router as well. */
3026 silc_server_send_channel_key(server, NULL, channel,
3027 server->server_type == SILC_ROUTER ?
3028 FALSE : !server->standalone);
3032 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3033 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3034 /* HMAC to use protect the traffic */
3035 unsigned char hash[32];
3039 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3041 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3042 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3046 /* Delete old hmac and allocate the new one */
3047 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
3048 silc_server_command_send_status_data(
3049 cmd, SILC_COMMAND_CMODE,
3050 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
3051 2, hmac, strlen(hmac));
3055 silc_hmac_free(channel->hmac);
3056 channel->hmac = newhmac;
3058 /* Set the HMAC key out of current channel key. The client must do
3060 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
3061 channel->key_len / 8, hash);
3062 silc_hmac_set_key(channel->hmac, hash,
3063 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3064 memset(hash, 0, sizeof(hash));
3067 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
3068 /* Hmac mode is unset. Remove the hmac and revert back to
3071 unsigned char hash[32];
3072 hmac = channel->hmac_name;
3074 /* Delete old hmac and allocate default one */
3075 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
3076 silc_server_command_send_status_data(
3077 cmd, SILC_COMMAND_CMODE,
3078 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0,
3079 2, hmac, strlen(hmac));
3083 silc_hmac_free(channel->hmac);
3084 channel->hmac = newhmac;
3086 /* Set the HMAC key out of current channel key. The client must do
3088 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
3089 channel->key_len / 8,
3091 silc_hmac_set_key(channel->hmac, hash,
3092 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3093 memset(hash, 0, sizeof(hash));
3097 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3098 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3099 /* Check if the founder public key was received */
3100 founder_key = idata->public_key;
3101 tmp = silc_argument_get_arg_type(cmd->args, 8, &tmp_len);
3103 if (!silc_pkcs_public_key_payload_decode(tmp, tmp_len, &founder_key)) {
3104 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3105 SILC_STATUS_ERR_AUTH_FAILED,
3110 /* If key was not sent and the channel mode has already founder
3111 then the key was not to be changed. */
3112 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)
3116 /* Set the founder authentication */
3117 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
3119 silc_server_command_send_status_reply(
3120 cmd, SILC_COMMAND_CMODE,
3121 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3125 /* Verify the payload before setting the mode */
3126 if (!silc_auth_verify_data(tmp, tmp_len, SILC_AUTH_PUBLIC_KEY,
3127 founder_key, 0, server->sha1hash,
3128 client->id, SILC_ID_CLIENT)) {
3129 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3130 SILC_STATUS_ERR_AUTH_FAILED,
3135 /* Save the public key */
3136 if (channel->founder_key)
3137 silc_pkcs_public_key_free(channel->founder_key);
3138 if (silc_argument_get_arg_type(cmd->args, 8, NULL))
3139 channel->founder_key = founder_key;
3141 channel->founder_key = silc_pkcs_public_key_copy(founder_key);
3142 if (!channel->founder_key) {
3143 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3144 SILC_STATUS_ERR_AUTH_FAILED,
3149 fkey = silc_pkcs_public_key_payload_encode(channel->founder_key);
3151 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3152 SILC_STATUS_ERR_AUTH_FAILED,
3154 silc_pkcs_public_key_free(channel->founder_key);
3155 channel->founder_key = NULL;
3160 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3161 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3162 if (channel->founder_key)
3163 silc_pkcs_public_key_free(channel->founder_key);
3164 channel->founder_key = NULL;
3170 if (mode_mask & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
3171 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3174 chpkdata = silc_argument_get_arg_type(cmd->args, 9, &chpklen);
3176 if (!chpkdata && channel->mode & SILC_CHANNEL_MODE_CHANNEL_AUTH)
3181 /* Process the channel public key(s) */
3182 st = silc_server_set_channel_pk_list(server, NULL, channel,
3184 if (st != SILC_STATUS_OK) {
3185 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE, st, 0);
3190 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3191 if (channel->mode & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
3192 if (channel->channel_pubkeys)
3193 silc_hash_table_free(channel->channel_pubkeys);
3194 channel->channel_pubkeys = NULL;
3201 /* Finally, set the mode */
3202 old_mask = channel->mode = mode_mask;
3204 /* Send CMODE_CHANGE notify. */
3205 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3206 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT)
3207 SILC_PUT32_MSB(channel->user_limit, ulimit);
3208 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
3209 SILC_NOTIFY_TYPE_CMODE_CHANGE, 8,
3210 cidp->data, cidp->len,
3212 cipher, cipher ? strlen(cipher) : 0,
3213 hmac, hmac ? strlen(hmac) : 0,
3214 passphrase, passphrase ?
3215 strlen(passphrase) : 0,
3216 fkey ? fkey->data : NULL,
3217 fkey ? fkey->len : 0,
3218 chpkdata ? chpkdata : NULL,
3219 chpkdata ? chpklen : 0,
3220 mode_mask & SILC_CHANNEL_MODE_ULIMIT ?
3222 mode_mask & SILC_CHANNEL_MODE_ULIMIT ?
3223 sizeof(ulimit) : 0);
3225 /* Set CMODE notify type to network */
3226 if (chpkdata && chpklen)
3227 silc_buffer_set(&chpk, chpkdata, chpklen);
3228 silc_server_send_notify_cmode(server, SILC_PRIMARY_ROUTE(server),
3229 SILC_BROADCAST(server), channel,
3230 mode_mask, client->id, SILC_ID_CLIENT,
3231 cipher, hmac, passphrase, founder_key,
3232 chpkdata ? &chpk : NULL);
3235 chpklist = silc_server_get_channel_pk_list(server, channel, FALSE, FALSE);
3237 /* Send command reply to sender */
3238 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3239 SILC_STATUS_OK, 0, ident, 5,
3240 2, tmp_id, tmp_len2,
3242 4, fkey ? fkey->data : NULL,
3243 fkey ? fkey->len : 0,
3244 5, chpklist ? chpklist->data :
3245 NULL, chpklist ? chpklist->len
3248 SILC_CHANNEL_MODE_ULIMIT ?
3251 SILC_CHANNEL_MODE_ULIMIT ?
3252 sizeof(ulimit) : 0));
3254 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3255 packet->data, packet->len, FALSE);
3257 silc_buffer_free(packet);
3258 silc_buffer_free(cidp);
3261 channel->mode = old_mask;
3262 silc_buffer_free(chpklist);
3263 silc_buffer_free(fkey);
3264 silc_free(channel_id);
3265 silc_server_command_free(cmd);
3268 /* Server side of CUMODE command. Changes client's mode on a channel. */
3270 SILC_SERVER_CMD_FUNC(cumode)
3272 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3273 SilcServer server = cmd->server;
3274 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3275 SilcChannelID *channel_id = NULL;
3276 SilcClientID *client_id = NULL;
3277 SilcChannelEntry channel;
3278 SilcClientEntry target_client;
3279 SilcChannelClientEntry chl;
3280 SilcBuffer packet, idp;
3281 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
3282 SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
3284 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3285 SilcPublicKey founder_key = NULL;
3286 SilcBuffer fkey = NULL;
3291 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
3293 /* Get Channel ID */
3294 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3296 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3297 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3300 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
3302 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3303 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3307 /* Get channel entry */
3308 channel = silc_idlist_find_channel_by_id(server->local_list,
3311 channel = silc_idlist_find_channel_by_id(server->global_list,
3314 silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3315 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
3316 0, 2, tmp_ch_id, tmp_ch_len);
3321 /* Check whether sender is on the channel */
3322 if (!silc_server_client_on_channel(client, channel, &chl)) {
3323 silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3324 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
3325 2, tmp_ch_id, tmp_ch_len);
3328 sender_mask = chl->mode;
3330 /* Get the target client's channel mode mask */
3331 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3333 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3334 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3338 SILC_GET32_MSB(target_mask, tmp_mask);
3340 /* Get target Client ID */
3341 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3343 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3344 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
3347 client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
3349 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3350 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
3354 /* Get target client's entry */
3355 target_client = silc_idlist_find_client_by_id(server->local_list,
3356 client_id, TRUE, NULL);
3358 target_client = silc_idlist_find_client_by_id(server->global_list,
3359 client_id, TRUE, NULL);
3361 if (target_client != client &&
3362 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
3363 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
3364 silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3365 SILC_STATUS_ERR_NOT_YOU, 0,
3366 2, tmp_ch_id, tmp_ch_len);
3370 /* Check whether target client is on the channel */
3371 if (target_client != client) {
3372 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
3373 silc_server_command_send_status_data2(
3374 cmd, SILC_COMMAND_CUMODE,
3375 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL, 0,
3377 3, tmp_ch_id, tmp_ch_len);
3386 /* If the target client is founder, no one else can change their mode
3388 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
3389 silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3390 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
3391 0, 2, tmp_ch_id, tmp_ch_len);
3395 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
3396 if (target_client != client) {
3397 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3398 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
3403 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
3404 /* The client tries to claim the founder rights. */
3405 unsigned char *tmp_auth;
3406 SilcUInt32 tmp_auth_len;
3407 SilcChannelClientEntry chl2;
3408 SilcHashTableList htl;
3410 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
3411 !channel->founder_key) {
3412 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3413 SILC_STATUS_ERR_AUTH_FAILED, 0);
3417 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
3419 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3420 SILC_STATUS_ERR_AUTH_FAILED, 0);
3424 /* Verify the authentication payload */
3425 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len, SILC_AUTH_PUBLIC_KEY,
3426 channel->founder_key, 0, server->sha1hash,
3427 client->id, SILC_ID_CLIENT)) {
3428 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3429 SILC_STATUS_ERR_AUTH_FAILED, 0);
3434 founder_key = channel->founder_key;
3435 fkey = silc_pkcs_public_key_payload_encode(founder_key);
3437 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3438 SILC_STATUS_ERR_AUTH_FAILED, 0);
3442 /* There cannot be anyone else as founder on the channel now. This
3443 client is definitely the founder due to this authentication. This
3444 is done only on router, not on server, since server cannot know
3445 whether router will accept this mode change or not. XXX This
3446 probably shouldn't be done anymore at all, may cause problems in
3447 router-router connections too (maybe just AUTH_FAILED error should
3448 be returned). -Pekka */
3449 if (server->server_type == SILC_ROUTER) {
3450 silc_hash_table_list(channel->user_list, &htl);
3451 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
3452 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
3453 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3454 silc_server_force_cumode_change(server, NULL, channel, chl2,
3458 silc_hash_table_list_reset(&htl);
3461 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
3464 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3465 if (target_client == client) {
3466 /* Remove channel founder rights from itself */
3467 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3470 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3471 SILC_STATUS_ERR_NOT_YOU, 0);
3477 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
3478 /* Promote to operator */
3479 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3480 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3481 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3482 silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3483 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
3484 0, 2, tmp_ch_id, tmp_ch_len);
3488 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
3492 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
3493 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3494 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3495 silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
3496 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
3497 0, 2, tmp_ch_id, tmp_ch_len);
3501 /* Demote to normal user */
3502 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
3507 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
3508 if (target_client != client) {
3509 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3510 SILC_STATUS_ERR_NOT_YOU, 0);
3514 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
3515 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
3519 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
3520 if (target_client != client) {
3521 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3522 SILC_STATUS_ERR_NOT_YOU, 0);
3526 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
3531 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
3532 if (target_client != client) {
3533 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3534 SILC_STATUS_ERR_NOT_YOU, 0);
3538 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)) {
3539 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
3543 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
3544 if (target_client != client) {
3545 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3546 SILC_STATUS_ERR_NOT_YOU, 0);
3550 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
3555 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
3556 if (target_client != client) {
3557 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3558 SILC_STATUS_ERR_NOT_YOU, 0);
3562 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)) {
3563 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
3567 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
3568 if (target_client != client) {
3569 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3570 SILC_STATUS_ERR_NOT_YOU, 0);
3574 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
3579 if (target_mask & SILC_CHANNEL_UMODE_QUIET) {
3580 if (!(chl->mode & SILC_CHANNEL_UMODE_QUIET)) {
3581 if (client == target_client) {
3582 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3583 SILC_STATUS_ERR_PERM_DENIED, 0);
3586 chl->mode |= SILC_CHANNEL_UMODE_QUIET;
3590 if (chl->mode & SILC_CHANNEL_UMODE_QUIET) {
3591 if (client == target_client) {
3592 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3593 SILC_STATUS_ERR_PERM_DENIED, 0);
3596 chl->mode &= ~SILC_CHANNEL_UMODE_QUIET;
3601 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3602 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3604 /* Send notify to channel, notify only if mode was actually changed. */
3606 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
3607 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
3608 idp->data, idp->len,
3611 fkey ? fkey->data : NULL,
3612 fkey ? fkey->len : 0);
3614 /* Set CUMODE notify type to network */
3615 silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
3616 SILC_BROADCAST(server), channel,
3617 target_mask, client->id, SILC_ID_CLIENT,
3618 target_client->id, founder_key);
3621 /* Send command reply to sender */
3622 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
3623 SILC_STATUS_OK, 0, ident, 3,
3625 3, tmp_ch_id, tmp_ch_len,
3626 4, tmp_id, tmp_len);
3627 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3628 packet->data, packet->len, FALSE);
3630 silc_buffer_free(packet);
3631 silc_buffer_free(idp);
3634 silc_free(channel_id);
3635 silc_free(client_id);
3636 silc_buffer_free(fkey);
3637 silc_server_command_free(cmd);
3640 /* Server side of KICK command. Kicks client out of channel. */
3642 SILC_SERVER_CMD_FUNC(kick)
3644 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3645 SilcServer server = cmd->server;
3646 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3647 SilcClientEntry target_client;
3648 SilcChannelID *channel_id;
3649 SilcClientID *client_id;
3650 SilcChannelEntry channel;
3651 SilcChannelClientEntry chl;
3652 SilcBuffer idp, packet;
3653 SilcUInt32 tmp_len, target_idp_len, clen;
3654 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3655 unsigned char *tmp, *comment, *target_idp;
3660 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
3662 /* Get Channel ID */
3663 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3665 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3666 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3669 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3671 silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3672 SILC_STATUS_ERR_BAD_CHANNEL_ID, 0,
3677 /* Get channel entry */
3678 channel = silc_idlist_find_channel_by_id(server->local_list,
3681 channel = silc_idlist_find_channel_by_id(server->local_list,
3684 silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3685 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
3686 0, 2, tmp, tmp_len);
3691 /* Check whether sender is on the channel */
3692 if (!silc_server_client_on_channel(client, channel, &chl)) {
3693 silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3694 SILC_STATUS_ERR_NOT_ON_CHANNEL,
3695 0, 2, tmp, tmp_len);
3699 /* Check that the kicker is channel operator or channel founder */
3700 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
3701 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
3702 silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3703 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
3704 0, 2, tmp, tmp_len);
3708 /* Get target Client ID */
3709 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
3711 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3712 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
3715 client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
3717 silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3718 SILC_STATUS_ERR_BAD_CLIENT_ID,
3719 0, 2, target_idp, target_idp_len);
3723 /* Get target client's entry */
3724 target_client = silc_idlist_find_client_by_id(server->local_list,
3725 client_id, TRUE, NULL);
3726 if (!target_client) {
3727 target_client = silc_idlist_find_client_by_id(server->global_list,
3728 client_id, TRUE, NULL);
3731 /* Check whether target client is on the channel */
3732 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
3733 silc_server_command_send_status_data2(cmd, SILC_COMMAND_KICK,
3734 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL,
3735 0, 2, target_idp, target_idp_len,
3740 /* Check that the target client is not channel founder. Channel founder
3741 cannot be kicked from the channel. */
3742 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3743 silc_server_command_send_status_data(cmd, SILC_COMMAND_KICK,
3744 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
3745 0, 2, tmp, tmp_len);
3750 comment = silc_argument_get_arg_type(cmd->args, 3, &clen);
3755 /* Send the reply back to the client */
3757 silc_command_reply_payload_encode_va(SILC_COMMAND_KICK,
3758 SILC_STATUS_OK, 0, ident, 2,
3760 3, target_idp, target_idp_len);
3761 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3762 packet->data, packet->len, FALSE);
3763 silc_buffer_free(packet);
3765 /* Send KICKED notify to local clients on the channel */
3766 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3767 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
3768 SILC_NOTIFY_TYPE_KICKED, 3,
3769 target_idp, target_idp_len,
3770 comment, comment ? strlen(comment) : 0,
3771 idp->data, idp->len);
3772 silc_buffer_free(idp);
3774 /* Send KICKED notify to primary route */
3775 silc_server_send_notify_kicked(server, SILC_PRIMARY_ROUTE(server),
3776 SILC_BROADCAST(server), channel,
3777 target_client->id, client->id, comment);
3779 /* Remove the client from channel's invite list */
3780 if (channel->invite_list && silc_hash_table_count(channel->invite_list)) {
3782 silc_argument_payload_encode_one(NULL, target_idp, target_idp_len, 3);
3783 SilcArgumentPayload args =
3784 silc_argument_payload_parse(ab->data, ab->len, 1);
3785 silc_server_inviteban_process(server, channel->invite_list, 1, args);
3786 silc_buffer_free(ab);
3787 silc_argument_payload_free(args);
3790 /* Remove the client from the channel. If the channel does not exist
3791 after removing the client then the client kicked itself off the channel
3792 and we don't have to send anything after that. */
3793 if (!silc_server_remove_from_one_channel(server, NULL, channel,
3794 target_client, FALSE))
3797 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3798 /* Re-generate channel key */
3799 if (!silc_server_create_channel_key(server, channel, 0))
3802 /* Send the channel key to the channel. The key of course is not sent
3803 to the client who was kicked off the channel. */
3804 silc_server_send_channel_key(server, target_client->connection, channel,
3805 server->server_type == SILC_ROUTER ?
3806 FALSE : !server->standalone);
3810 silc_server_command_free(cmd);
3813 /* Server side of OPER command. Client uses this comand to obtain server
3814 operator privileges to this server/router. */
3816 SILC_SERVER_CMD_FUNC(oper)
3818 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3819 SilcServer server = cmd->server;
3820 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3821 unsigned char *username, *auth;
3823 SilcServerConfigAdmin *admin;
3824 SilcIDListData idata = (SilcIDListData)client;
3825 bool result = FALSE;
3826 SilcPublicKey cached_key;
3828 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
3831 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
3833 /* Get the username */
3834 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3836 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3837 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3842 /* Get the admin configuration */
3843 admin = silc_server_config_find_admin(server, cmd->sock->ip,
3844 username, client->nickname);
3846 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
3847 username, client->nickname);
3849 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3850 SILC_STATUS_ERR_AUTH_FAILED,
3852 SILC_LOG_INFO(("OPER authentication failed for username '%s' by "
3853 "nickname '%s' from %s", username,
3854 client->nickname, cmd->sock->hostname));
3859 /* Get the authentication payload */
3860 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3862 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3863 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3868 /* Verify the authentication data. If both passphrase and public key
3869 is set then try both of them. */
3870 if (admin->passphrase)
3871 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
3872 admin->passphrase, admin->passphrase_len,
3873 idata->hash, client->id, SILC_ID_CLIENT);
3874 if (!result && admin->publickeys) {
3875 cached_key = silc_server_get_public_key(server, admin->publickeys);
3878 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
3879 cached_key, 0, idata->hash,
3880 client->id, SILC_ID_CLIENT);
3883 /* Authentication failed */
3884 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3885 SILC_STATUS_ERR_AUTH_FAILED,
3890 /* Client is now server operator */
3891 client->mode |= SILC_UMODE_SERVER_OPERATOR;
3893 /* Update statistics */
3894 if (SILC_IS_LOCAL(client))
3895 server->stat.my_server_ops++;
3896 if (server->server_type == SILC_ROUTER)
3897 server->stat.server_ops++;
3899 /* Send UMODE change to primary router */
3900 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
3901 SILC_BROADCAST(server), client->id,
3904 /* Check if anyone is watching this nickname */
3905 if (server->server_type == SILC_ROUTER)
3906 silc_server_check_watcher_list(server, client, NULL,
3907 SILC_NOTIFY_TYPE_UMODE_CHANGE);
3909 /* Send reply to the sender */
3910 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3914 silc_server_command_free(cmd);
3917 SILC_TASK_CALLBACK(silc_server_command_detach_cb)
3919 SilcServer server = app_context;
3920 QuitInternal q = (QuitInternal)context;
3921 SilcClientID *client_id = (SilcClientID *)q->sock;
3922 SilcClientEntry client;
3923 SilcSocketConnection sock;
3925 client = silc_idlist_find_client_by_id(server->local_list, client_id,
3927 if (client && client->connection) {
3928 sock = client->connection;
3930 /* If there is pending outgoing data for the client then purge it
3931 to the network before closing connection. */
3932 silc_server_packet_queue_purge(server, sock);
3934 /* Close the connection on our side */
3935 client->router = NULL;
3936 client->connection = NULL;
3937 sock->user_data = NULL;
3938 silc_server_close_connection(server, sock);
3941 silc_free(client_id);
3945 SILC_TASK_CALLBACK(silc_server_command_detach_timeout)
3947 SilcServer server = app_context;
3948 QuitInternal q = (QuitInternal)context;
3949 SilcClientID *client_id = (SilcClientID *)q->sock;
3950 SilcClientEntry client;
3952 client = silc_idlist_find_client_by_id(server->local_list, client_id,
3954 if (client && client->mode & SILC_UMODE_DETACHED) {
3955 SILC_LOG_DEBUG(("Detach timeout"));
3956 silc_server_free_client_data(server, NULL, client, TRUE,
3960 silc_free(client_id);
3964 /* Server side of DETACH command. Detached the client from the network
3965 by closing the connection but preserving the session. */
3967 SILC_SERVER_CMD_FUNC(detach)
3969 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3970 SilcServer server = cmd->server;
3971 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3974 if (server->config->detach_disabled) {
3975 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
3976 SILC_STATUS_ERR_OPERATION_ALLOWED,
3981 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
3984 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
3986 /* Remove operator privileges, since the client may resume in some
3987 other server which to it does not have operator privileges. */
3988 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
3989 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
3991 /* Send the user mode notify to notify that client is detached */
3992 client->mode |= SILC_UMODE_DETACHED;
3993 client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
3994 client->data.status &= ~SILC_IDLIST_STATUS_NOATTR;
3995 client->last_command = 0;
3996 client->fast_command = 0;
3997 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
3998 SILC_BROADCAST(server), client->id,
4000 server->stat.my_detached++;
4002 /* Check if anyone is watching this nickname */
4003 if (server->server_type == SILC_ROUTER)
4004 silc_server_check_watcher_list(server, client, NULL,
4005 SILC_NOTIFY_TYPE_UMODE_CHANGE);
4007 q = silc_calloc(1, sizeof(*q));
4008 q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
4009 silc_schedule_task_add(server->schedule, 0, silc_server_command_detach_cb,
4010 q, 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
4012 if (server->config->detach_timeout) {
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,
4016 silc_server_command_detach_timeout,
4017 q, server->config->detach_timeout * 60,
4018 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
4021 /* Send reply to the sender */
4022 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
4026 silc_server_command_free(cmd);
4029 /* Server side of WATCH command. */
4031 SILC_SERVER_CMD_FUNC(watch)
4033 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4034 SilcServer server = cmd->server;
4035 char *add_nick, *del_nick;
4036 SilcUInt32 add_nick_len, del_nick_len, tmp_len, pk_len;
4038 unsigned char hash[16], *tmp, *pk;
4039 SilcClientEntry client;
4040 SilcClientID *client_id = NULL;
4042 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WATCH, cmd, 1, 3);
4044 if (server->server_type != SILC_ROUTER && !server->standalone) {
4045 if (!cmd->pending) {
4046 /* Send the command to router */
4048 SilcUInt16 old_ident;
4050 SILC_LOG_DEBUG(("Forwarding WATCH to router"));
4052 old_ident = silc_command_get_ident(cmd->payload);
4053 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4054 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4056 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
4057 SILC_PACKET_COMMAND, cmd->packet->flags,
4058 tmpbuf->data, tmpbuf->len, TRUE);
4060 /* Reprocess this packet after received reply from router */
4061 silc_server_command_pending(server, SILC_COMMAND_WATCH,
4062 silc_command_get_ident(cmd->payload),
4063 silc_server_command_watch,
4064 silc_server_command_dup(cmd));
4065 cmd->pending = TRUE;
4066 silc_command_set_ident(cmd->payload, old_ident);
4067 silc_buffer_free(tmpbuf);
4068 } else if (context2) {
4069 /* Received reply from router, just send same data to the client. */
4070 SilcServerCommandReplyContext reply = context2;
4073 SILC_LOG_DEBUG(("Received reply to WATCH from router"));
4074 silc_command_get_status(reply->payload, &status, NULL);
4075 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, status,
4082 /* We are router and keep the watch list for local cell */
4084 /* Get the client ID */
4085 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4087 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4088 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4092 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4094 silc_server_command_send_status_data(cmd, SILC_COMMAND_WATCH,
4095 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
4096 0, 2, tmp, tmp_len);
4100 /* Get the client entry which must be in local list */
4101 client = silc_idlist_find_client_by_id(server->local_list,
4102 client_id, TRUE, NULL);
4104 silc_server_command_send_status_data(cmd, SILC_COMMAND_WATCH,
4105 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0,
4110 /* Take public key for watching by public key */
4111 pk = silc_argument_get_arg_type(cmd->args, 4, &pk_len);
4114 add_nick = silc_argument_get_arg_type(cmd->args, 2, &add_nick_len);
4115 del_nick = silc_argument_get_arg_type(cmd->args, 3, &del_nick_len);
4116 if (!add_nick && !del_nick && !pk) {
4117 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4118 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4123 if (add_nick && add_nick_len > 128)
4124 add_nick[128] = '\0';
4125 if (del_nick && del_nick_len > 128)
4126 del_nick[128] = '\0';
4128 memset(nick, 0, sizeof(nick));
4130 /* Add new nickname to be watched in our cell */
4132 if (silc_server_name_bad_chars(add_nick, strlen(add_nick)) == TRUE) {
4133 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4134 SILC_STATUS_ERR_BAD_NICKNAME, 0);
4138 /* Hash the nick, we have the hash saved, not nicks because we can
4139 do one to one mapping to the nick from Client ID hash this way. */
4140 silc_to_lower(add_nick, nick, sizeof(nick) - 1);
4141 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
4143 /* Check whether this client is already watching this nickname */
4144 if (silc_hash_table_find_by_context(server->watcher_list, hash,
4146 /* Nickname is alredy being watched for this client */
4147 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4148 SILC_STATUS_ERR_NICKNAME_IN_USE,
4153 /* Get the nickname from the watcher list and use the same key in
4154 new entries as well. If key doesn't exist then create it. */
4155 if (!silc_hash_table_find(server->watcher_list, hash, (void *)&tmp, NULL))
4156 tmp = silc_memdup(hash, CLIENTID_HASH_LEN);
4158 /* Add the client to the watcher list with the specified nickname hash. */
4159 silc_hash_table_add(server->watcher_list, tmp, client);
4162 /* Delete nickname from watch list */
4164 if (silc_server_name_bad_chars(del_nick, strlen(del_nick)) == TRUE) {
4165 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4166 SILC_STATUS_ERR_BAD_NICKNAME, 0);
4170 /* Hash the nick, we have the hash saved, not nicks because we can
4171 do one to one mapping to the nick from Client ID hash this way. */
4172 silc_to_lower(del_nick, nick, sizeof(nick) - 1);
4173 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
4175 /* Check that this client is watching for this nickname */
4176 if (!silc_hash_table_find_by_context(server->watcher_list, hash,
4177 client, (void *)&tmp)) {
4178 /* Nickname is alredy being watched for this client */
4179 silc_server_command_send_status_data(cmd, SILC_COMMAND_WATCH,
4180 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
4181 2, nick, strlen(nick));
4185 /* Delete the nickname from the watcher list. */
4186 silc_hash_table_del_by_context(server->watcher_list, hash, client);
4188 /* Now check whether there still exists entries with this key, if not
4189 then free the key to not leak memory. */
4190 if (!silc_hash_table_find(server->watcher_list, hash, NULL, NULL))
4194 /* Add/del public key */
4197 SilcArgumentPayload pkargs;
4199 SilcPublicKey public_key, pkkey;
4202 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4203 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4208 /* Get the argument from the Argument List Payload */
4209 SILC_GET16_MSB(pkargc, pk);
4210 pkargs = silc_argument_payload_parse(pk + 2, pk_len - 2, pkargc);
4212 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4213 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4218 pk = silc_argument_get_next_arg(pkargs, &type, &pk_len);
4220 if (!silc_pkcs_public_key_payload_decode(pk, pk_len, &public_key))
4226 /* Add public key to watch list */
4228 /* Check whether this client is already watching this public key */
4229 if (silc_hash_table_find_by_context(server->watcher_list_pk,
4230 public_key, client, NULL)) {
4231 silc_pkcs_public_key_free(public_key);
4232 silc_server_command_send_status_reply(
4233 cmd, SILC_COMMAND_WATCH,
4234 SILC_STATUS_ERR_NICKNAME_IN_USE, 0);
4238 /* Get the public key from the watcher list and use the same key in
4239 new entries as well. If key doesn't exist then create it. */
4241 if (!silc_hash_table_find(server->watcher_list_pk, public_key,
4242 (void *)&pkkey, NULL))
4245 silc_pkcs_public_key_free(public_key);
4247 /* Add the client to the watcher list with the specified public
4249 silc_hash_table_add(server->watcher_list_pk, pkkey, client);
4251 } else if (type == 0x01) {
4252 /* Delete public key from watch list */
4254 /* Check that this client is watching this public key */
4255 if (silc_hash_table_find_by_context(server->watcher_list_pk,
4258 silc_pkcs_public_key_free(public_key);
4259 silc_server_command_send_status_reply(
4260 cmd, SILC_COMMAND_WATCH,
4261 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4265 /* Delete the public key from the watcher list. */
4266 silc_hash_table_del_by_context(server->watcher_list_pk,
4267 public_key, client);
4269 /* Now check whether there still exists entries with this key, if
4270 not then free the key to not leak memory. */
4271 if (!silc_hash_table_find(server->watcher_list_pk, hash, NULL, NULL))
4272 silc_pkcs_public_key_free(pkkey);
4273 silc_pkcs_public_key_free(public_key);
4276 pk = silc_argument_get_next_arg(pkargs, &type, &pk_len);
4280 /* Distribute the watch list to backup routers too */
4281 if (server->backup) {
4283 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4284 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4285 silc_server_backup_send(server, NULL, SILC_PACKET_COMMAND,
4286 cmd->packet->flags, tmpbuf->data, tmpbuf->len,
4288 silc_buffer_free(tmpbuf);
4291 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4295 silc_free(client_id);
4296 silc_server_command_free(cmd);
4299 /* Server side of SILCOPER command. Client uses this comand to obtain router
4300 operator privileges to this router. */
4302 SILC_SERVER_CMD_FUNC(silcoper)
4304 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4305 SilcServer server = cmd->server;
4306 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4307 unsigned char *username, *auth;
4309 SilcServerConfigAdmin *admin;
4310 SilcIDListData idata = (SilcIDListData)client;
4311 bool result = FALSE;
4312 SilcPublicKey cached_key;
4314 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
4317 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4319 if (server->server_type != SILC_ROUTER) {
4320 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4321 SILC_STATUS_ERR_AUTH_FAILED, 0);
4325 /* Get the username */
4326 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4328 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4329 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4334 /* Get the admin configuration */
4335 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4336 username, client->nickname);
4338 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4339 username, client->nickname);
4341 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4342 SILC_STATUS_ERR_AUTH_FAILED, 0);
4343 SILC_LOG_INFO(("SILCOPER authentication failed for username '%s' by "
4344 "nickname '%s' from %s", username,
4345 client->nickname, cmd->sock->hostname));
4350 /* Get the authentication payload */
4351 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4353 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4354 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4359 /* Verify the authentication data. If both passphrase and public key
4360 is set then try both of them. */
4361 if (admin->passphrase)
4362 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4363 admin->passphrase, admin->passphrase_len,
4364 idata->hash, client->id, SILC_ID_CLIENT);
4365 if (!result && admin->publickeys) {
4366 cached_key = silc_server_get_public_key(server, admin->publickeys);
4369 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4370 cached_key, 0, idata->hash,
4371 client->id, SILC_ID_CLIENT);
4374 /* Authentication failed */
4375 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4376 SILC_STATUS_ERR_AUTH_FAILED, 0);
4380 /* Client is now router operator */
4381 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4383 /* Update statistics */
4384 if (SILC_IS_LOCAL(client))
4385 server->stat.my_router_ops++;
4386 if (server->server_type == SILC_ROUTER)
4387 server->stat.router_ops++;
4389 /* Send UMODE change to primary router */
4390 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
4391 SILC_BROADCAST(server), client->id,
4394 /* Check if anyone is watching this nickname */
4395 if (server->server_type == SILC_ROUTER)
4396 silc_server_check_watcher_list(server, client, NULL,
4397 SILC_NOTIFY_TYPE_UMODE_CHANGE);
4399 /* Send reply to the sender */
4400 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4404 silc_server_command_free(cmd);
4407 /* Server side of command BAN. This is used to manage the ban list of the
4408 channel. To add clients and remove clients from the ban list. */
4410 SILC_SERVER_CMD_FUNC(ban)
4412 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4413 SilcServer server = cmd->server;
4414 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4415 SilcBuffer packet, list, tmp2;
4416 SilcChannelEntry channel;
4417 SilcChannelClientEntry chl;
4418 SilcChannelID *channel_id = NULL;
4419 unsigned char *id, *tmp, *atype = NULL;
4420 SilcUInt32 id_len, len, len2;
4421 SilcArgumentPayload args;
4422 SilcHashTableList htl;
4424 SilcUInt16 argc = 0, ident = silc_command_get_ident(cmd->payload);
4425 SilcBufferStruct blist;
4427 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
4430 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4432 /* Get Channel ID */
4433 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4435 channel_id = silc_id_payload_parse_id(id, id_len, NULL);
4437 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4438 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4443 /* Get channel entry. The server must know about the channel since the
4444 client is expected to be on the channel. */
4445 channel = silc_idlist_find_channel_by_id(server->local_list,
4448 channel = silc_idlist_find_channel_by_id(server->global_list,
4451 silc_server_command_send_status_data(cmd, SILC_COMMAND_BAN,
4452 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
4458 /* Check whether this client is on the channel */
4459 if (!silc_server_client_on_channel(client, channel, &chl)) {
4460 silc_server_command_send_status_data(cmd, SILC_COMMAND_BAN,
4461 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
4466 /* The client must be at least channel operator. */
4467 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4468 silc_server_command_send_status_data(cmd, SILC_COMMAND_BAN,
4469 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0,
4474 /* Get the ban information */
4475 tmp = silc_argument_get_arg_type(cmd->args, 3, &len2);
4476 if (tmp && len2 > 2) {
4477 /* Parse the arguments to see they are constructed correctly */
4478 SILC_GET16_MSB(argc, tmp);
4479 args = silc_argument_payload_parse(tmp + 2, len2 - 2, argc);
4481 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4482 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4487 /* Get the type of action */
4488 atype = silc_argument_get_arg_type(cmd->args, 2, &len);
4489 if (atype && len == 1) {
4490 if (atype[0] == 0x00) {
4491 /* Allocate hash table for ban list if it doesn't exist yet */
4492 if (!channel->ban_list)
4494 silc_hash_table_alloc(0, silc_hash_ptr,
4496 silc_server_inviteban_destruct, channel,
4499 /* Check for resource limit */
4500 if (silc_hash_table_count(channel->ban_list) > 64) {
4501 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4502 SILC_STATUS_ERR_RESOURCE_LIMIT,
4508 /* Now add or delete the information. */
4509 silc_server_inviteban_process(server, channel->ban_list,
4510 (SilcUInt8)atype[0], args);
4512 silc_argument_payload_free(args);
4515 /* Encode ban list */
4517 if (channel->ban_list && silc_hash_table_count(channel->ban_list)) {
4518 list = silc_buffer_alloc_size(2);
4519 silc_buffer_format(list,
4520 SILC_STR_UI_SHORT(silc_hash_table_count(
4521 channel->ban_list)),
4523 silc_hash_table_list(channel->ban_list, &htl);
4524 while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2))
4525 list = silc_argument_payload_encode_one(list, tmp2->data, tmp2->len,
4527 silc_hash_table_list_reset(&htl);
4530 /* Send BAN notify type to local servers (but not clients) and to
4532 if (atype && tmp && len2) {
4533 silc_buffer_set(&blist, tmp, len2);
4535 /* Send to local servers if we are router */
4536 if (server->server_type == SILC_ROUTER)
4537 silc_server_send_notify_to_channel(server, NULL, channel, FALSE, FALSE,
4538 SILC_NOTIFY_TYPE_BAN, 3,
4541 tmp ? blist.data : NULL,
4542 tmp ? blist.len : 0);
4544 /* Send to network. */
4545 silc_server_send_notify_ban(server, SILC_PRIMARY_ROUTE(server),
4546 SILC_BROADCAST(server), channel, atype,
4550 /* Send the reply back to the client */
4552 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4553 SILC_STATUS_OK, 0, ident, 2,
4555 3, list ? list->data : NULL,
4556 list ? list->len : 0);
4557 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4558 packet->data, packet->len, FALSE);
4560 silc_buffer_free(packet);
4561 silc_buffer_free(list);
4564 silc_free(channel_id);
4565 silc_server_command_free(cmd);
4568 /* Server side command of LEAVE. Removes client from a channel. */
4570 SILC_SERVER_CMD_FUNC(leave)
4572 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4573 SilcServer server = cmd->server;
4574 SilcSocketConnection sock = cmd->sock;
4575 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4576 SilcChannelID *id = NULL;
4577 SilcChannelEntry channel;
4581 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !id_entry)
4584 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4586 /* Get Channel ID */
4587 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4589 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4590 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4593 id = silc_id_payload_parse_id(tmp, len, NULL);
4595 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4596 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4600 /* Get channel entry */
4601 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4603 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4605 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4606 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
4612 /* Check whether this client is on the channel */
4613 if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
4614 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4615 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0,
4620 /* Notify routers that they should remove this client from their list
4621 of clients on the channel. Send LEAVE notify type. */
4622 silc_server_send_notify_leave(server, SILC_PRIMARY_ROUTE(server),
4623 SILC_BROADCAST(server), channel, id_entry->id);
4625 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4626 SILC_STATUS_OK, 0, 2, tmp, len);
4628 /* Remove client from channel */
4629 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4631 /* If the channel does not exist anymore we won't send anything */
4634 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4635 /* Re-generate channel key */
4636 if (!silc_server_create_channel_key(server, channel, 0))
4639 /* Send the channel key */
4640 silc_server_send_channel_key(server, NULL, channel,
4641 server->server_type == SILC_ROUTER ?
4642 FALSE : !server->standalone);
4647 silc_server_command_free(cmd);
4650 /* Server side of command USERS. Resolves clients and their USERS currently
4651 joined on the requested channel. The list of Client ID's and their modes
4652 on the channel is sent back. */
4654 SILC_SERVER_CMD_FUNC(users)
4656 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4657 SilcServer server = cmd->server;
4658 SilcChannelEntry channel;
4659 SilcChannelID *id = NULL;
4660 SilcBuffer packet, idp;
4661 unsigned char *channel_id;
4662 SilcUInt32 channel_id_len;
4663 SilcBuffer client_id_list;
4664 SilcBuffer client_mode_list;
4665 unsigned char lc[4];
4666 SilcUInt32 list_count = 0;
4667 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4670 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
4672 /* Get Channel ID */
4673 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4675 /* Get channel name */
4676 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
4678 if (!channel_id && !channel_name) {
4679 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4680 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4685 id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
4687 silc_server_command_send_status_data(cmd, SILC_COMMAND_USERS,
4688 SILC_STATUS_ERR_BAD_CHANNEL_ID, 0,
4689 2, channel_id, channel_id_len);
4694 /* If we are server and we don't know about this channel we will send
4695 the command to our router. If we know about the channel then we also
4696 have the list of users already. */
4698 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4700 channel = silc_idlist_find_channel_by_name(server->local_list,
4701 channel_name, NULL);
4703 if (!channel || (!server->standalone && (channel->disabled ||
4704 !channel->users_resolved))) {
4705 if (server->server_type != SILC_ROUTER && !server->standalone &&
4709 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4710 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4712 /* Send USERS command */
4713 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
4714 SILC_PACKET_COMMAND, cmd->packet->flags,
4715 tmpbuf->data, tmpbuf->len, TRUE);
4717 /* Reprocess this packet after received reply */
4718 silc_server_command_pending(server, SILC_COMMAND_USERS,
4719 silc_command_get_ident(cmd->payload),
4720 silc_server_command_users,
4721 silc_server_command_dup(cmd));
4722 cmd->pending = TRUE;
4723 silc_command_set_ident(cmd->payload, ident);
4724 silc_buffer_free(tmpbuf);
4729 /* Check the global list as well. */
4731 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4733 channel = silc_idlist_find_channel_by_name(server->global_list,
4734 channel_name, NULL);
4736 /* Channel really does not exist */
4738 silc_server_command_send_status_data(
4739 cmd, SILC_COMMAND_USERS,
4740 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID, 0,
4741 2, channel_id, channel_id_len);
4743 silc_server_command_send_status_data(
4744 cmd, SILC_COMMAND_USERS,
4745 SILC_STATUS_ERR_NO_SUCH_CHANNEL, 0,
4746 2, channel_name, strlen(channel_name));
4751 /* If the channel is private or secret do not send anything, unless the
4752 user requesting this command is on the channel or is server */
4753 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
4754 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
4755 && !silc_server_client_on_channel(cmd->sock->user_data, channel,
4757 silc_server_command_send_status_data(cmd, SILC_COMMAND_USERS,
4758 SILC_STATUS_ERR_NO_SUCH_CHANNEL, 0,
4759 2, channel->channel_name,
4760 strlen(channel->channel_name));
4765 /* Get the users list */
4766 if (!silc_server_get_users_on_channel(server, channel, &client_id_list,
4767 &client_mode_list, &list_count)) {
4769 client_id_list = NULL;
4770 client_mode_list = NULL;
4774 SILC_PUT32_MSB(list_count, lc);
4777 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
4778 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
4779 SILC_STATUS_OK, 0, ident, 4,
4780 2, idp->data, idp->len,
4783 client_id_list->data : NULL,
4785 client_id_list->len : 0,
4786 5, client_mode_list ?
4787 client_mode_list->data : NULL,
4789 client_mode_list->len : 0);
4790 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4791 packet->data, packet->len, FALSE);
4793 silc_buffer_free(idp);
4794 silc_buffer_free(packet);
4796 silc_buffer_free(client_id_list);
4797 if (client_mode_list)
4798 silc_buffer_free(client_mode_list);
4802 silc_server_command_free(cmd);
4805 /* Server side of command GETKEY. This fetches the client's public key
4806 from the server where to the client is connected. */
4808 SILC_SERVER_CMD_FUNC(getkey)
4810 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4811 SilcServer server = cmd->server;
4813 SilcClientEntry client;
4814 SilcServerEntry server_entry;
4815 SilcClientID *client_id = NULL;
4816 SilcServerID *server_id = NULL;
4817 SilcIDPayload idp = NULL;
4818 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4821 SilcBuffer pk = NULL;
4823 SilcPublicKey public_key;
4825 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4827 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4828 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4832 idp = silc_id_payload_parse(tmp, tmp_len);
4834 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4835 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4840 id_type = silc_id_payload_get_type(idp);
4841 if (id_type == SILC_ID_CLIENT) {
4842 client_id = silc_id_payload_get_id(idp);
4844 /* If the client is not found from local list there is no chance it
4845 would be locally connected client so send the command further. */
4846 client = silc_idlist_find_client_by_id(server->local_list,
4847 client_id, TRUE, NULL);
4849 client = silc_idlist_find_client_by_id(server->global_list,
4850 client_id, TRUE, NULL);
4852 if ((!client && !cmd->pending && !server->standalone) ||
4853 (client && !client->connection && !cmd->pending &&
4854 !(client->mode & SILC_UMODE_DETACHED)) ||
4855 (client && !client->data.public_key && !cmd->pending)) {
4857 SilcUInt16 old_ident;
4858 SilcSocketConnection dest_sock;
4860 dest_sock = silc_server_get_client_route(server, NULL, 0,
4861 client_id, NULL, NULL);
4865 old_ident = silc_command_get_ident(cmd->payload);
4866 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4867 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4869 silc_server_packet_send(server, dest_sock,
4870 SILC_PACKET_COMMAND, cmd->packet->flags,
4871 tmpbuf->data, tmpbuf->len, TRUE);
4873 /* Reprocess this packet after received reply from router */
4874 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
4875 silc_command_get_ident(cmd->payload),
4876 silc_server_command_getkey,
4877 silc_server_command_dup(cmd));
4878 cmd->pending = TRUE;
4879 silc_command_set_ident(cmd->payload, old_ident);
4880 silc_buffer_free(tmpbuf);
4885 silc_server_command_send_status_data(cmd, SILC_COMMAND_GETKEY,
4886 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
4887 0, 2, tmp, tmp_len);
4891 /* The client is locally connected, just get the public key and
4892 send it back. If they key does not exist then do not send it,
4893 send just OK reply */
4894 public_key = client->data.public_key;
4896 pk = silc_pkcs_public_key_payload_encode(public_key);
4897 } else if (id_type == SILC_ID_SERVER) {
4898 server_id = silc_id_payload_get_id(idp);
4900 /* If the server is not found from local list there is no chance it
4901 would be locally connected server so send the command further. */
4902 server_entry = silc_idlist_find_server_by_id(server->local_list,
4903 server_id, TRUE, NULL);
4905 server_entry = silc_idlist_find_server_by_id(server->global_list,
4906 server_id, TRUE, NULL);
4908 if (server_entry != server->id_entry &&
4909 ((!server_entry && !cmd->pending && !server->standalone) ||
4910 (server_entry && !server_entry->connection && !cmd->pending &&
4911 !server->standalone) ||
4912 (server_entry && !server_entry->data.public_key && !cmd->pending &&
4913 !server->standalone))) {
4915 SilcUInt16 old_ident;
4917 old_ident = silc_command_get_ident(cmd->payload);
4918 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4919 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4921 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
4922 SILC_PACKET_COMMAND, cmd->packet->flags,
4923 tmpbuf->data, tmpbuf->len, TRUE);
4925 /* Reprocess this packet after received reply from router */
4926 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
4927 silc_command_get_ident(cmd->payload),
4928 silc_server_command_getkey,
4929 silc_server_command_dup(cmd));
4930 cmd->pending = TRUE;
4931 silc_command_set_ident(cmd->payload, old_ident);
4932 silc_buffer_free(tmpbuf);
4936 if (!server_entry) {
4937 silc_server_command_send_status_data(cmd, SILC_COMMAND_GETKEY,
4938 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
4939 0, 2, tmp, tmp_len);
4943 /* If they key does not exist then do not send it, send just OK reply */
4944 public_key = (!server_entry->data.public_key ?
4945 (server_entry == server->id_entry ? server->public_key :
4946 NULL) : server_entry->data.public_key);
4948 pk = silc_pkcs_public_key_payload_encode(public_key);
4953 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4954 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
4955 SILC_STATUS_OK, 0, ident, 2,
4957 3, pk ? pk->data : NULL,
4959 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4960 packet->data, packet->len, FALSE);
4961 silc_buffer_free(packet);
4965 silc_id_payload_free(idp);
4966 silc_buffer_free(pk);
4967 silc_free(client_id);
4968 silc_free(server_id);
4969 silc_server_command_free(cmd);
4973 /* Private range commands, specific to this implementation */
4975 /* Server side command of CONNECT. Connects us to the specified remote
4976 server or router. */
4978 SILC_SERVER_CMD_FUNC(connect)
4980 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4981 SilcServer server = cmd->server;
4982 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4983 unsigned char *tmp, *host;
4985 SilcUInt32 port = SILC_PORT;
4987 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
4990 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
4992 /* Check whether client has the permissions. */
4993 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
4994 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
4995 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
4996 SILC_STATUS_ERR_NO_SERVER_PRIV, 0);
5000 if (server->server_type == SILC_ROUTER && !server->backup_router &&
5001 client->mode & SILC_UMODE_SERVER_OPERATOR) {
5002 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5003 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
5007 /* Get the remote server */
5008 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5010 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5011 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5017 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5019 SILC_GET32_MSB(port, tmp);
5021 /* Create the connection. It is done with timeout and is async. */
5022 silc_server_create_connection(server, host, port);
5024 /* Send reply to the sender */
5025 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5029 silc_server_command_free(cmd);
5032 /* Server side command of CLOSE. Closes connection to a specified server. */
5034 SILC_SERVER_CMD_FUNC(close)
5036 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5037 SilcServer server = cmd->server;
5038 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5039 SilcServerEntry server_entry;
5040 SilcSocketConnection sock;
5043 unsigned char *name;
5044 SilcUInt32 port = SILC_PORT;
5046 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
5049 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
5051 /* Check whether client has the permissions. */
5052 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5053 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5054 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5055 SILC_STATUS_ERR_NO_SERVER_PRIV,
5060 /* Get the remote server */
5061 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5063 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5064 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5070 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5072 SILC_GET32_MSB(port, tmp);
5074 server_entry = silc_idlist_find_server_by_conn(server->local_list,
5075 name, port, TRUE, NULL);
5077 server_entry = silc_idlist_find_server_by_conn(server->global_list,
5078 name, port, TRUE, NULL);
5079 if (!server_entry) {
5080 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5081 SILC_STATUS_ERR_NO_SERVER_ID, 0);
5085 if (server_entry == server->id_entry) {
5086 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5087 SILC_STATUS_ERR_NO_SERVER_ID, 0);
5091 /* Send reply to the sender */
5092 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5095 /* Close the connection to the server */
5096 sock = (SilcSocketConnection)server_entry->connection;
5098 if (server_entry->server_type == SILC_BACKUP_ROUTER) {
5099 server->backup_closed = TRUE;
5100 silc_server_backup_del(server, server_entry);
5103 server->backup_noswitch = TRUE;
5104 if (server->router == server_entry) {
5105 server->id_entry->router = NULL;
5106 server->router = NULL;
5107 server->standalone = TRUE;
5109 silc_server_disconnect_remote(server, sock,
5110 SILC_STATUS_ERR_BANNED_FROM_SERVER,
5111 "Closed by administrator");
5112 if (sock->user_data)
5113 silc_server_free_sock_user_data(server, sock, NULL);
5114 server->backup_noswitch = FALSE;
5117 silc_server_command_free(cmd);
5120 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
5121 active connections. */
5123 SILC_SERVER_CMD_FUNC(shutdown)
5125 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5126 SilcServer server = cmd->server;
5127 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5129 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
5132 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
5134 /* Check whether client has the permission. */
5135 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5136 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5137 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5138 SILC_STATUS_ERR_NO_SERVER_PRIV,
5143 /* Send reply to the sender */
5144 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5147 /* Then, gracefully, or not, bring the server down. */
5148 silc_server_stop(server);
5152 silc_server_command_free(cmd);