5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2002 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, packet dropped"));
210 silc_packet_context_free(packet);
211 silc_socket_free(ctx->sock);
215 ctx->args = silc_command_get_args(ctx->payload);
217 /* Get the command */
218 command = silc_command_get(ctx->payload);
219 for (cmd = silc_command_list; cmd->cb; cmd++)
220 if (cmd->cmd == command)
223 if (!cmd || !cmd->cb) {
224 SILC_LOG_DEBUG(("Unknown command %d", command));
225 silc_server_command_send_status_reply(ctx, command,
226 SILC_STATUS_ERR_UNKNOWN_COMMAND, 0);
227 silc_server_command_free(ctx);
231 /* Execute client's commands always with timeout. Normally they are
232 executed with zero (0) timeout but if client is sending command more
233 frequently than once in 2 seconds, then the timeout may be 0 to 2
235 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
236 SilcClientEntry client = (SilcClientEntry)sock->user_data;
237 SilcServerCommandTimeout timeout;
241 SILC_LOG_DEBUG(("Client entry is invalid"));
242 silc_server_command_free(ctx);
246 timeout = silc_calloc(1, sizeof(*timeout));
250 if (client->last_command && (time(NULL) - client->last_command) < 2) {
251 client->fast_command++;
254 if (client->fast_command - 2 <= 0)
255 client->fast_command = 0;
257 client->fast_command -= 2;
261 if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
262 (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
263 silc_schedule_task_add(server->schedule, sock->sock,
264 silc_server_command_process_timeout, timeout,
265 (client->fast_command < 3 ? 0 :
266 2 - (time(NULL) - client->last_command)),
267 (client->fast_command < 3 ? 200000 : 0),
268 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
270 silc_schedule_task_add(server->schedule, sock->sock,
271 silc_server_command_process_timeout, timeout,
272 0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
276 /* Execute for server */
278 if (!(cmd->flags & SILC_CF_REG)) {
279 SILC_LOG_DEBUG(("Calling %s command", silc_get_command_name(cmd->cmd)));
281 } else if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) {
282 SILC_LOG_DEBUG(("Calling %s command", silc_get_command_name(cmd->cmd)));
285 SILC_LOG_DEBUG(("Server is not registered"));
286 silc_server_command_free(ctx);
290 /* Allocate Command Context */
292 SilcServerCommandContext silc_server_command_alloc()
294 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
299 /* Free's the command context allocated before executing the command */
301 void silc_server_command_free(SilcServerCommandContext ctx)
304 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
306 if (ctx->users < 1) {
308 silc_command_payload_free(ctx->payload);
310 silc_packet_context_free(ctx->packet);
312 silc_socket_free(ctx->sock); /* Decrease reference counter */
317 /* Duplicate Command Context by adding reference counter. The context won't
318 be free'd untill it hits zero. */
320 SilcServerCommandContext
321 silc_server_command_dup(SilcServerCommandContext ctx)
324 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
329 /* Timeout for pending command. If reply to pending command never arrives
330 this is called to free resources. */
332 SILC_TASK_CALLBACK(silc_server_command_pending_timeout)
334 SilcServer server = app_context;
335 SilcServerCommandPending *reply = context;
336 SilcServerCommandReplyContext cmdr;
340 SILC_LOG_DEBUG(("Timeout pending command"));
342 /* Allocate temporary and bogus command reply context */
343 cmdr = silc_calloc(1, sizeof(*cmdr));
344 cmdr->server = server;
345 cmdr->ident = reply->ident;
347 /* Check for pending commands and mark to be exeucted */
349 silc_server_command_pending_check(server, reply->reply_cmd,
350 reply->ident, &cmdr->callbacks_count);
352 /* Create bogus command reply with an error inside */
354 silc_command_reply_payload_encode_va(reply->reply_cmd ? reply->reply_cmd :
355 SILC_COMMAND_RESERVED,
356 SILC_STATUS_ERR_TIMEDOUT, 0,
358 cmdr->payload = silc_command_payload_parse(tmpreply->data, tmpreply->len);
359 silc_buffer_free(tmpreply);
361 /* Call all callbacks. Same as SILC_SERVER_PENDING_EXEC macro. */
362 for (i = 0; i < cmdr->callbacks_count; i++)
363 if (cmdr->callbacks[i].callback)
364 (*cmdr->callbacks[i].callback)(cmdr->callbacks[i].context, cmdr);
366 silc_server_command_pending_del(server, reply->reply_cmd, reply->ident);
367 silc_server_command_reply_free(cmdr);
370 /* Add new pending command to be executed when reply to a command has been
371 received. The `reply_cmd' is the command that will call the `callback'
372 with `context' when reply has been received. It can be SILC_COMMAND_NONE
373 to match any command with the `ident'. If `ident' is non-zero
374 the `callback' will be executed when received reply with command
375 identifier `ident'. If there already exists pending command for the
376 specified command, ident, callback and context this function has no
379 bool silc_server_command_pending(SilcServer server,
380 SilcCommand reply_cmd,
382 SilcCommandCb callback,
385 return silc_server_command_pending_timed(server, reply_cmd, ident, callback,
389 /* Same as silc_server_command_pending with specific timeout for pending
390 commands. If the `timeout' is zero default timeout is used. */
392 bool silc_server_command_pending_timed(SilcServer server,
393 SilcCommand reply_cmd,
395 SilcCommandCb callback,
399 SilcServerCommandPending *reply;
401 /* Check whether identical pending already exists for same command,
402 ident, callback and callback context. If it does then it would be
403 error to register it again. */
404 silc_dlist_start(server->pending_commands);
405 while ((reply = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
406 if (reply->reply_cmd == reply_cmd && reply->ident == ident &&
407 reply->callback == callback && reply->context == context)
411 reply = silc_calloc(1, sizeof(*reply));
412 reply->reply_cmd = reply_cmd;
413 reply->ident = ident;
414 reply->context = context;
415 reply->callback = callback;
417 silc_schedule_task_add(server->schedule, 0,
418 silc_server_command_pending_timeout, reply,
419 timeout ? timeout : 10, 0,
420 SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
421 silc_dlist_add(server->pending_commands, reply);
426 /* Deletes pending command by reply command type. */
428 void silc_server_command_pending_del(SilcServer server,
429 SilcCommand reply_cmd,
432 SilcServerCommandPending *r;
434 silc_dlist_start(server->pending_commands);
435 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
436 if ((r->reply_cmd == reply_cmd || (r->reply_cmd == SILC_COMMAND_NONE &&
438 && r->ident == ident) {
439 silc_dlist_del(server->pending_commands, r);
441 silc_schedule_task_del(server->schedule, r->timeout);
447 /* Checks for pending commands and marks callbacks to be called from
448 the command reply function. Returns TRUE if there were pending command. */
450 SilcServerCommandPendingCallbacks
451 silc_server_command_pending_check(SilcServer server,
454 SilcUInt32 *callbacks_count)
456 SilcServerCommandPending *r;
457 SilcServerCommandPendingCallbacks callbacks = NULL;
460 silc_dlist_start(server->pending_commands);
461 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
462 if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE)
463 && r->ident == ident) {
464 callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
465 callbacks[i].context = r->context;
466 callbacks[i].callback = r->callback;
467 r->reply_check = TRUE;
472 *callbacks_count = i;
476 /* Sends simple status message as command reply packet */
479 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
486 SILC_LOG_DEBUG(("Sending command status %d", status));
489 silc_command_reply_payload_encode_va(command, status, error,
490 silc_command_get_ident(cmd->payload),
492 silc_server_packet_send(cmd->server, cmd->sock,
493 SILC_PACKET_COMMAND_REPLY, 0,
494 buffer->data, buffer->len, FALSE);
495 silc_buffer_free(buffer);
498 /* Sends command status reply with one extra argument. The argument
499 type must be sent as argument. */
502 silc_server_command_send_status_data(SilcServerCommandContext cmd,
507 const unsigned char *arg,
512 SILC_LOG_DEBUG(("Sending command status %d", status));
515 silc_command_reply_payload_encode_va(command, status, 0,
516 silc_command_get_ident(cmd->payload),
517 1, arg_type, arg, arg_len);
518 silc_server_packet_send(cmd->server, cmd->sock,
519 SILC_PACKET_COMMAND_REPLY, 0,
520 buffer->data, buffer->len, FALSE);
521 silc_buffer_free(buffer);
524 /* This function can be called to check whether in the command reply
525 an error occurred. This function has no effect if this is called
526 when the command function was not called as pending command callback.
527 This returns TRUE if error had occurred. */
530 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
531 SilcServerCommandReplyContext cmdr,
534 if (!cmd->pending || !cmdr)
537 if (!silc_command_get_status(cmdr->payload, NULL, NULL)) {
540 /* Send the same command reply payload */
541 silc_command_set_command(cmdr->payload, silc_command_get(cmd->payload));
542 silc_command_set_ident(cmdr->payload,
543 silc_command_get_ident(cmd->payload));
544 buffer = silc_command_payload_encode_payload(cmdr->payload);
545 silc_server_packet_send(cmd->server, cmd->sock,
546 SILC_PACKET_COMMAND_REPLY, 0,
547 buffer->data, buffer->len, FALSE);
548 silc_buffer_free(buffer);
555 /* Server side of command WHOIS. */
557 SILC_SERVER_CMD_FUNC(whois)
559 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
560 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 256);
561 silc_server_query_command(cmd->server, SILC_COMMAND_WHOIS, cmd);
562 silc_server_command_free(cmd);
565 /* Server side of command WHOWAS. */
567 SILC_SERVER_CMD_FUNC(whowas)
569 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
570 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
571 silc_server_query_command(cmd->server, SILC_COMMAND_WHOWAS, cmd);
572 silc_server_command_free(cmd);
575 /* Server side of command IDENTIFY. */
577 SILC_SERVER_CMD_FUNC(identify)
579 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
580 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 256);
581 silc_server_query_command(cmd->server, SILC_COMMAND_IDENTIFY, cmd);
582 silc_server_command_free(cmd);
585 /* Server side of command NICK. Sets nickname for user. Setting
586 nickname causes generation of a new client ID for the client. The
587 new client ID is sent to the client after changing the nickname. */
589 SILC_SERVER_CMD_FUNC(nick)
591 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
592 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
593 SilcServer server = cmd->server;
594 SilcBuffer packet, nidp, oidp = NULL;
595 SilcClientID *new_id;
598 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
601 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
604 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
607 nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
609 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
610 SILC_STATUS_ERR_BAD_NICKNAME, 0);
615 if (silc_server_name_bad_chars(nick, nick_len) == TRUE) {
616 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
617 SILC_STATUS_ERR_BAD_NICKNAME, 0);
621 /* Check for same nickname */
622 if (!strcmp(client->nickname, nick)) {
623 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
627 /* Create new Client ID */
628 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
630 cmd->server->md5hash, nick,
634 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
635 SILC_STATUS_ERR_BAD_NICKNAME, 0);
638 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
641 /* Send notify about nickname change to our router. We send the new
642 ID and ask to replace it with the old one. If we are router the
643 packet is broadcasted. Send NICK_CHANGE notify. */
644 silc_server_send_notify_nick_change(server, SILC_PRIMARY_ROUTE(server),
645 SILC_BROADCAST(server), client->id,
648 /* Check if anyone is watching the old nickname */
649 if (server->server_type == SILC_ROUTER)
650 silc_server_check_watcher_list(server, client, nick,
651 SILC_NOTIFY_TYPE_NICK_CHANGE);
653 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
655 /* Remove old cache entry */
656 silc_idcache_del_by_context(server->local_list->clients, client);
658 silc_free(client->id);
661 silc_free(client->nickname);
662 client->nickname = strdup(nick);
664 /* Update client cache */
665 silc_idcache_add(server->local_list->clients, client->nickname,
666 client->id, (void *)client, 0, NULL);
668 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
670 /* Send NICK_CHANGE notify to the client's channels */
671 silc_server_send_notify_on_channels(server, NULL, client,
672 SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
673 oidp->data, oidp->len,
674 nidp->data, nidp->len,
676 strlen(client->nickname));
678 /* Check if anyone is watching the new nickname */
679 if (server->server_type == SILC_ROUTER)
680 silc_server_check_watcher_list(server, client, NULL,
681 SILC_NOTIFY_TYPE_NICK_CHANGE);
684 /* Send the new Client ID as reply command back to client */
685 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
686 SILC_STATUS_OK, 0, ident, 2,
687 2, nidp->data, nidp->len,
688 3, nick, strlen(nick));
689 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
690 0, packet->data, packet->len, FALSE);
692 silc_buffer_free(packet);
693 silc_buffer_free(nidp);
695 silc_buffer_free(oidp);
698 silc_server_command_free(cmd);
701 /* Sends the LIST command reply */
704 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
705 SilcChannelEntry *lch,
706 SilcUInt32 lch_count,
707 SilcChannelEntry *gch,
708 SilcUInt32 gch_count)
711 SilcBuffer packet, idp;
712 SilcChannelEntry entry;
714 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
716 unsigned char usercount[4];
718 int valid_lcount = 0, valid_rcount = 0;
720 for (i = 0; i < lch_count; i++) {
721 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
726 for (i = 0; i < gch_count; i++) {
727 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
733 status = SILC_STATUS_OK;
734 if ((lch_count + gch_count) > 1)
735 status = SILC_STATUS_LIST_START;
738 for (i = 0, k = 0; i < lch_count; i++) {
744 status = SILC_STATUS_LIST_ITEM;
745 if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
746 status = SILC_STATUS_LIST_END;
748 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
750 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
752 memset(usercount, 0, sizeof(usercount));
754 topic = entry->topic;
755 users = silc_hash_table_count(entry->user_list);
756 SILC_PUT32_MSB(users, usercount);
761 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
763 2, idp->data, idp->len,
764 3, entry->channel_name,
765 strlen(entry->channel_name),
766 4, topic, topic ? strlen(topic) : 0,
768 silc_server_packet_send(cmd->server, cmd->sock,
769 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
771 silc_buffer_free(packet);
772 silc_buffer_free(idp);
777 for (i = 0, k = 0; i < gch_count; i++) {
783 status = SILC_STATUS_LIST_ITEM;
784 if (valid_rcount > 1 && k == valid_rcount - 1)
785 status = SILC_STATUS_LIST_END;
787 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
789 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
791 memset(usercount, 0, sizeof(usercount));
793 topic = entry->topic;
794 users = entry->user_count;
795 SILC_PUT32_MSB(users, usercount);
800 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
802 2, idp->data, idp->len,
803 3, entry->channel_name,
804 strlen(entry->channel_name),
805 4, topic, topic ? strlen(topic) : 0,
807 silc_server_packet_send(cmd->server, cmd->sock,
808 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
810 silc_buffer_free(packet);
811 silc_buffer_free(idp);
816 /* Server side of LIST command. This lists the channel of the requested
817 server. Secret channels are not listed. */
819 SILC_SERVER_CMD_FUNC(list)
821 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
822 SilcServer server = cmd->server;
823 SilcChannelID *channel_id = NULL;
826 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
827 SilcUInt32 lch_count = 0, gch_count = 0;
829 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
831 /* If we are normal server, send the command to router, since we
832 want to know all channels in the network. */
833 if (!cmd->pending && server->server_type != SILC_ROUTER &&
834 !server->standalone) {
836 SilcUInt16 old_ident;
838 old_ident = silc_command_get_ident(cmd->payload);
839 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
840 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
841 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
842 SILC_PACKET_COMMAND, cmd->packet->flags,
843 tmpbuf->data, tmpbuf->len, TRUE);
845 /* Reprocess this packet after received reply from router */
846 silc_server_command_pending(server, SILC_COMMAND_LIST,
847 silc_command_get_ident(cmd->payload),
848 silc_server_command_list,
849 silc_server_command_dup(cmd));
851 silc_command_set_ident(cmd->payload, old_ident);
852 silc_buffer_free(tmpbuf);
857 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
859 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
861 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
862 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
867 /* Get the channels from local list */
868 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
871 /* Get the channels from global list */
872 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
876 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
877 gchannels, gch_count);
879 silc_free(lchannels);
880 silc_free(gchannels);
883 silc_server_command_free(cmd);
886 /* Server side of TOPIC command. Sets topic for channel and/or returns
887 current topic to client. */
889 SILC_SERVER_CMD_FUNC(topic)
891 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
892 SilcServer server = cmd->server;
893 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
894 SilcChannelID *channel_id;
895 SilcChannelEntry channel;
896 SilcChannelClientEntry chl;
897 SilcBuffer packet, idp;
899 SilcUInt32 argc, tmp_len;
900 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
902 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
905 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
907 argc = silc_argument_get_arg_num(cmd->args);
910 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
912 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
913 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
916 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
918 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
919 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
923 /* Check whether the channel exists */
924 channel = silc_idlist_find_channel_by_id(server->local_list,
927 channel = silc_idlist_find_channel_by_id(server->global_list,
930 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
931 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
939 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
941 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
942 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
947 if (strlen(tmp) > 256) {
948 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
949 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
954 /* See whether the client is on channel and has rights to change topic */
955 if (!silc_server_client_on_channel(client, channel, &chl)) {
956 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
957 SILC_STATUS_ERR_NOT_ON_CHANNEL,
962 if (channel->mode & SILC_CHANNEL_MODE_TOPIC &&
963 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
964 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
965 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
966 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
971 if (!channel->topic || strcmp(channel->topic, tmp)) {
972 /* Set the topic for channel */
973 silc_free(channel->topic);
974 channel->topic = strdup(tmp);
976 /* Send TOPIC_SET notify type to the network */
977 silc_server_send_notify_topic_set(server, SILC_PRIMARY_ROUTE(server),
978 SILC_BROADCAST(server), channel,
979 client->id, SILC_ID_CLIENT,
982 /* Send notify about topic change to all clients on the channel */
983 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
984 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
985 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
988 strlen(channel->topic));
989 silc_buffer_free(idp);
993 /* Send the topic to client as reply packet */
994 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
995 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
996 SILC_STATUS_OK, 0, ident, 2,
997 2, idp->data, idp->len,
1000 strlen(channel->topic) : 0);
1001 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1002 0, packet->data, packet->len, FALSE);
1004 silc_buffer_free(packet);
1005 silc_buffer_free(idp);
1006 silc_free(channel_id);
1009 silc_server_command_free(cmd);
1012 /* Server side of INVITE command. Invites some client to join some channel.
1013 This command is also used to manage the invite list of the channel. */
1015 SILC_SERVER_CMD_FUNC(invite)
1017 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1018 SilcServer server = cmd->server;
1019 SilcSocketConnection sock = cmd->sock, dest_sock;
1020 SilcChannelClientEntry chl;
1021 SilcClientEntry sender, dest;
1022 SilcClientID *dest_id = NULL;
1023 SilcChannelEntry channel;
1024 SilcChannelID *channel_id = NULL;
1025 SilcIDListData idata;
1026 SilcArgumentPayload args;
1027 SilcHashTableList htl;
1028 SilcBuffer packet, list, tmp2;
1029 SilcBufferStruct alist;
1030 unsigned char *tmp, *atype = NULL;
1031 SilcUInt32 len, type, len2;
1032 SilcUInt16 argc = 0, ident = silc_command_get_ident(cmd->payload);
1034 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
1036 /* Get Channel ID */
1037 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1039 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1040 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
1043 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
1045 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1046 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
1050 /* Get the channel entry */
1051 channel = silc_idlist_find_channel_by_id(server->local_list,
1054 channel = silc_idlist_find_channel_by_id(server->global_list,
1057 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1058 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1064 /* Check whether the sender of this command is on the channel. */
1065 sender = (SilcClientEntry)sock->user_data;
1066 if (!sender || !silc_server_client_on_channel(sender, channel, &chl)) {
1067 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1068 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
1072 /* Check whether the channel is invite-only channel. If yes then the
1073 sender of this command must be at least channel operator. */
1074 if (channel->mode & SILC_CHANNEL_MODE_INVITE &&
1075 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
1076 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
1077 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1078 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
1083 /* Get destination client ID */
1084 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1088 dest_id = silc_id_payload_parse_id(tmp, len, NULL);
1090 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1091 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
1095 /* Get the client entry */
1096 dest = silc_server_query_client(server, dest_id, FALSE, &resolve);
1098 if (server->server_type != SILC_SERVER || !resolve || cmd->pending) {
1099 silc_server_command_send_status_reply(
1100 cmd, SILC_COMMAND_INVITE,
1101 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0);
1105 /* The client info is being resolved. Reprocess this packet after
1106 receiving the reply to the query. */
1107 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1109 silc_server_command_invite,
1110 silc_server_command_dup(cmd));
1111 cmd->pending = TRUE;
1115 /* Check whether the requested client is already on the channel. */
1116 if (silc_server_client_on_channel(dest, channel, NULL)) {
1117 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1118 SILC_STATUS_ERR_USER_ON_CHANNEL,
1123 /* Get route to the client */
1124 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id,
1127 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1128 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1133 /* Add the client to the invite list */
1135 /* Allocate hash table for invite list if it doesn't exist yet */
1136 if (!channel->invite_list)
1137 channel->invite_list =
1138 silc_hash_table_alloc(0, silc_hash_ptr,
1140 silc_server_inviteban_destruct, channel, TRUE);
1142 /* Check if the ID is in the list already */
1143 silc_hash_table_list(channel->invite_list, &htl);
1144 while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2)) {
1145 if (type == 3 && !memcmp(tmp2->data, tmp, len)) {
1150 silc_hash_table_list_reset(&htl);
1152 /* Add new Client ID to invite list */
1154 list = silc_buffer_alloc_size(len);
1155 silc_buffer_put(list, tmp, len);
1156 silc_hash_table_add(channel->invite_list, (void *)3, list);
1159 if (!(dest->mode & SILC_UMODE_BLOCK_INVITE)) {
1160 /* Send notify to the client that is invited to the channel */
1161 SilcBuffer idp, idp2;
1162 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1163 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1164 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
1166 SILC_NOTIFY_TYPE_INVITE, 3,
1167 idp->data, idp->len,
1168 channel->channel_name,
1169 strlen(channel->channel_name),
1170 idp2->data, idp2->len);
1171 silc_buffer_free(idp);
1172 silc_buffer_free(idp2);
1176 /* Get the invite information */
1177 tmp = silc_argument_get_arg_type(cmd->args, 4, &len2);
1178 if (tmp && len2 > 2) {
1179 /* Parse the arguments to see they are constructed correctly */
1180 SILC_GET16_MSB(argc, tmp);
1181 args = silc_argument_payload_parse(tmp + 2, len2 - 2, argc);
1183 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1184 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1189 /* Get the type of action */
1190 atype = silc_argument_get_arg_type(cmd->args, 3, &len);
1191 if (atype && len == 1) {
1192 if (atype[0] == 0x00) {
1193 /* Allocate hash table for invite list if it doesn't exist yet */
1194 if (!channel->invite_list)
1195 channel->invite_list =
1196 silc_hash_table_alloc(0, silc_hash_ptr,
1198 silc_server_inviteban_destruct, channel,
1201 /* Check for resource limit */
1202 if (silc_hash_table_count(channel->invite_list) > 64) {
1203 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1204 SILC_STATUS_ERR_RESOURCE_LIMIT,
1210 /* Now add or delete the information. */
1211 silc_server_inviteban_process(server, channel->invite_list,
1212 (SilcUInt8)atype[0], args);
1214 silc_argument_payload_free(args);
1217 /* Encode invite list */
1219 if (channel->invite_list && silc_hash_table_count(channel->invite_list)) {
1220 list = silc_buffer_alloc_size(2);
1221 silc_buffer_format(list,
1222 SILC_STR_UI_SHORT(silc_hash_table_count(
1223 channel->invite_list)),
1225 silc_hash_table_list(channel->invite_list, &htl);
1226 while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2))
1227 list = silc_argument_payload_encode_one(list, tmp2->data, tmp2->len,
1229 silc_hash_table_list_reset(&htl);
1232 /* Send notify to the primary router */
1233 if (atype && tmp && len2) {
1234 silc_buffer_set(&alist, tmp, len2);
1235 silc_server_send_notify_invite(server, SILC_PRIMARY_ROUTE(server),
1236 SILC_BROADCAST(server), channel,
1238 tmp ? &alist : NULL);
1241 /* Send invite list back only if the list was modified, or no arguments
1244 argc = silc_argument_get_arg_num(cmd->args);
1247 if (silc_argument_get_arg_type(cmd->args, 3, &len))
1250 /* Send command reply */
1251 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1252 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
1253 SILC_STATUS_OK, 0, ident, 2,
1257 type && list ? list->len : 0);
1258 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1259 packet->data, packet->len, FALSE);
1260 silc_buffer_free(packet);
1261 silc_buffer_free(list);
1265 silc_free(channel_id);
1266 silc_server_command_free(cmd);
1270 SilcSocketConnection sock;
1274 /* Quits connection to client. This gets called if client won't
1275 close the connection even when it has issued QUIT command. */
1277 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
1279 SilcServer server = app_context;
1280 QuitInternal q = (QuitInternal)context;
1282 /* Free all client specific data, such as client entry and entires
1283 on channels this client may be on. */
1284 silc_server_free_client_data(server, q->sock, q->sock->user_data,
1286 q->sock->user_data = NULL;
1288 /* Close the connection on our side */
1289 silc_server_close_connection(server, q->sock);
1291 silc_socket_free(q->sock);
1292 silc_free(q->signoff);
1296 /* Quits SILC session. This is the normal way to disconnect client. */
1298 SILC_SERVER_CMD_FUNC(quit)
1300 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1301 SilcServer server = cmd->server;
1302 SilcSocketConnection sock = cmd->sock;
1304 unsigned char *tmp = NULL;
1307 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
1309 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1313 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1317 q = silc_calloc(1, sizeof(*q));
1318 q->sock = silc_socket_dup(sock);
1319 q->signoff = tmp ? strdup(tmp) : NULL;
1321 /* We quit the connection with little timeout */
1322 silc_schedule_task_add(server->schedule, sock->sock,
1323 silc_server_command_quit_cb, (void *)q,
1324 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1327 silc_server_command_free(cmd);
1330 /* Server side of command KILL. This command is used by router operator
1331 to remove an client from the SILC Network temporarily. */
1333 SILC_SERVER_CMD_FUNC(kill)
1335 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1336 SilcServer server = cmd->server;
1337 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1338 SilcClientEntry remote_client;
1339 SilcClientID *client_id = NULL;
1340 unsigned char *tmp, *comment, *auth;
1341 SilcUInt32 tmp_len, tmp_len2, auth_len;
1343 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 3);
1345 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
1348 /* Get authentication payload if present */
1349 auth = silc_argument_get_arg_type(cmd->args, 3, &auth_len);
1352 /* Router operator killing */
1354 /* KILL command works only on router */
1355 if (server->server_type != SILC_ROUTER) {
1356 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1357 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
1361 /* Check whether client has the permissions. */
1362 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
1363 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1364 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
1369 /* Get the client ID */
1370 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1372 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1373 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1377 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1379 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1380 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1385 /* Get the client entry */
1386 remote_client = silc_idlist_find_client_by_id(server->local_list,
1387 client_id, TRUE, NULL);
1388 if (!remote_client) {
1389 remote_client = silc_idlist_find_client_by_id(server->global_list,
1390 client_id, TRUE, NULL);
1391 if (!remote_client) {
1392 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1393 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1400 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
1401 if (comment && tmp_len2 > 128) {
1403 comment[127] = '\0';
1406 /* If authentication data is provided then verify that killing is
1408 if (auth && auth_len) {
1409 SilcSocketConnection sock;
1411 if (!SILC_IS_LOCAL(remote_client) || !remote_client->data.public_key) {
1412 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1413 SILC_STATUS_ERR_OPERATION_ALLOWED,
1418 /* Verify the signature */
1419 if (!silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
1420 remote_client->data.public_key, 0,
1421 server->sha1hash, remote_client->id,
1423 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1424 SILC_STATUS_ERR_AUTH_FAILED,
1429 /* Send reply to the sender */
1430 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1433 /* Do normal signoff for the destination client */
1434 sock = remote_client->connection;
1435 silc_server_remove_from_channels(server, NULL, remote_client,
1436 TRUE, (char *)"Killed", TRUE, TRUE);
1437 silc_server_free_client_data(server, NULL, remote_client, TRUE,
1439 (unsigned char *)"Killed");
1441 silc_server_close_connection(server, sock);
1443 /* Router operator killing */
1445 /* Send reply to the sender */
1446 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1449 /* Check if anyone is watching this nickname */
1450 if (server->server_type == SILC_ROUTER)
1451 silc_server_check_watcher_list(server, client, NULL,
1452 SILC_NOTIFY_TYPE_KILLED);
1454 /* Now do the killing */
1455 silc_server_kill_client(server, remote_client, comment, client->id,
1460 silc_free(client_id);
1461 silc_server_command_free(cmd);
1464 /* Server side of command INFO. This sends information about us to
1465 the client. If client requested specific server we will send the
1466 command to that server. */
1468 SILC_SERVER_CMD_FUNC(info)
1470 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1471 SilcServer server = cmd->server;
1472 SilcBuffer packet, idp;
1475 char *dest_server, *server_info = NULL, *server_name;
1476 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1477 SilcServerEntry entry = NULL;
1478 SilcServerID *server_id = NULL;
1480 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
1482 /* Get server name */
1483 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1486 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1488 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1490 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1491 SILC_STATUS_ERR_NO_SERVER_ID, 0);
1497 /* Check whether we have this server cached */
1498 entry = silc_idlist_find_server_by_id(server->local_list,
1499 server_id, TRUE, NULL);
1501 entry = silc_idlist_find_server_by_id(server->global_list,
1502 server_id, TRUE, NULL);
1503 if (!entry && server->server_type != SILC_SERVER) {
1504 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1505 SILC_STATUS_ERR_NO_SUCH_SERVER,
1512 /* Some buggy servers has sent request to router about themselves. */
1513 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
1516 if ((!dest_server && !server_id && !entry) || (entry &&
1517 entry == server->id_entry) ||
1518 (dest_server && !cmd->pending &&
1519 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
1520 /* Send our reply */
1521 char info_string[256];
1523 memset(info_string, 0, sizeof(info_string));
1524 snprintf(info_string, sizeof(info_string),
1525 "location: %s server: %s admin: %s <%s>",
1526 server->config->server_info->location,
1527 server->config->server_info->server_type,
1528 server->config->server_info->admin,
1529 server->config->server_info->email);
1531 server_info = info_string;
1532 entry = server->id_entry;
1534 /* Check whether we have this server cached */
1535 if (!entry && dest_server) {
1536 entry = silc_idlist_find_server_by_name(server->global_list,
1537 dest_server, TRUE, NULL);
1539 entry = silc_idlist_find_server_by_name(server->local_list,
1540 dest_server, TRUE, NULL);
1544 if (!cmd->pending &&
1545 server->server_type != SILC_SERVER && entry && !entry->server_info) {
1546 /* Send to the server */
1548 SilcUInt16 old_ident;
1550 old_ident = silc_command_get_ident(cmd->payload);
1551 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1552 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1554 silc_server_packet_send(server, entry->connection,
1555 SILC_PACKET_COMMAND, cmd->packet->flags,
1556 tmpbuf->data, tmpbuf->len, TRUE);
1558 /* Reprocess this packet after received reply from router */
1559 silc_server_command_pending(server, SILC_COMMAND_INFO,
1560 silc_command_get_ident(cmd->payload),
1561 silc_server_command_info,
1562 silc_server_command_dup(cmd));
1563 cmd->pending = TRUE;
1564 silc_command_set_ident(cmd->payload, old_ident);
1565 silc_buffer_free(tmpbuf);
1569 if (!entry && !cmd->pending && !server->standalone) {
1570 /* Send to the primary router */
1572 SilcUInt16 old_ident;
1574 old_ident = silc_command_get_ident(cmd->payload);
1575 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1576 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1578 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
1579 SILC_PACKET_COMMAND, cmd->packet->flags,
1580 tmpbuf->data, tmpbuf->len, TRUE);
1582 /* Reprocess this packet after received reply from router */
1583 silc_server_command_pending(server, SILC_COMMAND_INFO,
1584 silc_command_get_ident(cmd->payload),
1585 silc_server_command_info,
1586 silc_server_command_dup(cmd));
1587 cmd->pending = TRUE;
1588 silc_command_set_ident(cmd->payload, old_ident);
1589 silc_buffer_free(tmpbuf);
1594 silc_free(server_id);
1597 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1598 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
1602 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1604 server_info = entry->server_info;
1605 server_name = entry->server_name;
1607 /* Send the reply */
1608 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
1609 SILC_STATUS_OK, 0, ident, 3,
1610 2, idp->data, idp->len,
1612 strlen(server_name),
1615 strlen(server_info) : 0);
1616 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1617 packet->data, packet->len, FALSE);
1619 silc_buffer_free(packet);
1620 silc_buffer_free(idp);
1623 silc_server_command_free(cmd);
1626 /* Server side of command PING. This just replies to the ping. */
1628 SILC_SERVER_CMD_FUNC(ping)
1630 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1631 SilcServer server = cmd->server;
1634 SilcServerID *server_id = NULL;
1636 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PING, cmd, 1, 1);
1639 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1641 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1642 SILC_STATUS_ERR_NO_SERVER_ID, 0);
1645 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1649 if (SILC_ID_SERVER_COMPARE(server_id, server->id)) {
1650 /* Send our reply */
1651 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1654 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1655 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
1660 silc_free(server_id);
1661 silc_server_command_free(cmd);
1664 /* Server side of command STATS. */
1666 SILC_SERVER_CMD_FUNC(stats)
1668 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1669 SilcServer server = cmd->server;
1670 SilcServerID *server_id;
1673 SilcBuffer packet, stats;
1674 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1677 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1);
1680 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1682 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1683 SILC_STATUS_ERR_NO_SERVER_ID, 0);
1686 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1690 /* The ID must be ours */
1691 if (!SILC_ID_SERVER_COMPARE(server->id, server_id)) {
1692 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1693 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
1694 silc_free(server_id);
1697 silc_free(server_id);
1699 /* If we are router then just send everything we got. If we are normal
1700 server then we'll send this to our router to get all the latest
1701 statistical information. */
1702 if (!cmd->pending && server->server_type != SILC_ROUTER &&
1703 !server->standalone) {
1704 /* Send request to our router */
1705 SilcBuffer idp = silc_id_payload_encode(server->router->id,
1707 packet = silc_command_payload_encode_va(SILC_COMMAND_STATS,
1708 ++server->cmd_ident, 1,
1709 1, idp->data, idp->len);
1710 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
1711 SILC_PACKET_COMMAND, 0, packet->data,
1712 packet->len, FALSE);
1714 /* Reprocess this packet after received reply from router */
1715 silc_server_command_pending(server, SILC_COMMAND_STATS,
1717 silc_server_command_stats,
1718 silc_server_command_dup(cmd));
1719 cmd->pending = TRUE;
1720 silc_buffer_free(packet);
1721 silc_buffer_free(idp);
1725 /* Send our reply to sender */
1726 uptime = time(NULL) - server->starttime;
1728 stats = silc_buffer_alloc_size(60);
1729 silc_buffer_format(stats,
1730 SILC_STR_UI_INT(server->starttime),
1731 SILC_STR_UI_INT(uptime),
1732 SILC_STR_UI_INT(server->stat.my_clients),
1733 SILC_STR_UI_INT(server->stat.my_channels),
1734 SILC_STR_UI_INT(server->stat.my_server_ops),
1735 SILC_STR_UI_INT(server->stat.my_router_ops),
1736 SILC_STR_UI_INT(server->stat.cell_clients),
1737 SILC_STR_UI_INT(server->stat.cell_channels),
1738 SILC_STR_UI_INT(server->stat.cell_servers),
1739 SILC_STR_UI_INT(server->stat.clients),
1740 SILC_STR_UI_INT(server->stat.channels),
1741 SILC_STR_UI_INT(server->stat.servers),
1742 SILC_STR_UI_INT(server->stat.routers),
1743 SILC_STR_UI_INT(server->stat.server_ops),
1744 SILC_STR_UI_INT(server->stat.router_ops),
1747 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_STATS,
1748 SILC_STATUS_OK, 0, ident, 2,
1750 3, stats->data, stats->len);
1751 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1752 0, packet->data, packet->len, FALSE);
1753 silc_buffer_free(packet);
1754 silc_buffer_free(stats);
1757 silc_server_command_free(cmd);
1760 /* Internal routine to join channel. The channel sent to this function
1761 has been either created or resolved from ID lists. This joins the sent
1762 client to the channel. */
1764 static void silc_server_command_join_channel(SilcServer server,
1765 SilcServerCommandContext cmd,
1766 SilcChannelEntry channel,
1767 SilcClientID *client_id,
1771 const unsigned char *auth,
1772 SilcUInt32 auth_len)
1774 SilcSocketConnection sock = cmd->sock;
1776 SilcUInt32 tmp_len, user_count;
1777 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
1778 SilcClientEntry client;
1779 SilcChannelClientEntry chl;
1780 SilcBuffer reply, chidp, clidp, keyp = NULL;
1781 SilcBuffer user_list, mode_list, invite_list, ban_list;
1782 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1783 char check[512], check2[512];
1784 bool founder = FALSE;
1786 SilcBuffer fkey = NULL;
1789 SILC_LOG_DEBUG(("Joining client to channel"));
1794 /* Get the client entry */
1795 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1796 client = (SilcClientEntry)sock->user_data;
1800 client = silc_server_query_client(server, client_id, FALSE,
1803 if (!resolve || cmd->pending) {
1804 silc_server_command_send_status_reply(
1805 cmd, SILC_COMMAND_JOIN,
1806 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
1810 /* The client info is being resolved. Reprocess this packet after
1811 receiving the reply to the query. */
1812 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1814 silc_server_command_join,
1815 silc_server_command_dup(cmd));
1816 cmd->pending = TRUE;
1820 if (auth && auth_len && !client->data.public_key) {
1821 if (cmd->pending == 2)
1824 /* We must retrieve the detached client's public key by sending
1825 GETKEY command. Reprocess this packet after receiving the key */
1826 clidp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
1827 silc_server_send_command(server, cmd->sock,
1828 SILC_COMMAND_GETKEY, ++server->cmd_ident,
1829 1, 1, clidp->data, clidp->len);
1830 silc_buffer_free(clidp);
1831 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
1833 silc_server_command_join,
1834 silc_server_command_dup(cmd));
1839 cmd->pending = FALSE;
1843 * Check founder auth payload if provided. If client can gain founder
1844 * privileges it can override various conditions on joining the channel,
1845 * and can have directly the founder mode set on the channel.
1847 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1848 SilcIDListData idata = (SilcIDListData)client;
1849 SilcChannelClientEntry chl2;
1850 SilcHashTableList htl;
1852 if (channel->founder_key && idata->public_key &&
1853 silc_pkcs_public_key_compare(channel->founder_key,
1854 idata->public_key)) {
1855 /* Check whether the client is to become founder */
1856 if (silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
1857 channel->founder_key, 0, server->sha1hash,
1858 client->id, SILC_ID_CLIENT)) {
1860 /* There cannot be anyone else as founder on the channel now. This
1861 client is definitely the founder due to this authentication */
1862 silc_hash_table_list(channel->user_list, &htl);
1863 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
1864 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
1865 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
1866 silc_server_force_cumode_change(server, NULL, channel, chl2,
1870 silc_hash_table_list_reset(&htl);
1872 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
1879 * Check channel modes
1883 memset(check, 0, sizeof(check));
1884 memset(check2, 0, sizeof(check2));
1885 silc_strncat(check, sizeof(check),
1886 client->nickname, strlen(client->nickname));
1887 silc_strncat(check, sizeof(check), "!", 1);
1888 silc_strncat(check, sizeof(check),
1889 client->username, strlen(client->username));
1890 if (!strchr(client->username, '@')) {
1891 silc_strncat(check, sizeof(check), "@", 1);
1892 silc_strncat(check, sizeof(check),
1893 cmd->sock->hostname, strlen(cmd->sock->hostname));
1896 silc_strncat(check2, sizeof(check2),
1897 client->nickname, strlen(client->nickname));
1898 if (!strchr(client->nickname, '@')) {
1899 silc_strncat(check2, sizeof(check2), "@", 1);
1900 silc_strncat(check2, sizeof(check2),
1901 server->server_name, strlen(server->server_name));
1903 silc_strncat(check2, sizeof(check2), "!", 1);
1904 silc_strncat(check2, sizeof(check2),
1905 client->username, strlen(client->username));
1906 if (!strchr(client->username, '@')) {
1907 silc_strncat(check2, sizeof(check2), "@", 1);
1908 silc_strncat(check2, sizeof(check2),
1909 cmd->sock->hostname, strlen(cmd->sock->hostname));
1912 /* Check invite list if channel is invite-only channel */
1913 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1914 if (!channel->invite_list ||
1915 !silc_hash_table_count(channel->invite_list) ||
1916 (!silc_server_inviteban_match(server, channel->invite_list,
1918 !silc_server_inviteban_match(server, channel->invite_list,
1919 2, client->data.public_key) &&
1920 !silc_server_inviteban_match(server, channel->invite_list,
1922 !silc_server_inviteban_match(server, channel->invite_list,
1924 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1925 SILC_STATUS_ERR_NOT_INVITED, 0);
1930 /* Check ban list if it exists. If the client's nickname, server,
1931 username and/or hostname is in the ban list the access to the
1932 channel is denied. */
1933 if (channel->ban_list && silc_hash_table_count(channel->ban_list)) {
1934 if (silc_server_inviteban_match(server, channel->ban_list,
1936 silc_server_inviteban_match(server, channel->ban_list,
1937 2, client->data.public_key) ||
1938 silc_server_inviteban_match(server, channel->ban_list,
1940 silc_server_inviteban_match(server, channel->ban_list,
1942 silc_server_command_send_status_reply(
1943 cmd, SILC_COMMAND_JOIN,
1944 SILC_STATUS_ERR_BANNED_FROM_CHANNEL, 0);
1949 /* Check user count limit if set. */
1950 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
1951 if (silc_hash_table_count(channel->user_list) + 1 >
1952 channel->user_limit) {
1953 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1954 SILC_STATUS_ERR_CHANNEL_IS_FULL,
1961 /* Check the channel passphrase if set. */
1962 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1963 /* Get passphrase */
1964 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1966 passphrase = silc_memdup(tmp, tmp_len);
1968 if (!passphrase || !channel->passphrase ||
1969 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
1970 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1971 SILC_STATUS_ERR_BAD_PASSWORD, 0);
1977 * Client is allowed to join to the channel. Make it happen.
1980 /* Check whether the client already is on the channel */
1981 if (silc_server_client_on_channel(client, channel, NULL)) {
1982 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1983 SILC_STATUS_ERR_USER_ON_CHANNEL, 0);
1987 /* Generate new channel key as protocol dictates */
1989 if (!silc_server_create_channel_key(server, channel, 0))
1992 /* Send the channel key. This is broadcasted to the channel but is not
1993 sent to the client who is joining to the channel. */
1994 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
1995 silc_server_send_channel_key(server, NULL, channel,
1996 server->server_type == SILC_ROUTER ?
1997 FALSE : !server->standalone);
2000 /* Join the client to the channel by adding it to channel's user list.
2001 Add also the channel to client entry's channels list for fast cross-
2003 chl = silc_calloc(1, sizeof(*chl));
2005 chl->client = client;
2006 chl->channel = channel;
2007 silc_hash_table_add(channel->user_list, client, chl);
2008 silc_hash_table_add(client->channels, channel, chl);
2009 channel->user_count++;
2010 channel->disabled = FALSE;
2012 /* Get users on the channel */
2013 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
2016 /* Encode Client ID Payload of the original client who wants to join */
2017 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2019 /* Encode command reply packet */
2020 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2021 SILC_PUT32_MSB(channel->mode, mode);
2022 SILC_PUT32_MSB(created, tmp2);
2023 SILC_PUT32_MSB(user_count, tmp3);
2025 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
2026 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
2027 cipher = silc_cipher_get_name(channel->channel_key);
2028 keyp = silc_channel_key_payload_encode(silc_id_get_len(channel->id,
2031 strlen(cipher), cipher,
2032 channel->key_len / 8, channel->key);
2036 if (channel->founder_key)
2037 fkey = silc_pkcs_public_key_payload_encode(channel->founder_key);
2039 /* Encode invite list */
2041 if (channel->invite_list && silc_hash_table_count(channel->invite_list)) {
2042 SilcHashTableList htl;
2044 invite_list = silc_buffer_alloc_size(2);
2045 silc_buffer_format(invite_list,
2046 SILC_STR_UI_SHORT(silc_hash_table_count(
2047 channel->invite_list)),
2050 silc_hash_table_list(channel->invite_list, &htl);
2051 while (silc_hash_table_get(&htl, (void **)&tmp_len, (void **)&reply))
2052 invite_list = silc_argument_payload_encode_one(invite_list,
2054 reply->len, tmp_len);
2055 silc_hash_table_list_reset(&htl);
2058 /* Encode ban list */
2060 if (channel->ban_list && silc_hash_table_count(channel->ban_list)) {
2061 SilcHashTableList htl;
2063 ban_list = silc_buffer_alloc_size(2);
2064 silc_buffer_format(ban_list,
2065 SILC_STR_UI_SHORT(silc_hash_table_count(
2066 channel->ban_list)),
2069 silc_hash_table_list(channel->ban_list, &htl);
2070 while (silc_hash_table_get(&htl, (void **)&tmp_len, (void **)&reply))
2071 ban_list = silc_argument_payload_encode_one(ban_list,
2073 reply->len, tmp_len);
2074 silc_hash_table_list_reset(&htl);
2078 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2079 SILC_STATUS_OK, 0, ident, 14,
2080 2, channel->channel_name,
2081 strlen(channel->channel_name),
2082 3, chidp->data, chidp->len,
2083 4, clidp->data, clidp->len,
2086 7, keyp ? keyp->data : NULL,
2087 keyp ? keyp->len : 0,
2088 8, ban_list ? ban_list->data : NULL,
2089 ban_list ? ban_list->len : 0,
2090 9, invite_list ? invite_list->data :
2092 invite_list ? invite_list->len : 0,
2095 strlen(channel->topic) : 0,
2096 11, silc_hmac_get_name(channel->hmac),
2097 strlen(silc_hmac_get_name(channel->
2100 13, user_list->data, user_list->len,
2101 14, mode_list->data,
2103 15, fkey ? fkey->data : NULL,
2104 fkey ? fkey->len : 0);
2106 /* Send command reply */
2107 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
2108 reply->data, reply->len, FALSE);
2110 /* Send JOIN notify to locally connected clients on the channel. If
2111 we are normal server then router will send or have sent JOIN notify
2112 already. However since we've added the client already to our channel
2113 we'll ignore it (in packet_receive.c) so we must send it here. If
2114 we are router then this will send it to local clients and local
2116 SILC_LOG_DEBUG(("Send JOIN notify to channel"));
2117 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2118 SILC_NOTIFY_TYPE_JOIN, 2,
2119 clidp->data, clidp->len,
2120 chidp->data, chidp->len);
2122 /* Update statistics */
2123 server->stat.my_chanclients++;
2124 if (server->server_type == SILC_ROUTER) {
2125 server->stat.cell_chanclients++;
2126 server->stat.chanclients++;
2129 if (!cmd->pending) {
2130 /* Send JOIN notify packet to our primary router */
2131 silc_server_send_notify_join(server, SILC_PRIMARY_ROUTE(server),
2132 SILC_BROADCAST(server), channel, client->id);
2135 /* Distribute the channel key to all backup routers. */
2136 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
2137 keyp->data, keyp->len, FALSE, TRUE);
2139 /* If client became founder by providing correct founder auth data
2140 notify the mode change to the channel. */
2142 SILC_PUT32_MSB(chl->mode, mode);
2143 SILC_LOG_DEBUG(("Send CUMODE_CHANGE notify to channel"));
2144 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2145 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
2146 clidp->data, clidp->len,
2147 mode, 4, clidp->data, clidp->len,
2148 fkey ? fkey->data : NULL,
2149 fkey ? fkey->len : 0);
2153 /* Set CUMODE notify type to network */
2155 silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
2156 SILC_BROADCAST(server), channel,
2157 chl->mode, client->id, SILC_ID_CLIENT,
2158 client->id, channel->founder_key);
2160 silc_buffer_free(reply);
2161 silc_buffer_free(clidp);
2162 silc_buffer_free(chidp);
2163 silc_buffer_free(keyp);
2164 silc_buffer_free(user_list);
2165 silc_buffer_free(mode_list);
2166 silc_buffer_free(fkey);
2167 silc_buffer_free(invite_list);
2168 silc_buffer_free(ban_list);
2172 memset(passphrase, 0, strlen(passphrase));
2173 silc_free(passphrase);
2176 /* Server side of command JOIN. Joins client into requested channel. If
2177 the channel does not exist it will be created. */
2179 SILC_SERVER_CMD_FUNC(join)
2181 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2182 SilcServer server = cmd->server;
2183 unsigned char *auth;
2184 SilcUInt32 tmp_len, auth_len;
2185 char *tmp, *channel_name = NULL, *cipher, *hmac;
2186 SilcChannelEntry channel;
2187 SilcUInt32 umode = 0;
2188 bool created = FALSE, create_key = TRUE;
2189 SilcClientID *client_id;
2191 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
2193 /* Get channel name */
2194 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2196 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2197 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2204 channel_name[255] = '\0';
2206 if (silc_server_name_bad_chchars(channel_name, tmp_len) == TRUE) {
2207 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2208 SILC_STATUS_ERR_BAD_CHANNEL, 0);
2212 /* Get Client ID of the client who is joining to the channel */
2213 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2215 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2216 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2220 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2222 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2223 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2228 /* Get cipher, hmac name and auth payload */
2229 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2230 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2231 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
2233 /* See if the channel exists */
2234 channel = silc_idlist_find_channel_by_name(server->local_list,
2235 channel_name, NULL);
2237 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2238 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2240 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2241 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2246 silc_free(client_id);
2247 client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
2250 (channel->disabled && server->server_type != SILC_ROUTER)) {
2251 /* Channel not found or not valid */
2253 /* If we are standalone server we don't have a router, we just create
2254 the channel by ourselves (unless it existed). */
2255 if (server->standalone) {
2257 channel = silc_server_create_new_channel(server, server->id, cipher,
2258 hmac, channel_name, TRUE);
2260 silc_server_command_send_status_reply(
2261 cmd, SILC_COMMAND_JOIN,
2262 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
2264 silc_free(client_id);
2268 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2274 /* The channel does not exist on our server. If we are normal server
2275 we will send JOIN command to our router which will handle the
2276 joining procedure (either creates the channel if it doesn't exist
2277 or joins the client to it). */
2278 if (server->server_type != SILC_ROUTER) {
2280 SilcUInt16 old_ident;
2282 /* If this is pending command callback then we've resolved
2283 it and it didn't work, return since we've notified the
2284 client already in the command reply callback. */
2286 silc_free(client_id);
2290 old_ident = silc_command_get_ident(cmd->payload);
2291 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2292 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2294 /* Send JOIN command to our router */
2295 silc_server_packet_send(server, (SilcSocketConnection)
2296 SILC_PRIMARY_ROUTE(server),
2297 SILC_PACKET_COMMAND, cmd->packet->flags,
2298 tmpbuf->data, tmpbuf->len, TRUE);
2300 /* Reprocess this packet after received reply from router */
2301 silc_server_command_pending(server, SILC_COMMAND_JOIN,
2302 silc_command_get_ident(cmd->payload),
2303 silc_server_command_join,
2304 silc_server_command_dup(cmd));
2305 cmd->pending = TRUE;
2306 silc_command_set_ident(cmd->payload, old_ident);
2307 silc_buffer_free(tmpbuf);
2308 silc_free(client_id);
2312 /* We are router and the channel does not seem exist so we will check
2313 our global list as well for the channel. */
2314 channel = silc_idlist_find_channel_by_name(server->global_list,
2315 channel_name, NULL);
2317 /* Channel really does not exist, create it */
2318 channel = silc_server_create_new_channel(server, server->id, cipher,
2319 hmac, channel_name, TRUE);
2321 silc_server_command_send_status_reply(
2322 cmd, SILC_COMMAND_JOIN,
2323 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
2324 silc_free(client_id);
2328 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2336 /* Channel not found */
2338 /* If the command came from router and we are normal server then
2339 something went wrong with the joining as the channel was not found.
2340 We can't do anything else but ignore this. */
2341 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
2342 server->server_type != SILC_ROUTER) {
2343 silc_free(client_id);
2347 /* We are router and the channel does not seem exist so we will check
2348 our global list as well for the channel. */
2349 channel = silc_idlist_find_channel_by_name(server->global_list,
2350 channel_name, NULL);
2352 /* Channel really does not exist, create it */
2353 channel = silc_server_create_new_channel(server, server->id, cipher,
2354 hmac, channel_name, TRUE);
2356 silc_server_command_send_status_reply(
2357 cmd, SILC_COMMAND_JOIN,
2358 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
2359 silc_free(client_id);
2363 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2370 /* Check whether the channel was created by our router */
2371 if (cmd->pending && context2) {
2372 SilcServerCommandReplyContext reply = context2;
2374 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
2375 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
2376 SILC_GET32_MSB(created, tmp);
2377 if (silc_argument_get_arg_type(reply->args, 7, NULL))
2378 create_key = FALSE; /* Router returned the key already */
2380 if (silc_command_get_status(reply->payload, NULL, NULL) &&
2381 channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2382 /* Save channel passphrase, if user provided it successfully */
2385 pa = silc_argument_get_arg_type(cmd->args, 3, &pa_len);
2387 silc_free(channel->passphrase);
2388 channel->passphrase = silc_memdup(pa, pa_len);
2393 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
2394 !channel->disabled && !silc_hash_table_count(channel->user_list))
2398 /* If the channel does not have global users and is also empty the client
2399 will be the channel founder and operator. */
2400 if (!channel->disabled &&
2401 !channel->global_users && !silc_hash_table_count(channel->user_list))
2402 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2404 /* Join to the channel */
2405 silc_server_command_join_channel(server, cmd, channel, client_id,
2406 created, create_key, umode,
2409 silc_free(client_id);
2412 silc_server_command_free(cmd);
2415 /* Server side of command MOTD. Sends server's current "message of the
2416 day" to the client. */
2418 SILC_SERVER_CMD_FUNC(motd)
2420 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2421 SilcServer server = cmd->server;
2422 SilcBuffer packet, idp;
2423 char *motd, *dest_server;
2424 SilcUInt32 motd_len;
2425 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2427 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
2429 /* Get server name */
2430 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2432 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2433 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
2437 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
2440 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
2442 if (server->config && server->config->server_info &&
2443 server->config->server_info->motd_file) {
2445 motd = silc_file_readfile(server->config->server_info->motd_file,
2451 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
2458 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
2464 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2465 packet->data, packet->len, FALSE);
2466 silc_buffer_free(packet);
2467 silc_buffer_free(idp);
2469 SilcServerEntry entry;
2471 /* Check whether we have this server cached */
2472 entry = silc_idlist_find_server_by_name(server->global_list,
2473 dest_server, TRUE, NULL);
2475 entry = silc_idlist_find_server_by_name(server->local_list,
2476 dest_server, TRUE, NULL);
2479 if (server->server_type != SILC_SERVER && !cmd->pending &&
2480 entry && !entry->motd) {
2481 /* Send to the server */
2483 SilcUInt16 old_ident;
2485 old_ident = silc_command_get_ident(cmd->payload);
2486 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2487 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2489 silc_server_packet_send(server, entry->connection,
2490 SILC_PACKET_COMMAND, cmd->packet->flags,
2491 tmpbuf->data, tmpbuf->len, TRUE);
2493 /* Reprocess this packet after received reply from router */
2494 silc_server_command_pending(server, SILC_COMMAND_MOTD,
2495 silc_command_get_ident(cmd->payload),
2496 silc_server_command_motd,
2497 silc_server_command_dup(cmd));
2498 cmd->pending = TRUE;
2499 silc_command_set_ident(cmd->payload, old_ident);
2500 silc_buffer_free(tmpbuf);
2504 if (!entry && !cmd->pending && !server->standalone) {
2505 /* Send to the primary router */
2507 SilcUInt16 old_ident;
2509 old_ident = silc_command_get_ident(cmd->payload);
2510 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2511 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2513 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
2514 SILC_PACKET_COMMAND, cmd->packet->flags,
2515 tmpbuf->data, tmpbuf->len, TRUE);
2517 /* Reprocess this packet after received reply from router */
2518 silc_server_command_pending(server, SILC_COMMAND_MOTD,
2519 silc_command_get_ident(cmd->payload),
2520 silc_server_command_motd,
2521 silc_server_command_dup(cmd));
2522 cmd->pending = TRUE;
2523 silc_command_set_ident(cmd->payload, old_ident);
2524 silc_buffer_free(tmpbuf);
2529 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2530 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
2534 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
2535 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
2536 SILC_STATUS_OK, 0, ident, 2,
2540 strlen(entry->motd) : 0);
2541 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2542 packet->data, packet->len, FALSE);
2543 silc_buffer_free(packet);
2544 silc_buffer_free(idp);
2548 silc_server_command_free(cmd);
2551 /* Server side of command UMODE. Client can use this command to set/unset
2552 user mode. Client actually cannot set itself to be as server/router
2553 operator so this can be used only to unset the modes. */
2555 SILC_SERVER_CMD_FUNC(umode)
2557 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2558 SilcServer server = cmd->server;
2559 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2561 unsigned char *tmp_mask, m[4];
2562 SilcUInt32 mask = 0;
2563 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2564 bool set_mask = FALSE;
2566 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
2569 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2);
2571 /* Get the client's mode mask */
2572 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2574 SILC_GET32_MSB(mask, tmp_mask);
2579 /* Check that mode changing is allowed. */
2580 if (!silc_server_check_umode_rights(server, client, mask)) {
2581 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2582 SILC_STATUS_ERR_PERM_DENIED, 0);
2586 /* Anonymous mode cannot be set by client */
2587 if (mask & SILC_UMODE_ANONYMOUS) {
2588 if (!(client->mode & SILC_UMODE_ANONYMOUS)) {
2589 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2590 SILC_STATUS_ERR_PERM_DENIED, 0);
2594 if (client->mode & SILC_UMODE_ANONYMOUS) {
2595 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2596 SILC_STATUS_ERR_PERM_DENIED, 0);
2601 /* Update statistics */
2602 if (mask & SILC_UMODE_GONE) {
2603 if (!(client->mode & SILC_UMODE_GONE))
2604 server->stat.my_aways++;
2606 if (client->mode & SILC_UMODE_GONE)
2607 server->stat.my_aways--;
2610 /* Change the mode */
2611 client->mode = mask;
2613 /* Send UMODE change to primary router */
2614 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
2615 SILC_BROADCAST(server), client->id,
2618 /* Check if anyone is watching this nickname */
2619 if (server->server_type == SILC_ROUTER)
2620 silc_server_check_watcher_list(server, client, NULL,
2621 SILC_NOTIFY_TYPE_UMODE_CHANGE);
2624 /* Send command reply to sender */
2625 SILC_PUT32_MSB(client->mode, m);
2626 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
2627 SILC_STATUS_OK, 0, ident, 1,
2629 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2630 packet->data, packet->len, FALSE);
2631 silc_buffer_free(packet);
2634 silc_server_command_free(cmd);
2637 /* Server side command of CMODE. Changes channel mode */
2639 SILC_SERVER_CMD_FUNC(cmode)
2641 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2642 SilcServer server = cmd->server;
2643 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2644 SilcIDListData idata = (SilcIDListData)client;
2645 SilcChannelID *channel_id = NULL;
2646 SilcChannelEntry channel;
2647 SilcChannelClientEntry chl;
2648 SilcBuffer packet, cidp;
2649 unsigned char *tmp, *tmp_id, *tmp_mask;
2650 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
2651 SilcUInt32 mode_mask = 0, old_mask = 0, tmp_len, tmp_len2;
2652 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2653 bool set_mask = FALSE;
2654 SilcPublicKey founder_key = NULL;
2655 SilcBuffer fkey = NULL;
2658 silc_server_command_free(cmd);
2662 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 8);
2664 /* Get Channel ID */
2665 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2667 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2668 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2669 silc_server_command_free(cmd);
2672 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
2674 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2675 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2676 silc_server_command_free(cmd);
2680 /* Get channel entry */
2681 channel = silc_idlist_find_channel_by_id(server->local_list,
2684 channel = silc_idlist_find_channel_by_id(server->global_list,
2687 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2688 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
2690 silc_free(channel_id);
2691 silc_server_command_free(cmd);
2695 old_mask = channel->mode;
2697 /* Get the channel mode mask */
2698 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2700 SILC_GET32_MSB(mode_mask, tmp_mask);
2704 /* Check whether this client is on the channel */
2705 if (!silc_server_client_on_channel(client, channel, &chl)) {
2706 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2707 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
2711 /* Check that client has rights to change any requested channel modes */
2712 if (set_mask && !silc_server_check_cmode_rights(server, channel, chl,
2714 SILC_LOG_DEBUG(("Client does not have rights to change mode"));
2715 silc_server_command_send_status_reply(
2716 cmd, SILC_COMMAND_CMODE,
2717 (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) ?
2718 SILC_STATUS_ERR_NO_CHANNEL_PRIV :
2719 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV), 0);
2723 /* If mode mask was not sent as argument then merely return the current
2724 mode mask to the sender. */
2727 SILC_PUT32_MSB(channel->mode, m);
2728 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2729 SILC_STATUS_OK, 0, ident, 2,
2730 2, tmp_id, tmp_len2,
2732 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2733 packet->data, packet->len, FALSE);
2734 silc_buffer_free(packet);
2739 * Check the modes. Modes that requires nothing special operation are
2743 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2744 /* Channel uses private keys to protect traffic. Client(s) has set the
2745 key locally they want to use, server does not know that key. */
2746 /* Nothing interesting to do here */
2748 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2749 /* The mode is removed and we need to generate and distribute
2750 new channel key. Clients are not using private channel keys
2751 anymore after this. */
2753 /* Re-generate channel key */
2754 if (!silc_server_create_channel_key(server, channel, 0))
2757 /* Send the channel key. This sends it to our local clients and if
2758 we are normal server to our router as well. */
2759 silc_server_send_channel_key(server, NULL, channel,
2760 server->server_type == SILC_ROUTER ?
2761 FALSE : !server->standalone);
2763 cipher = (char *)silc_cipher_get_name(channel->channel_key);
2764 hmac = (char *)silc_hmac_get_name(channel->hmac);
2768 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2769 /* User limit is set on channel */
2770 SilcUInt32 user_limit;
2772 /* Get user limit */
2773 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2775 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2776 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2777 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
2781 SILC_GET32_MSB(user_limit, tmp);
2782 channel->user_limit = user_limit;
2785 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2786 /* User limit mode is unset. Remove user limit */
2787 channel->user_limit = 0;
2790 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
2791 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
2792 /* Passphrase has been set to channel */
2794 /* Get the passphrase */
2795 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
2797 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2798 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
2802 /* Save the passphrase */
2803 passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
2806 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2807 /* Passphrase mode is unset. remove the passphrase */
2808 silc_free(channel->passphrase);
2809 channel->passphrase = NULL;
2813 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
2814 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
2815 /* Cipher to use protect the traffic */
2816 SilcCipher newkey, oldkey;
2819 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
2821 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2822 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
2826 /* Delete old cipher and allocate the new one */
2827 if (!silc_cipher_alloc(cipher, &newkey)) {
2828 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2829 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
2833 oldkey = channel->channel_key;
2834 channel->channel_key = newkey;
2836 /* Re-generate channel key */
2837 if (!silc_server_create_channel_key(server, channel, 0)) {
2838 /* We don't have new key, revert to old one */
2839 channel->channel_key = oldkey;
2843 /* Remove old channel key for good */
2844 silc_cipher_free(oldkey);
2846 /* Send the channel key. This sends it to our local clients and if
2847 we are normal server to our router as well. */
2848 silc_server_send_channel_key(server, NULL, channel,
2849 server->server_type == SILC_ROUTER ?
2850 FALSE : !server->standalone);
2853 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2854 /* Cipher mode is unset. Remove the cipher and revert back to
2856 SilcCipher newkey, oldkey;
2857 cipher = channel->cipher;
2859 /* Delete old cipher and allocate default one */
2860 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
2861 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2862 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
2866 oldkey = channel->channel_key;
2867 channel->channel_key = newkey;
2869 /* Re-generate channel key */
2870 if (!silc_server_create_channel_key(server, channel, 0)) {
2871 /* We don't have new key, revert to old one */
2872 channel->channel_key = oldkey;
2876 /* Remove old channel key for good */
2877 silc_cipher_free(oldkey);
2879 /* Send the channel key. This sends it to our local clients and if
2880 we are normal server to our router as well. */
2881 silc_server_send_channel_key(server, NULL, channel,
2882 server->server_type == SILC_ROUTER ?
2883 FALSE : !server->standalone);
2887 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
2888 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
2889 /* HMAC to use protect the traffic */
2890 unsigned char hash[32];
2894 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
2896 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2897 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
2901 /* Delete old hmac and allocate the new one */
2902 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
2903 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2904 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
2908 silc_hmac_free(channel->hmac);
2909 channel->hmac = newhmac;
2911 /* Set the HMAC key out of current channel key. The client must do
2913 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
2914 channel->key_len / 8, hash);
2915 silc_hmac_set_key(channel->hmac, hash,
2916 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
2917 memset(hash, 0, sizeof(hash));
2920 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
2921 /* Hmac mode is unset. Remove the hmac and revert back to
2924 unsigned char hash[32];
2925 hmac = channel->hmac_name;
2927 /* Delete old hmac and allocate default one */
2928 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
2929 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2930 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
2934 silc_hmac_free(channel->hmac);
2935 channel->hmac = newhmac;
2937 /* Set the HMAC key out of current channel key. The client must do
2939 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
2940 channel->key_len / 8,
2942 silc_hmac_set_key(channel->hmac, hash,
2943 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
2944 memset(hash, 0, sizeof(hash));
2948 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
2949 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2950 /* Check if the founder public key was received */
2951 founder_key = idata->public_key;
2952 tmp = silc_argument_get_arg_type(cmd->args, 8, &tmp_len);
2954 if (!silc_pkcs_public_key_payload_decode(tmp, tmp_len, &founder_key)) {
2955 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2956 SILC_STATUS_ERR_AUTH_FAILED,
2961 /* If key was not sent and the channel mode has already founder
2962 then the key was not to be changed. */
2963 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)
2967 /* Set the founder authentication */
2968 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
2970 silc_server_command_send_status_reply(
2971 cmd, SILC_COMMAND_CMODE,
2972 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
2976 /* Verify the payload before setting the mode */
2977 if (!silc_auth_verify_data(tmp, tmp_len, SILC_AUTH_PUBLIC_KEY,
2978 founder_key, 0, server->sha1hash,
2979 client->id, SILC_ID_CLIENT)) {
2980 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2981 SILC_STATUS_ERR_AUTH_FAILED,
2986 /* Save the public key */
2987 if (channel->founder_key)
2988 silc_pkcs_public_key_free(channel->founder_key);
2989 if (silc_argument_get_arg_type(cmd->args, 8, NULL))
2990 channel->founder_key = founder_key;
2992 channel->founder_key = silc_pkcs_public_key_copy(founder_key);
2993 if (!channel->founder_key) {
2994 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2995 SILC_STATUS_ERR_AUTH_FAILED,
3000 fkey = silc_pkcs_public_key_payload_encode(channel->founder_key);
3002 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3003 SILC_STATUS_ERR_AUTH_FAILED,
3005 silc_pkcs_public_key_free(channel->founder_key);
3006 channel->founder_key = NULL;
3012 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3013 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3014 if (channel->founder_key)
3015 silc_pkcs_public_key_free(channel->founder_key);
3016 channel->founder_key = NULL;
3021 /* Finally, set the mode */
3022 old_mask = channel->mode = mode_mask;
3024 /* Send CMODE_CHANGE notify. */
3025 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3026 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3027 SILC_NOTIFY_TYPE_CMODE_CHANGE, 6,
3028 cidp->data, cidp->len,
3030 cipher, cipher ? strlen(cipher) : 0,
3031 hmac, hmac ? strlen(hmac) : 0,
3032 passphrase, passphrase ?
3033 strlen(passphrase) : 0,
3034 fkey ? fkey->data : NULL,
3035 fkey ? fkey->len : 0);
3037 /* Set CMODE notify type to network */
3038 silc_server_send_notify_cmode(server, SILC_PRIMARY_ROUTE(server),
3039 SILC_BROADCAST(server), channel,
3040 mode_mask, client->id, SILC_ID_CLIENT,
3041 cipher, hmac, passphrase, founder_key);
3043 /* Send command reply to sender */
3044 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3045 SILC_STATUS_OK, 0, ident, 3,
3046 2, tmp_id, tmp_len2,
3048 4, fkey ? fkey->data : NULL,
3049 fkey ? fkey->len : 0);
3050 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3051 packet->data, packet->len, FALSE);
3053 silc_buffer_free(packet);
3054 silc_buffer_free(cidp);
3057 channel->mode = old_mask;
3058 silc_buffer_free(fkey);
3059 silc_free(channel_id);
3060 silc_server_command_free(cmd);
3063 /* Server side of CUMODE command. Changes client's mode on a channel. */
3065 SILC_SERVER_CMD_FUNC(cumode)
3067 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3068 SilcServer server = cmd->server;
3069 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3070 SilcChannelID *channel_id = NULL;
3071 SilcClientID *client_id = NULL;
3072 SilcChannelEntry channel;
3073 SilcClientEntry target_client;
3074 SilcChannelClientEntry chl;
3075 SilcBuffer packet, idp;
3076 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
3077 SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
3079 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3080 SilcPublicKey founder_key = NULL;
3081 SilcBuffer fkey = NULL;
3086 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
3088 /* Get Channel ID */
3089 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3091 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3092 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3095 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
3097 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3098 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3102 /* Get channel entry */
3103 channel = silc_idlist_find_channel_by_id(server->local_list,
3106 channel = silc_idlist_find_channel_by_id(server->global_list,
3109 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3110 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
3116 /* Check whether sender is on the channel */
3117 if (!silc_server_client_on_channel(client, channel, &chl)) {
3118 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3119 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
3122 sender_mask = chl->mode;
3124 /* Get the target client's channel mode mask */
3125 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3127 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3128 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3132 SILC_GET32_MSB(target_mask, tmp_mask);
3134 /* Get target Client ID */
3135 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3137 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3138 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
3141 client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
3143 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3144 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
3148 /* Get target client's entry */
3149 target_client = silc_idlist_find_client_by_id(server->local_list,
3150 client_id, TRUE, NULL);
3151 if (!target_client) {
3152 target_client = silc_idlist_find_client_by_id(server->global_list,
3153 client_id, TRUE, NULL);
3156 if (target_client != client &&
3157 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
3158 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
3159 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3160 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
3164 /* Check whether target client is on the channel */
3165 if (target_client != client) {
3166 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
3167 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3168 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL, 0);
3177 /* If the target client is founder, no one else can change their mode
3179 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
3180 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3181 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
3186 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
3187 if (target_client != client) {
3188 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3189 SILC_STATUS_ERR_NOT_YOU, 0);
3193 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
3194 /* The client tries to claim the founder rights. */
3195 unsigned char *tmp_auth;
3196 SilcUInt32 tmp_auth_len;
3197 SilcChannelClientEntry chl2;
3198 SilcHashTableList htl;
3200 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
3201 !channel->founder_key) {
3202 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3203 SILC_STATUS_ERR_AUTH_FAILED, 0);
3207 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
3209 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3210 SILC_STATUS_ERR_AUTH_FAILED, 0);
3214 /* Verify the authentication payload */
3215 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len, SILC_AUTH_PUBLIC_KEY,
3216 channel->founder_key, 0, server->sha1hash,
3217 client->id, SILC_ID_CLIENT)) {
3218 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3219 SILC_STATUS_ERR_AUTH_FAILED, 0);
3224 founder_key = channel->founder_key;
3225 fkey = silc_pkcs_public_key_payload_encode(founder_key);
3227 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3228 SILC_STATUS_ERR_AUTH_FAILED, 0);
3232 /* There cannot be anyone else as founder on the channel now. This
3233 client is definitely the founder due to this authentication */
3234 silc_hash_table_list(channel->user_list, &htl);
3235 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
3236 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
3237 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3238 silc_server_force_cumode_change(server, NULL, channel, chl2,
3242 silc_hash_table_list_reset(&htl);
3244 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
3247 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3248 if (target_client == client) {
3249 /* Remove channel founder rights from itself */
3250 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3253 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3254 SILC_STATUS_ERR_NOT_YOU, 0);
3260 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
3261 /* Promote to operator */
3262 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3263 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3264 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3265 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3266 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
3271 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
3275 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
3276 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3277 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3278 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3279 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
3284 /* Demote to normal user */
3285 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
3290 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
3291 if (target_client != client) {
3292 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3293 SILC_STATUS_ERR_NOT_YOU, 0);
3297 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
3298 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
3302 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
3303 if (target_client != client) {
3304 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3305 SILC_STATUS_ERR_NOT_YOU, 0);
3309 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
3314 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
3315 if (target_client != client) {
3316 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3317 SILC_STATUS_ERR_NOT_YOU, 0);
3321 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)) {
3322 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
3326 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
3327 if (target_client != client) {
3328 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3329 SILC_STATUS_ERR_NOT_YOU, 0);
3333 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
3338 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
3339 if (target_client != client) {
3340 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3341 SILC_STATUS_ERR_NOT_YOU, 0);
3345 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)) {
3346 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
3350 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
3351 if (target_client != client) {
3352 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3353 SILC_STATUS_ERR_NOT_YOU, 0);
3357 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
3362 if (target_mask & SILC_CHANNEL_UMODE_QUIET) {
3363 if (!(chl->mode & SILC_CHANNEL_UMODE_QUIET)) {
3364 if (client == target_client) {
3365 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3366 SILC_STATUS_ERR_PERM_DENIED, 0);
3369 chl->mode |= SILC_CHANNEL_UMODE_QUIET;
3373 if (chl->mode & SILC_CHANNEL_UMODE_QUIET) {
3374 if (client == target_client) {
3375 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3376 SILC_STATUS_ERR_PERM_DENIED, 0);
3379 chl->mode &= ~SILC_CHANNEL_UMODE_QUIET;
3384 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3385 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3387 /* Send notify to channel, notify only if mode was actually changed. */
3389 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3390 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
3391 idp->data, idp->len,
3394 fkey ? fkey->data : NULL,
3395 fkey ? fkey->len : 0);
3397 /* Set CUMODE notify type to network */
3398 silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
3399 SILC_BROADCAST(server), channel,
3400 target_mask, client->id, SILC_ID_CLIENT,
3401 target_client->id, founder_key);
3404 /* Send command reply to sender */
3405 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
3406 SILC_STATUS_OK, 0, ident, 3,
3408 3, tmp_ch_id, tmp_ch_len,
3409 4, tmp_id, tmp_len);
3410 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3411 packet->data, packet->len, FALSE);
3413 silc_buffer_free(packet);
3414 silc_buffer_free(idp);
3417 silc_free(channel_id);
3418 silc_free(client_id);
3419 silc_buffer_free(fkey);
3420 silc_server_command_free(cmd);
3423 /* Server side of KICK command. Kicks client out of channel. */
3425 SILC_SERVER_CMD_FUNC(kick)
3427 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3428 SilcServer server = cmd->server;
3429 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3430 SilcClientEntry target_client;
3431 SilcChannelID *channel_id;
3432 SilcClientID *client_id;
3433 SilcChannelEntry channel;
3434 SilcChannelClientEntry chl;
3436 SilcUInt32 tmp_len, target_idp_len;
3437 unsigned char *tmp, *comment, *target_idp;
3442 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
3444 /* Get Channel ID */
3445 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3447 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3448 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3451 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3453 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3454 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3458 /* Get channel entry */
3459 channel = silc_idlist_find_channel_by_id(server->local_list,
3462 channel = silc_idlist_find_channel_by_id(server->local_list,
3465 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3466 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
3472 /* Check whether sender is on the channel */
3473 if (!silc_server_client_on_channel(client, channel, &chl)) {
3474 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3475 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
3479 /* Check that the kicker is channel operator or channel founder */
3480 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
3481 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
3482 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3483 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
3487 /* Get target Client ID */
3488 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
3490 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3491 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
3494 client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
3496 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3497 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
3501 /* Get target client's entry */
3502 target_client = silc_idlist_find_client_by_id(server->local_list,
3503 client_id, TRUE, NULL);
3504 if (!target_client) {
3505 target_client = silc_idlist_find_client_by_id(server->global_list,
3506 client_id, TRUE, NULL);
3509 /* Check whether target client is on the channel */
3510 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
3511 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3512 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL,
3517 /* Check that the target client is not channel founder. Channel founder
3518 cannot be kicked from the channel. */
3519 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3520 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3521 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
3528 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3532 /* Send command reply to sender */
3533 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3536 /* Send KICKED notify to local clients on the channel */
3537 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3538 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3539 SILC_NOTIFY_TYPE_KICKED, 3,
3540 target_idp, target_idp_len,
3541 comment, comment ? strlen(comment) : 0,
3542 idp->data, idp->len);
3543 silc_buffer_free(idp);
3545 /* Send KICKED notify to primary route */
3546 silc_server_send_notify_kicked(server, SILC_PRIMARY_ROUTE(server),
3547 SILC_BROADCAST(server), channel,
3548 target_client->id, client->id, comment);
3550 /* Remove the client from channel's invite list */
3551 if (channel->invite_list && silc_hash_table_count(channel->invite_list)) {
3553 silc_argument_payload_encode_one(NULL, target_idp, target_idp_len, 3);
3554 SilcArgumentPayload args =
3555 silc_argument_payload_parse(ab->data, ab->len, 1);
3556 silc_server_inviteban_process(server, channel->invite_list, 1, args);
3557 silc_buffer_free(ab);
3558 silc_argument_payload_free(args);
3561 /* Remove the client from the channel. If the channel does not exist
3562 after removing the client then the client kicked itself off the channel
3563 and we don't have to send anything after that. */
3564 if (!silc_server_remove_from_one_channel(server, NULL, channel,
3565 target_client, FALSE))
3568 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3569 /* Re-generate channel key */
3570 if (!silc_server_create_channel_key(server, channel, 0))
3573 /* Send the channel key to the channel. The key of course is not sent
3574 to the client who was kicked off the channel. */
3575 silc_server_send_channel_key(server, target_client->connection, channel,
3576 server->server_type == SILC_ROUTER ?
3577 FALSE : !server->standalone);
3581 silc_server_command_free(cmd);
3584 /* Server side of OPER command. Client uses this comand to obtain server
3585 operator privileges to this server/router. */
3587 SILC_SERVER_CMD_FUNC(oper)
3589 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3590 SilcServer server = cmd->server;
3591 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3592 unsigned char *username, *auth;
3594 SilcServerConfigAdmin *admin;
3595 SilcIDListData idata = (SilcIDListData)client;
3596 bool result = FALSE;
3597 SilcPublicKey cached_key;
3599 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
3602 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
3604 /* Get the username */
3605 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3607 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3608 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3613 /* Get the admin configuration */
3614 admin = silc_server_config_find_admin(server, cmd->sock->ip,
3615 username, client->nickname);
3617 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
3618 username, client->nickname);
3620 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3621 SILC_STATUS_ERR_AUTH_FAILED,
3623 SILC_LOG_INFO(("OPER authentication failed for username '%s' by "
3624 "nickname '%s' from %s", username,
3625 client->nickname, cmd->sock->hostname));
3630 /* Get the authentication payload */
3631 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3633 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3634 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3639 /* Verify the authentication data. If both passphrase and public key
3640 is set then try both of them. */
3641 if (admin->passphrase)
3642 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
3643 admin->passphrase, admin->passphrase_len,
3644 idata->hash, client->id, SILC_ID_CLIENT);
3645 if (!result && admin->publickeys) {
3646 cached_key = silc_server_get_public_key(server, admin->publickeys);
3649 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
3650 cached_key, 0, idata->hash,
3651 client->id, SILC_ID_CLIENT);
3654 /* Authentication failed */
3655 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3656 SILC_STATUS_ERR_AUTH_FAILED,
3661 /* Client is now server operator */
3662 client->mode |= SILC_UMODE_SERVER_OPERATOR;
3664 /* Update statistics */
3665 if (SILC_IS_LOCAL(client))
3666 server->stat.my_server_ops++;
3667 if (server->server_type == SILC_ROUTER)
3668 server->stat.server_ops++;
3670 /* Send UMODE change to primary router */
3671 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
3672 SILC_BROADCAST(server), client->id,
3675 /* Check if anyone is watching this nickname */
3676 if (server->server_type == SILC_ROUTER)
3677 silc_server_check_watcher_list(server, client, NULL,
3678 SILC_NOTIFY_TYPE_UMODE_CHANGE);
3680 /* Send reply to the sender */
3681 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3685 silc_server_command_free(cmd);
3688 SILC_TASK_CALLBACK(silc_server_command_detach_cb)
3690 SilcServer server = app_context;
3691 QuitInternal q = (QuitInternal)context;
3692 SilcClientID *client_id = (SilcClientID *)q->sock;
3693 SilcClientEntry client;
3694 SilcSocketConnection sock;
3696 client = silc_idlist_find_client_by_id(server->local_list, client_id,
3698 if (client && client->connection) {
3699 sock = client->connection;
3701 /* If there is pending outgoing data for the client then purge it
3702 to the network before closing connection. */
3703 silc_server_packet_queue_purge(server, sock);
3705 /* Close the connection on our side */
3706 client->router = NULL;
3707 client->connection = NULL;
3708 sock->user_data = NULL;
3709 silc_server_close_connection(server, sock);
3712 silc_free(client_id);
3716 SILC_TASK_CALLBACK(silc_server_command_detach_timeout)
3718 SilcServer server = app_context;
3719 QuitInternal q = (QuitInternal)context;
3720 SilcClientID *client_id = (SilcClientID *)q->sock;
3721 SilcClientEntry client;
3723 client = silc_idlist_find_client_by_id(server->local_list, client_id,
3725 if (client && client->mode & SILC_UMODE_DETACHED) {
3726 SILC_LOG_DEBUG(("Detach timeout"));
3727 silc_server_free_client_data(server, NULL, client, TRUE,
3731 silc_free(client_id);
3735 /* Server side of DETACH command. Detached the client from the network
3736 by closing the connection but preserving the session. */
3738 SILC_SERVER_CMD_FUNC(detach)
3740 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3741 SilcServer server = cmd->server;
3742 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3745 if (server->config->detach_disabled) {
3746 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
3747 SILC_STATUS_ERR_OPERATION_ALLOWED,
3752 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
3755 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
3757 /* Remove operator privileges, since the client may resume in some
3758 other server which to it does not have operator privileges. */
3759 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
3760 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
3762 /* Send the user mode notify to notify that client is detached */
3763 client->mode |= SILC_UMODE_DETACHED;
3764 client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
3765 client->data.status &= ~SILC_IDLIST_STATUS_NOATTR;
3766 client->last_command = 0;
3767 client->fast_command = 0;
3768 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
3769 SILC_BROADCAST(server), client->id,
3771 server->stat.my_detached++;
3773 /* Check if anyone is watching this nickname */
3774 if (server->server_type == SILC_ROUTER)
3775 silc_server_check_watcher_list(server, client, NULL,
3776 SILC_NOTIFY_TYPE_UMODE_CHANGE);
3778 q = silc_calloc(1, sizeof(*q));
3779 q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
3780 silc_schedule_task_add(server->schedule, 0, silc_server_command_detach_cb,
3781 q, 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
3783 if (server->config->detach_timeout) {
3784 q = silc_calloc(1, sizeof(*q));
3785 q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
3786 silc_schedule_task_add(server->schedule, 0,
3787 silc_server_command_detach_timeout,
3788 q, server->config->detach_timeout * 60,
3789 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
3792 /* Send reply to the sender */
3793 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
3797 silc_server_command_free(cmd);
3800 /* Server side of WATCH command. */
3802 SILC_SERVER_CMD_FUNC(watch)
3804 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3805 SilcServer server = cmd->server;
3806 char *add_nick, *del_nick;
3807 SilcUInt32 add_nick_len, del_nick_len, tmp_len;
3809 unsigned char hash[16], *tmp;
3810 SilcClientEntry client;
3811 SilcClientID *client_id = NULL;
3813 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WATCH, cmd, 1, 3);
3815 if (server->server_type != SILC_ROUTER && !server->standalone) {
3816 if (!cmd->pending) {
3817 /* Send the command to router */
3819 SilcUInt16 old_ident;
3821 SILC_LOG_DEBUG(("Forwarding WATCH to router"));
3823 old_ident = silc_command_get_ident(cmd->payload);
3824 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3825 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3827 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
3828 SILC_PACKET_COMMAND, cmd->packet->flags,
3829 tmpbuf->data, tmpbuf->len, TRUE);
3831 /* Reprocess this packet after received reply from router */
3832 silc_server_command_pending(server, SILC_COMMAND_WATCH,
3833 silc_command_get_ident(cmd->payload),
3834 silc_server_command_watch,
3835 silc_server_command_dup(cmd));
3836 cmd->pending = TRUE;
3837 silc_command_set_ident(cmd->payload, old_ident);
3838 silc_buffer_free(tmpbuf);
3839 } else if (context2) {
3840 /* Received reply from router, just send same data to the client. */
3841 SilcServerCommandReplyContext reply = context2;
3844 SILC_LOG_DEBUG(("Received reply to WATCH from router"));
3845 silc_command_get_status(reply->payload, &status, NULL);
3846 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, status,
3853 /* We are router and keep the watch list for local cell */
3855 /* Get the client ID */
3856 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3858 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
3859 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3863 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3865 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
3866 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
3871 /* Get the client entry which must be in local list */
3872 client = silc_idlist_find_client_by_id(server->local_list,
3873 client_id, TRUE, NULL);
3875 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
3876 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
3882 add_nick = silc_argument_get_arg_type(cmd->args, 2, &add_nick_len);
3883 del_nick = silc_argument_get_arg_type(cmd->args, 3, &del_nick_len);
3884 if (!add_nick && !del_nick) {
3885 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
3886 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3891 if (add_nick && add_nick_len > 128)
3892 add_nick[128] = '\0';
3893 if (del_nick && del_nick_len > 128)
3894 del_nick[128] = '\0';
3896 memset(nick, 0, sizeof(nick));
3898 /* Add new nickname to be watched in our cell */
3900 if (silc_server_name_bad_chars(add_nick, strlen(add_nick)) == TRUE) {
3901 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
3902 SILC_STATUS_ERR_BAD_NICKNAME, 0);
3906 /* Hash the nick, we have the hash saved, not nicks because we can
3907 do one to one mapping to the nick from Client ID hash this way. */
3908 silc_to_lower(add_nick, nick, sizeof(nick) - 1);
3909 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
3911 /* Check whether this client is already watching this nickname */
3912 if (silc_hash_table_find_by_context(server->watcher_list, hash,
3914 /* Nickname is alredy being watched for this client */
3915 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
3916 SILC_STATUS_ERR_NICKNAME_IN_USE,
3921 /* Get the nickname from the watcher list and use the same key in
3922 new entries as well. If key doesn't exist then create it. */
3923 if (!silc_hash_table_find(server->watcher_list, hash, (void **)&tmp, NULL))
3924 tmp = silc_memdup(hash, CLIENTID_HASH_LEN);
3926 /* Add the client to the watcher list with the specified nickname hash. */
3927 silc_hash_table_add(server->watcher_list, tmp, client);
3930 /* Delete nickname from watch list */
3932 if (silc_server_name_bad_chars(del_nick, strlen(del_nick)) == TRUE) {
3933 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
3934 SILC_STATUS_ERR_BAD_NICKNAME, 0);
3938 /* Hash the nick, we have the hash saved, not nicks because we can
3939 do one to one mapping to the nick from Client ID hash this way. */
3940 silc_to_lower(del_nick, nick, sizeof(nick) - 1);
3941 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
3943 /* Check that this client is watching for this nickname */
3944 if (!silc_hash_table_find_by_context(server->watcher_list, hash,
3945 client, (void **)&tmp)) {
3946 /* Nickname is alredy being watched for this client */
3947 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
3948 SILC_STATUS_ERR_NO_SUCH_NICK, 0);
3952 /* Delete the nickname from the watcher list. */
3953 silc_hash_table_del_by_context(server->watcher_list, hash, client);
3955 /* Now check whether there still exists entries with this key, if not
3956 then free the key to not leak memory. */
3957 if (!silc_hash_table_find(server->watcher_list, hash, NULL, NULL))
3961 /* Distribute the watch list to backup routers too */
3962 if (server->backup) {
3964 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3965 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3966 silc_server_backup_send(server, NULL, SILC_PACKET_COMMAND,
3967 cmd->packet->flags, tmpbuf->data, tmpbuf->len,
3969 silc_buffer_free(tmpbuf);
3972 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
3976 silc_free(client_id);
3977 silc_server_command_free(cmd);
3980 /* Server side of SILCOPER command. Client uses this comand to obtain router
3981 operator privileges to this router. */
3983 SILC_SERVER_CMD_FUNC(silcoper)
3985 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3986 SilcServer server = cmd->server;
3987 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3988 unsigned char *username, *auth;
3990 SilcServerConfigAdmin *admin;
3991 SilcIDListData idata = (SilcIDListData)client;
3992 bool result = FALSE;
3993 SilcPublicKey cached_key;
3995 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
3998 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4000 if (server->server_type != SILC_ROUTER) {
4001 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4002 SILC_STATUS_ERR_AUTH_FAILED, 0);
4006 /* Get the username */
4007 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4009 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4010 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4015 /* Get the admin configuration */
4016 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4017 username, client->nickname);
4019 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4020 username, client->nickname);
4022 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4023 SILC_STATUS_ERR_AUTH_FAILED, 0);
4024 SILC_LOG_INFO(("SILCOPER authentication failed for username '%s' by "
4025 "nickname '%s' from %s", username,
4026 client->nickname, cmd->sock->hostname));
4031 /* Get the authentication payload */
4032 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4034 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4035 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4040 /* Verify the authentication data. If both passphrase and public key
4041 is set then try both of them. */
4042 if (admin->passphrase)
4043 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4044 admin->passphrase, admin->passphrase_len,
4045 idata->hash, client->id, SILC_ID_CLIENT);
4046 if (!result && admin->publickeys) {
4047 cached_key = silc_server_get_public_key(server, admin->publickeys);
4050 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4051 cached_key, 0, idata->hash,
4052 client->id, SILC_ID_CLIENT);
4055 /* Authentication failed */
4056 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4057 SILC_STATUS_ERR_AUTH_FAILED, 0);
4061 /* Client is now router operator */
4062 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4064 /* Update statistics */
4065 if (SILC_IS_LOCAL(client))
4066 server->stat.my_router_ops++;
4067 if (server->server_type == SILC_ROUTER)
4068 server->stat.router_ops++;
4070 /* Send UMODE change to primary router */
4071 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
4072 SILC_BROADCAST(server), client->id,
4075 /* Check if anyone is watching this nickname */
4076 if (server->server_type == SILC_ROUTER)
4077 silc_server_check_watcher_list(server, client, NULL,
4078 SILC_NOTIFY_TYPE_UMODE_CHANGE);
4080 /* Send reply to the sender */
4081 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4085 silc_server_command_free(cmd);
4088 /* Server side of command BAN. This is used to manage the ban list of the
4089 channel. To add clients and remove clients from the ban list. */
4091 SILC_SERVER_CMD_FUNC(ban)
4093 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4094 SilcServer server = cmd->server;
4095 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4096 SilcBuffer packet, list, tmp2;
4097 SilcChannelEntry channel;
4098 SilcChannelClientEntry chl;
4099 SilcChannelID *channel_id = NULL;
4100 unsigned char *id, *tmp, *atype = NULL;
4101 SilcUInt32 id_len, len, len2;
4102 SilcArgumentPayload args;
4103 SilcHashTableList htl;
4105 SilcUInt16 argc = 0, ident = silc_command_get_ident(cmd->payload);
4106 SilcBufferStruct blist;
4108 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
4111 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4113 /* Get Channel ID */
4114 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4116 channel_id = silc_id_payload_parse_id(id, id_len, NULL);
4118 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4119 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4124 /* Get channel entry. The server must know about the channel since the
4125 client is expected to be on the channel. */
4126 channel = silc_idlist_find_channel_by_id(server->local_list,
4129 channel = silc_idlist_find_channel_by_id(server->global_list,
4132 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4133 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4139 /* Check whether this client is on the channel */
4140 if (!silc_server_client_on_channel(client, channel, &chl)) {
4141 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4142 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4146 /* The client must be at least channel operator. */
4147 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4148 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4149 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
4153 /* Get the ban information */
4154 tmp = silc_argument_get_arg_type(cmd->args, 3, &len2);
4155 if (tmp && len2 > 2) {
4156 /* Parse the arguments to see they are constructed correctly */
4157 SILC_GET16_MSB(argc, tmp);
4158 args = silc_argument_payload_parse(tmp + 2, len2 - 2, argc);
4160 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4161 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4166 /* Get the type of action */
4167 atype = silc_argument_get_arg_type(cmd->args, 2, &len);
4168 if (atype && len == 1) {
4169 if (atype[0] == 0x00) {
4170 /* Allocate hash table for ban list if it doesn't exist yet */
4171 if (!channel->ban_list)
4173 silc_hash_table_alloc(0, silc_hash_ptr,
4175 silc_server_inviteban_destruct, channel,
4178 /* Check for resource limit */
4179 if (silc_hash_table_count(channel->ban_list) > 64) {
4180 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4181 SILC_STATUS_ERR_RESOURCE_LIMIT,
4187 /* Now add or delete the information. */
4188 silc_server_inviteban_process(server, channel->ban_list,
4189 (SilcUInt8)atype[0], args);
4191 silc_argument_payload_free(args);
4194 /* Encode ban list */
4196 if (channel->ban_list && silc_hash_table_count(channel->ban_list)) {
4197 list = silc_buffer_alloc_size(2);
4198 silc_buffer_format(list,
4199 SILC_STR_UI_SHORT(silc_hash_table_count(
4200 channel->ban_list)),
4202 silc_hash_table_list(channel->ban_list, &htl);
4203 while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2))
4204 list = silc_argument_payload_encode_one(list, tmp2->data, tmp2->len,
4206 silc_hash_table_list_reset(&htl);
4209 /* Send the BAN notify type to our primary router. */
4210 if (atype && tmp && len2) {
4211 silc_buffer_set(&blist, tmp, len2);
4212 silc_server_send_notify_ban(server, SILC_PRIMARY_ROUTE(server),
4213 SILC_BROADCAST(server), channel, atype,
4217 /* Send the reply back to the client */
4219 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4220 SILC_STATUS_OK, 0, ident, 2,
4222 3, list ? list->data : NULL,
4223 list ? list->len : 0);
4224 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4225 packet->data, packet->len, FALSE);
4227 silc_buffer_free(packet);
4228 silc_buffer_free(list);
4231 silc_free(channel_id);
4232 silc_server_command_free(cmd);
4235 /* Server side command of LEAVE. Removes client from a channel. */
4237 SILC_SERVER_CMD_FUNC(leave)
4239 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4240 SilcServer server = cmd->server;
4241 SilcSocketConnection sock = cmd->sock;
4242 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4243 SilcChannelID *id = NULL;
4244 SilcChannelEntry channel;
4248 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !id_entry)
4251 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4253 /* Get Channel ID */
4254 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4256 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4257 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4260 id = silc_id_payload_parse_id(tmp, len, NULL);
4262 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4263 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4267 /* Get channel entry */
4268 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4270 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4272 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4273 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4279 /* Check whether this client is on the channel */
4280 if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
4281 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4282 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4286 /* Notify routers that they should remove this client from their list
4287 of clients on the channel. Send LEAVE notify type. */
4288 silc_server_send_notify_leave(server, SILC_PRIMARY_ROUTE(server),
4289 SILC_BROADCAST(server), channel, id_entry->id);
4291 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4292 SILC_STATUS_OK, 0, 2, tmp, len);
4294 /* Remove client from channel */
4295 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4297 /* If the channel does not exist anymore we won't send anything */
4300 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4301 /* Re-generate channel key */
4302 if (!silc_server_create_channel_key(server, channel, 0))
4305 /* Send the channel key */
4306 silc_server_send_channel_key(server, NULL, channel,
4307 server->server_type == SILC_ROUTER ?
4308 FALSE : !server->standalone);
4313 silc_server_command_free(cmd);
4316 /* Server side of command USERS. Resolves clients and their USERS currently
4317 joined on the requested channel. The list of Client ID's and their modes
4318 on the channel is sent back. */
4320 SILC_SERVER_CMD_FUNC(users)
4322 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4323 SilcServer server = cmd->server;
4324 SilcChannelEntry channel;
4325 SilcChannelID *id = NULL;
4326 SilcBuffer packet, idp;
4327 unsigned char *channel_id;
4328 SilcUInt32 channel_id_len;
4329 SilcBuffer client_id_list;
4330 SilcBuffer client_mode_list;
4331 unsigned char lc[4];
4332 SilcUInt32 list_count = 0;
4333 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4336 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
4338 /* Get Channel ID */
4339 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4341 /* Get channel name */
4342 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
4344 if (!channel_id && !channel_name) {
4345 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4346 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4351 id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
4353 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4354 SILC_STATUS_ERR_BAD_CHANNEL_ID, 0);
4359 /* If we are server and we don't know about this channel we will send
4360 the command to our router. If we know about the channel then we also
4361 have the list of users already. */
4363 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4365 channel = silc_idlist_find_channel_by_name(server->local_list,
4366 channel_name, NULL);
4368 if (!channel || (!server->standalone && (channel->disabled ||
4369 !channel->users_resolved))) {
4370 if (server->server_type != SILC_ROUTER && !server->standalone &&
4374 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4375 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4377 /* Send USERS command */
4378 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
4379 SILC_PACKET_COMMAND, cmd->packet->flags,
4380 tmpbuf->data, tmpbuf->len, TRUE);
4382 /* Reprocess this packet after received reply */
4383 silc_server_command_pending(server, SILC_COMMAND_USERS,
4384 silc_command_get_ident(cmd->payload),
4385 silc_server_command_users,
4386 silc_server_command_dup(cmd));
4387 cmd->pending = TRUE;
4388 silc_command_set_ident(cmd->payload, ident);
4389 silc_buffer_free(tmpbuf);
4394 /* Check the global list as well. */
4396 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4398 channel = silc_idlist_find_channel_by_name(server->global_list,
4399 channel_name, NULL);
4401 /* Channel really does not exist */
4402 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4403 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4409 /* If the channel is private or secret do not send anything, unless the
4410 user requesting this command is on the channel or is server */
4411 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
4412 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
4413 && !silc_server_client_on_channel(cmd->sock->user_data, channel,
4415 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4416 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4422 /* Get the users list */
4423 if (!silc_server_get_users_on_channel(server, channel, &client_id_list,
4424 &client_mode_list, &list_count)) {
4426 client_id_list = NULL;
4427 client_mode_list = NULL;
4431 SILC_PUT32_MSB(list_count, lc);
4434 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
4435 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
4436 SILC_STATUS_OK, 0, ident, 4,
4437 2, idp->data, idp->len,
4440 client_id_list->data : NULL,
4442 client_id_list->len : 0,
4443 5, client_mode_list ?
4444 client_mode_list->data : NULL,
4446 client_mode_list->len : 0);
4447 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4448 packet->data, packet->len, FALSE);
4450 silc_buffer_free(idp);
4451 silc_buffer_free(packet);
4453 silc_buffer_free(client_id_list);
4454 if (client_mode_list)
4455 silc_buffer_free(client_mode_list);
4459 silc_server_command_free(cmd);
4462 /* Server side of command GETKEY. This fetches the client's public key
4463 from the server where to the client is connected. */
4465 SILC_SERVER_CMD_FUNC(getkey)
4467 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4468 SilcServer server = cmd->server;
4470 SilcClientEntry client;
4471 SilcServerEntry server_entry;
4472 SilcClientID *client_id = NULL;
4473 SilcServerID *server_id = NULL;
4474 SilcIDPayload idp = NULL;
4475 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4478 SilcBuffer pk = NULL;
4480 SilcPublicKey public_key;
4482 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4484 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4485 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4489 idp = silc_id_payload_parse(tmp, tmp_len);
4491 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4492 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4497 id_type = silc_id_payload_get_type(idp);
4498 if (id_type == SILC_ID_CLIENT) {
4499 client_id = silc_id_payload_get_id(idp);
4501 /* If the client is not found from local list there is no chance it
4502 would be locally connected client so send the command further. */
4503 client = silc_idlist_find_client_by_id(server->local_list,
4504 client_id, TRUE, NULL);
4506 client = silc_idlist_find_client_by_id(server->global_list,
4507 client_id, TRUE, NULL);
4509 if ((!client && !cmd->pending && !server->standalone) ||
4510 (client && !client->connection && !cmd->pending &&
4511 !(client->mode & SILC_UMODE_DETACHED)) ||
4512 (client && !client->data.public_key && !cmd->pending)) {
4514 SilcUInt16 old_ident;
4515 SilcSocketConnection dest_sock;
4517 dest_sock = silc_server_get_client_route(server, NULL, 0,
4518 client_id, NULL, NULL);
4522 old_ident = silc_command_get_ident(cmd->payload);
4523 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4524 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4526 silc_server_packet_send(server, dest_sock,
4527 SILC_PACKET_COMMAND, cmd->packet->flags,
4528 tmpbuf->data, tmpbuf->len, TRUE);
4530 /* Reprocess this packet after received reply from router */
4531 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
4532 silc_command_get_ident(cmd->payload),
4533 silc_server_command_getkey,
4534 silc_server_command_dup(cmd));
4535 cmd->pending = TRUE;
4536 silc_command_set_ident(cmd->payload, old_ident);
4537 silc_buffer_free(tmpbuf);
4542 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4543 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
4548 /* The client is locally connected, just get the public key and
4549 send it back. If they key does not exist then do not send it,
4550 send just OK reply */
4551 public_key = client->data.public_key;
4553 pk = silc_pkcs_public_key_payload_encode(public_key);
4554 } else if (id_type == SILC_ID_SERVER) {
4555 server_id = silc_id_payload_get_id(idp);
4557 /* If the server is not found from local list there is no chance it
4558 would be locally connected server so send the command further. */
4559 server_entry = silc_idlist_find_server_by_id(server->local_list,
4560 server_id, TRUE, NULL);
4562 server_entry = silc_idlist_find_server_by_id(server->global_list,
4563 server_id, TRUE, NULL);
4565 if (server_entry != server->id_entry &&
4566 ((!server_entry && !cmd->pending && !server->standalone) ||
4567 (server_entry && !server_entry->connection && !cmd->pending &&
4568 !server->standalone) ||
4569 (server_entry && !server_entry->data.public_key && !cmd->pending &&
4570 !server->standalone))) {
4572 SilcUInt16 old_ident;
4574 old_ident = silc_command_get_ident(cmd->payload);
4575 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4576 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4578 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
4579 SILC_PACKET_COMMAND, cmd->packet->flags,
4580 tmpbuf->data, tmpbuf->len, TRUE);
4582 /* Reprocess this packet after received reply from router */
4583 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
4584 silc_command_get_ident(cmd->payload),
4585 silc_server_command_getkey,
4586 silc_server_command_dup(cmd));
4587 cmd->pending = TRUE;
4588 silc_command_set_ident(cmd->payload, old_ident);
4589 silc_buffer_free(tmpbuf);
4593 if (!server_entry) {
4594 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4595 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
4600 /* If they key does not exist then do not send it, send just OK reply */
4601 public_key = (!server_entry->data.public_key ?
4602 (server_entry == server->id_entry ? server->public_key :
4603 NULL) : server_entry->data.public_key);
4605 pk = silc_pkcs_public_key_payload_encode(public_key);
4610 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4611 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
4612 SILC_STATUS_OK, 0, ident, 2,
4614 3, pk ? pk->data : NULL,
4616 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4617 packet->data, packet->len, FALSE);
4618 silc_buffer_free(packet);
4622 silc_id_payload_free(idp);
4623 silc_buffer_free(pk);
4624 silc_free(client_id);
4625 silc_free(server_id);
4626 silc_server_command_free(cmd);
4630 /* Private range commands, specific to this implementation */
4632 /* Server side command of CONNECT. Connects us to the specified remote
4633 server or router. */
4635 SILC_SERVER_CMD_FUNC(connect)
4637 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4638 SilcServer server = cmd->server;
4639 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4640 unsigned char *tmp, *host;
4642 SilcUInt32 port = SILC_PORT;
4644 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
4647 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
4649 /* Check whether client has the permissions. */
4650 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
4651 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
4652 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
4653 SILC_STATUS_ERR_NO_SERVER_PRIV, 0);
4657 if (server->server_type == SILC_ROUTER && !server->backup_router &&
4658 client->mode & SILC_UMODE_SERVER_OPERATOR) {
4659 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
4660 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
4664 /* Get the remote server */
4665 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4667 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
4668 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4674 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4676 SILC_GET32_MSB(port, tmp);
4678 /* Create the connection. It is done with timeout and is async. */
4679 silc_server_create_connection(server, host, port);
4681 /* Send reply to the sender */
4682 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
4686 silc_server_command_free(cmd);
4689 /* Server side command of CLOSE. Closes connection to a specified server. */
4691 SILC_SERVER_CMD_FUNC(close)
4693 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4694 SilcServer server = cmd->server;
4695 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4696 SilcServerEntry server_entry;
4697 SilcSocketConnection sock;
4700 unsigned char *name;
4701 SilcUInt32 port = SILC_PORT;
4703 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
4706 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
4708 /* Check whether client has the permissions. */
4709 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
4710 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
4711 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
4712 SILC_STATUS_ERR_NO_SERVER_PRIV,
4717 /* Get the remote server */
4718 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4720 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
4721 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4727 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4729 SILC_GET32_MSB(port, tmp);
4731 server_entry = silc_idlist_find_server_by_conn(server->local_list,
4732 name, port, FALSE, NULL);
4734 server_entry = silc_idlist_find_server_by_conn(server->global_list,
4735 name, port, FALSE, NULL);
4736 if (!server_entry) {
4737 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
4738 SILC_STATUS_ERR_NO_SERVER_ID, 0);
4742 if (server_entry == server->id_entry) {
4743 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
4744 SILC_STATUS_ERR_NO_SERVER_ID, 0);
4748 /* Send reply to the sender */
4749 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
4752 /* Close the connection to the server */
4753 sock = (SilcSocketConnection)server_entry->connection;
4755 server->backup_noswitch = TRUE;
4756 if (server->router == server_entry) {
4757 server->id_entry->router = NULL;
4758 server->router = NULL;
4759 server->standalone = TRUE;
4761 silc_server_disconnect_remote(server, sock,
4762 SILC_STATUS_ERR_BANNED_FROM_SERVER,
4763 "Closed by administrator");
4764 if (sock->user_data)
4765 silc_server_free_sock_user_data(server, sock, NULL);
4766 server->backup_noswitch = FALSE;
4769 silc_server_command_free(cmd);
4772 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4773 active connections. */
4775 SILC_SERVER_CMD_FUNC(shutdown)
4777 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4778 SilcServer server = cmd->server;
4779 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4781 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
4784 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
4786 /* Check whether client has the permission. */
4787 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
4788 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
4789 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
4790 SILC_STATUS_ERR_NO_SERVER_PRIV,
4795 /* Send reply to the sender */
4796 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
4799 /* Then, gracefully, or not, bring the server down. */
4800 silc_server_stop(server);
4804 silc_server_command_free(cmd);