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);
165 /* Update access time */
166 client->last_command = time(NULL);
168 if (!(timeout->cmd->flags & SILC_CF_REG)) {
169 SILC_LOG_DEBUG(("Calling %s command",
170 silc_get_command_name(timeout->cmd->cmd)));
171 timeout->cmd->cb(timeout->ctx, NULL);
172 } else if (silc_server_is_registered(timeout->ctx->server,
175 timeout->cmd->cmd)) {
176 SILC_LOG_DEBUG(("Calling %s command",
177 silc_get_command_name(timeout->cmd->cmd)));
178 timeout->cmd->cb(timeout->ctx, NULL);
180 SILC_LOG_DEBUG(("Client is not registered"));
181 silc_server_command_free(timeout->ctx);
187 /* Processes received command packet. */
189 void silc_server_command_process(SilcServer server,
190 SilcSocketConnection sock,
191 SilcPacketContext *packet)
193 SilcServerCommandContext ctx;
194 SilcServerCommand *cmd;
197 /* Allocate command context. This must be free'd by the
198 command routine receiving it. */
199 ctx = silc_server_command_alloc();
200 ctx->server = server;
201 ctx->sock = silc_socket_dup(sock);
202 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
204 /* Parse the command payload in the packet */
205 ctx->payload = silc_command_payload_parse(packet->buffer->data,
206 packet->buffer->len);
208 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
209 silc_packet_context_free(packet);
210 silc_socket_free(ctx->sock);
214 ctx->args = silc_command_get_args(ctx->payload);
216 /* Get the command */
217 command = silc_command_get(ctx->payload);
218 for (cmd = silc_command_list; cmd->cb; cmd++)
219 if (cmd->cmd == command)
222 if (!cmd || !cmd->cb) {
223 SILC_LOG_DEBUG(("Unknown command %d", command));
224 silc_server_command_send_status_reply(ctx, command,
225 SILC_STATUS_ERR_UNKNOWN_COMMAND, 0);
226 silc_server_command_free(ctx);
230 /* Execute client's commands always with timeout. Normally they are
231 executed with zero (0) timeout but if client is sending command more
232 frequently than once in 2 seconds, then the timeout may be 0 to 2
234 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
235 SilcClientEntry client = (SilcClientEntry)sock->user_data;
236 SilcServerCommandTimeout timeout;
240 SILC_LOG_DEBUG(("Client entry is invalid"));
241 silc_server_command_free(ctx);
244 timeout = silc_calloc(1, sizeof(*timeout));
248 if (client->last_command && (time(NULL) - client->last_command) < 2) {
249 client->fast_command++;
252 if (client->fast_command - 2 <= 0)
253 client->fast_command = 0;
255 client->fast_command -= 2;
259 if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
260 (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
261 silc_schedule_task_add(server->schedule, sock->sock,
262 silc_server_command_process_timeout, timeout,
263 (client->fast_command < 3 ? 0 :
264 2 - (time(NULL) - client->last_command)),
265 (client->fast_command < 3 ? 200000 : 0),
266 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
268 silc_schedule_task_add(server->schedule, sock->sock,
269 silc_server_command_process_timeout, timeout,
270 0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
274 /* Execute for server */
276 if (!(cmd->flags & SILC_CF_REG)) {
277 SILC_LOG_DEBUG(("Calling %s command", silc_get_command_name(cmd->cmd)));
279 } else if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) {
280 SILC_LOG_DEBUG(("Calling %s command", silc_get_command_name(cmd->cmd)));
283 SILC_LOG_DEBUG(("Server is not registered"));
284 silc_server_command_free(ctx);
288 /* Allocate Command Context */
290 SilcServerCommandContext silc_server_command_alloc()
292 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
297 /* Free's the command context allocated before executing the command */
299 void silc_server_command_free(SilcServerCommandContext ctx)
302 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
304 if (ctx->users < 1) {
306 silc_command_payload_free(ctx->payload);
308 silc_packet_context_free(ctx->packet);
310 silc_socket_free(ctx->sock); /* Decrease reference counter */
315 /* Duplicate Command Context by adding reference counter. The context won't
316 be free'd untill it hits zero. */
318 SilcServerCommandContext
319 silc_server_command_dup(SilcServerCommandContext ctx)
322 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
327 /* Timeout for pending command. If reply to pending command never arrives
328 this is called to free resources. */
330 SILC_TASK_CALLBACK(silc_server_command_pending_timeout)
332 SilcServer server = app_context;
333 SilcServerCommandPending *reply = context;
334 SilcServerCommandReplyContext cmdr;
338 SILC_LOG_DEBUG(("Timeout pending command"));
340 /* Allocate temporary and bogus command reply context */
341 cmdr = silc_calloc(1, sizeof(*cmdr));
342 cmdr->server = server;
343 cmdr->ident = reply->ident;
345 /* Check for pending commands and mark to be exeucted */
347 silc_server_command_pending_check(server, reply->reply_cmd,
348 reply->ident, &cmdr->callbacks_count);
350 /* Create bogus command reply with an error inside */
352 silc_command_reply_payload_encode_va(reply->reply_cmd ? reply->reply_cmd :
353 SILC_COMMAND_RESERVED,
354 SILC_STATUS_ERR_TIMEDOUT, 0,
356 cmdr->payload = silc_command_payload_parse(tmpreply->data, tmpreply->len);
357 silc_buffer_free(tmpreply);
359 /* Call all callbacks. Same as SILC_SERVER_PENDING_EXEC macro. */
360 for (i = 0; i < cmdr->callbacks_count; i++)
361 if (cmdr->callbacks[i].callback)
362 (*cmdr->callbacks[i].callback)(cmdr->callbacks[i].context, cmdr);
364 silc_server_command_pending_del(server, reply->reply_cmd, reply->ident);
365 silc_server_command_reply_free(cmdr);
368 /* Add new pending command to be executed when reply to a command has been
369 received. The `reply_cmd' is the command that will call the `callback'
370 with `context' when reply has been received. It can be SILC_COMMAND_NONE
371 to match any command with the `ident'. If `ident' is non-zero
372 the `callback' will be executed when received reply with command
373 identifier `ident'. If there already exists pending command for the
374 specified command, ident, callback and context this function has no
377 bool silc_server_command_pending(SilcServer server,
378 SilcCommand reply_cmd,
380 SilcCommandCb callback,
383 return silc_server_command_pending_timed(server, reply_cmd, ident, callback,
387 /* Same as silc_server_command_pending with specific timeout for pending
388 commands. If the `timeout' is zero default timeout is used. */
390 bool silc_server_command_pending_timed(SilcServer server,
391 SilcCommand reply_cmd,
393 SilcCommandCb callback,
397 SilcServerCommandPending *reply;
399 /* Check whether identical pending already exists for same command,
400 ident, callback and callback context. If it does then it would be
401 error to register it again. */
402 silc_dlist_start(server->pending_commands);
403 while ((reply = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
404 if (reply->reply_cmd == reply_cmd && reply->ident == ident &&
405 reply->callback == callback && reply->context == context)
409 reply = silc_calloc(1, sizeof(*reply));
410 reply->reply_cmd = reply_cmd;
411 reply->ident = ident;
412 reply->context = context;
413 reply->callback = callback;
415 silc_schedule_task_add(server->schedule, 0,
416 silc_server_command_pending_timeout, reply,
417 timeout ? timeout : 10, 0,
418 SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
419 silc_dlist_add(server->pending_commands, reply);
424 /* Deletes pending command by reply command type. */
426 void silc_server_command_pending_del(SilcServer server,
427 SilcCommand reply_cmd,
430 SilcServerCommandPending *r;
432 silc_dlist_start(server->pending_commands);
433 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
434 if ((r->reply_cmd == reply_cmd || (r->reply_cmd == SILC_COMMAND_NONE &&
436 && r->ident == ident) {
437 silc_dlist_del(server->pending_commands, r);
439 silc_schedule_task_del(server->schedule, r->timeout);
445 /* Checks for pending commands and marks callbacks to be called from
446 the command reply function. Returns TRUE if there were pending command. */
448 SilcServerCommandPendingCallbacks
449 silc_server_command_pending_check(SilcServer server,
452 SilcUInt32 *callbacks_count)
454 SilcServerCommandPending *r;
455 SilcServerCommandPendingCallbacks callbacks = NULL;
458 silc_dlist_start(server->pending_commands);
459 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
460 if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE)
461 && r->ident == ident) {
462 callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
463 callbacks[i].context = r->context;
464 callbacks[i].callback = r->callback;
465 r->reply_check = TRUE;
470 *callbacks_count = i;
474 /* Sends simple status message as command reply packet */
477 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
484 SILC_LOG_DEBUG(("Sending command status %d", status));
487 silc_command_reply_payload_encode_va(command, status, error,
488 silc_command_get_ident(cmd->payload),
490 silc_server_packet_send(cmd->server, cmd->sock,
491 SILC_PACKET_COMMAND_REPLY, 0,
492 buffer->data, buffer->len, FALSE);
493 silc_buffer_free(buffer);
496 /* Sends command status reply with one extra argument. The argument
497 type must be sent as argument. */
500 silc_server_command_send_status_data(SilcServerCommandContext cmd,
505 const unsigned char *arg,
510 SILC_LOG_DEBUG(("Sending command status %d", status));
513 silc_command_reply_payload_encode_va(command, status, 0,
514 silc_command_get_ident(cmd->payload),
515 1, arg_type, arg, arg_len);
516 silc_server_packet_send(cmd->server, cmd->sock,
517 SILC_PACKET_COMMAND_REPLY, 0,
518 buffer->data, buffer->len, FALSE);
519 silc_buffer_free(buffer);
522 /* This function can be called to check whether in the command reply
523 an error occurred. This function has no effect if this is called
524 when the command function was not called as pending command callback.
525 This returns TRUE if error had occurred. */
528 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
529 SilcServerCommandReplyContext cmdr,
532 if (!cmd->pending || !cmdr)
535 if (!silc_command_get_status(cmdr->payload, NULL, NULL)) {
538 /* Send the same command reply payload */
539 silc_command_set_command(cmdr->payload, silc_command_get(cmd->payload));
540 silc_command_set_ident(cmdr->payload,
541 silc_command_get_ident(cmd->payload));
542 buffer = silc_command_payload_encode_payload(cmdr->payload);
543 silc_server_packet_send(cmd->server, cmd->sock,
544 SILC_PACKET_COMMAND_REPLY, 0,
545 buffer->data, buffer->len, FALSE);
546 silc_buffer_free(buffer);
553 /* Server side of command WHOIS. */
555 SILC_SERVER_CMD_FUNC(whois)
557 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
558 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 256);
559 silc_server_query_command(cmd->server, SILC_COMMAND_WHOIS, cmd);
560 silc_server_command_free(cmd);
563 /* Server side of command WHOWAS. */
565 SILC_SERVER_CMD_FUNC(whowas)
567 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
568 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
569 silc_server_query_command(cmd->server, SILC_COMMAND_WHOWAS, cmd);
570 silc_server_command_free(cmd);
573 /* Server side of command IDENTIFY. */
575 SILC_SERVER_CMD_FUNC(identify)
577 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
578 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 256);
579 silc_server_query_command(cmd->server, SILC_COMMAND_IDENTIFY, cmd);
580 silc_server_command_free(cmd);
583 /* Server side of command NICK. Sets nickname for user. Setting
584 nickname causes generation of a new client ID for the client. The
585 new client ID is sent to the client after changing the nickname. */
587 SILC_SERVER_CMD_FUNC(nick)
589 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
590 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
591 SilcServer server = cmd->server;
592 SilcBuffer packet, nidp, oidp = NULL;
593 SilcClientID *new_id;
596 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
599 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
602 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
605 nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
608 if (silc_server_name_bad_chars(nick, nick_len) == TRUE) {
609 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
610 SILC_STATUS_ERR_BAD_NICKNAME, 0);
614 /* Check for same nickname */
615 if (!strcmp(client->nickname, nick)) {
616 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
620 /* Create new Client ID */
621 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
623 cmd->server->md5hash, nick,
627 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
628 SILC_STATUS_ERR_BAD_NICKNAME, 0);
631 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
634 /* Send notify about nickname change to our router. We send the new
635 ID and ask to replace it with the old one. If we are router the
636 packet is broadcasted. Send NICK_CHANGE notify. */
637 silc_server_send_notify_nick_change(server, SILC_PRIMARY_ROUTE(server),
638 SILC_BROADCAST(server), client->id,
641 /* Check if anyone is watching the old nickname */
642 if (server->server_type == SILC_ROUTER)
643 silc_server_check_watcher_list(server, client, nick,
644 SILC_NOTIFY_TYPE_NICK_CHANGE);
646 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
648 /* Remove old cache entry */
649 silc_idcache_del_by_context(server->local_list->clients, client);
651 silc_free(client->id);
654 silc_free(client->nickname);
655 client->nickname = strdup(nick);
657 /* Update client cache */
658 silc_idcache_add(server->local_list->clients, client->nickname,
659 client->id, (void *)client, 0, NULL);
661 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
663 /* Send NICK_CHANGE notify to the client's channels */
664 silc_server_send_notify_on_channels(server, NULL, client,
665 SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
666 oidp->data, oidp->len,
667 nidp->data, nidp->len,
669 strlen(client->nickname));
671 /* Check if anyone is watching the new nickname */
672 if (server->server_type == SILC_ROUTER)
673 silc_server_check_watcher_list(server, client, NULL,
674 SILC_NOTIFY_TYPE_NICK_CHANGE);
677 /* Send the new Client ID as reply command back to client */
678 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
679 SILC_STATUS_OK, 0, ident, 2,
680 2, nidp->data, nidp->len,
681 3, nick, strlen(nick));
682 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
683 0, packet->data, packet->len, FALSE);
685 silc_buffer_free(packet);
686 silc_buffer_free(nidp);
688 silc_buffer_free(oidp);
691 silc_server_command_free(cmd);
694 /* Sends the LIST command reply */
697 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
698 SilcChannelEntry *lch,
699 SilcUInt32 lch_count,
700 SilcChannelEntry *gch,
701 SilcUInt32 gch_count)
704 SilcBuffer packet, idp;
705 SilcChannelEntry entry;
707 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
709 unsigned char usercount[4];
711 int valid_lcount = 0, valid_rcount = 0;
713 for (i = 0; i < lch_count; i++) {
714 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
719 for (i = 0; i < gch_count; i++) {
720 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
726 status = SILC_STATUS_OK;
727 if ((lch_count + gch_count) > 1)
728 status = SILC_STATUS_LIST_START;
731 for (i = 0, k = 0; i < lch_count; i++) {
737 status = SILC_STATUS_LIST_ITEM;
738 if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
739 status = SILC_STATUS_LIST_END;
741 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
743 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
745 memset(usercount, 0, sizeof(usercount));
747 topic = entry->topic;
748 users = silc_hash_table_count(entry->user_list);
749 SILC_PUT32_MSB(users, usercount);
754 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
756 2, idp->data, idp->len,
757 3, entry->channel_name,
758 strlen(entry->channel_name),
759 4, topic, topic ? strlen(topic) : 0,
761 silc_server_packet_send(cmd->server, cmd->sock,
762 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
764 silc_buffer_free(packet);
765 silc_buffer_free(idp);
770 for (i = 0, k = 0; i < gch_count; i++) {
776 status = SILC_STATUS_LIST_ITEM;
777 if (valid_rcount > 1 && k == valid_rcount - 1)
778 status = SILC_STATUS_LIST_END;
780 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
782 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
784 memset(usercount, 0, sizeof(usercount));
786 topic = entry->topic;
787 users = entry->user_count;
788 SILC_PUT32_MSB(users, usercount);
793 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
795 2, idp->data, idp->len,
796 3, entry->channel_name,
797 strlen(entry->channel_name),
798 4, topic, topic ? strlen(topic) : 0,
800 silc_server_packet_send(cmd->server, cmd->sock,
801 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
803 silc_buffer_free(packet);
804 silc_buffer_free(idp);
809 /* Server side of LIST command. This lists the channel of the requested
810 server. Secret channels are not listed. */
812 SILC_SERVER_CMD_FUNC(list)
814 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
815 SilcServer server = cmd->server;
816 SilcChannelID *channel_id = NULL;
819 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
820 SilcUInt32 lch_count = 0, gch_count = 0;
822 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
824 /* If we are normal server, send the command to router, since we
825 want to know all channels in the network. */
826 if (!cmd->pending && server->server_type != SILC_ROUTER &&
827 !server->standalone) {
829 SilcUInt16 old_ident;
831 old_ident = silc_command_get_ident(cmd->payload);
832 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
833 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
834 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
835 SILC_PACKET_COMMAND, cmd->packet->flags,
836 tmpbuf->data, tmpbuf->len, TRUE);
838 /* Reprocess this packet after received reply from router */
839 silc_server_command_pending(server, SILC_COMMAND_LIST,
840 silc_command_get_ident(cmd->payload),
841 silc_server_command_list,
842 silc_server_command_dup(cmd));
844 silc_command_set_ident(cmd->payload, old_ident);
845 silc_buffer_free(tmpbuf);
850 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
852 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
854 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
855 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
860 /* Get the channels from local list */
861 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
864 /* Get the channels from global list */
865 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
869 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
870 gchannels, gch_count);
872 silc_free(lchannels);
873 silc_free(gchannels);
876 silc_server_command_free(cmd);
879 /* Server side of TOPIC command. Sets topic for channel and/or returns
880 current topic to client. */
882 SILC_SERVER_CMD_FUNC(topic)
884 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
885 SilcServer server = cmd->server;
886 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
887 SilcChannelID *channel_id;
888 SilcChannelEntry channel;
889 SilcChannelClientEntry chl;
890 SilcBuffer packet, idp;
892 SilcUInt32 argc, tmp_len;
893 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
895 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
898 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
900 argc = silc_argument_get_arg_num(cmd->args);
903 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
905 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
906 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
909 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
911 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
912 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
916 /* Check whether the channel exists */
917 channel = silc_idlist_find_channel_by_id(server->local_list,
920 channel = silc_idlist_find_channel_by_id(server->global_list,
923 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
924 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
932 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
934 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
935 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
940 if (strlen(tmp) > 256) {
941 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
942 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
947 /* See whether the client is on channel and has rights to change topic */
948 if (!silc_server_client_on_channel(client, channel, &chl)) {
949 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
950 SILC_STATUS_ERR_NOT_ON_CHANNEL,
955 if (channel->mode & SILC_CHANNEL_MODE_TOPIC &&
956 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
957 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
958 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
959 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
964 if (!channel->topic || strcmp(channel->topic, tmp)) {
965 /* Set the topic for channel */
966 silc_free(channel->topic);
967 channel->topic = strdup(tmp);
969 /* Send TOPIC_SET notify type to the network */
970 silc_server_send_notify_topic_set(server, SILC_PRIMARY_ROUTE(server),
971 SILC_BROADCAST(server), channel,
972 client->id, SILC_ID_CLIENT,
975 /* Send notify about topic change to all clients on the channel */
976 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
977 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
978 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
981 strlen(channel->topic));
982 silc_buffer_free(idp);
986 /* Send the topic to client as reply packet */
987 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
988 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
989 SILC_STATUS_OK, 0, ident, 2,
990 2, idp->data, idp->len,
993 strlen(channel->topic) : 0);
994 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
995 0, packet->data, packet->len, FALSE);
997 silc_buffer_free(packet);
998 silc_buffer_free(idp);
999 silc_free(channel_id);
1002 silc_server_command_free(cmd);
1005 /* Server side of INVITE command. Invites some client to join some channel.
1006 This command is also used to manage the invite list of the channel. */
1008 SILC_SERVER_CMD_FUNC(invite)
1010 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1011 SilcServer server = cmd->server;
1012 SilcSocketConnection sock = cmd->sock, dest_sock;
1013 SilcChannelClientEntry chl;
1014 SilcClientEntry sender, dest;
1015 SilcClientID *dest_id = NULL;
1016 SilcChannelEntry channel;
1017 SilcChannelID *channel_id = NULL;
1018 SilcIDListData idata;
1019 SilcBuffer idp, idp2, packet;
1020 unsigned char *tmp, *add, *del;
1022 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1024 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
1026 /* Get Channel ID */
1027 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1029 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1030 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
1033 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
1035 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1036 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
1040 /* Get the channel entry */
1041 channel = silc_idlist_find_channel_by_id(server->local_list,
1044 channel = silc_idlist_find_channel_by_id(server->global_list,
1047 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1048 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1054 /* Check whether the sender of this command is on the channel. */
1055 sender = (SilcClientEntry)sock->user_data;
1056 if (!sender || !silc_server_client_on_channel(sender, channel, &chl)) {
1057 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1058 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
1062 /* Check whether the channel is invite-only channel. If yes then the
1063 sender of this command must be at least channel operator. */
1064 if (channel->mode & SILC_CHANNEL_MODE_INVITE &&
1065 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
1066 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
1067 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1068 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
1073 /* Get destination client ID */
1074 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1079 dest_id = silc_id_payload_parse_id(tmp, len, NULL);
1081 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1082 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
1086 /* Get the client entry */
1087 dest = silc_server_query_client(server, dest_id, FALSE, &resolve);
1089 if (server->server_type != SILC_SERVER || !resolve) {
1090 silc_server_command_send_status_reply(
1091 cmd, SILC_COMMAND_INVITE,
1092 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0);
1096 /* The client info is being resolved. Reprocess this packet after
1097 receiving the reply to the query. */
1098 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1100 silc_server_command_invite,
1101 silc_server_command_dup(cmd));
1102 cmd->pending = TRUE;
1103 silc_free(channel_id);
1108 /* Check whether the requested client is already on the channel. */
1109 if (silc_server_client_on_channel(dest, channel, NULL)) {
1110 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1111 SILC_STATUS_ERR_USER_ON_CHANNEL,
1116 /* Get route to the client */
1117 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id,
1120 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1121 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1126 memset(invite, 0, sizeof(invite));
1127 silc_strncat(invite, sizeof(invite),
1128 dest->nickname, strlen(dest->nickname));
1129 silc_strncat(invite, sizeof(invite), "!", 1);
1130 silc_strncat(invite, sizeof(invite),
1131 dest->username, strlen(dest->username));
1132 if (!strchr(dest->username, '@')) {
1133 silc_strncat(invite, sizeof(invite), "@", 1);
1134 silc_strncat(invite, sizeof(invite), cmd->sock->hostname,
1135 strlen(cmd->sock->hostname));
1138 len = strlen(invite);
1139 if (!channel->invite_list)
1140 channel->invite_list = silc_calloc(len + 2,
1141 sizeof(*channel->invite_list));
1143 channel->invite_list = silc_realloc(channel->invite_list,
1144 sizeof(*channel->invite_list) *
1146 strlen(channel->invite_list) + 2));
1147 strncat(channel->invite_list, invite, len);
1148 strncat(channel->invite_list, ",", 1);
1150 if (!(dest->mode & SILC_UMODE_BLOCK_INVITE)) {
1151 /* Send notify to the client that is invited to the channel */
1152 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1153 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1154 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
1156 SILC_NOTIFY_TYPE_INVITE, 3,
1157 idp->data, idp->len,
1158 channel->channel_name,
1159 strlen(channel->channel_name),
1160 idp2->data, idp2->len);
1161 silc_buffer_free(idp);
1162 silc_buffer_free(idp2);
1166 /* Add the client to the invite list of the channel */
1167 add = silc_argument_get_arg_type(cmd->args, 3, &len);
1169 if (!channel->invite_list)
1170 channel->invite_list = silc_calloc(len + 2,
1171 sizeof(*channel->invite_list));
1173 channel->invite_list = silc_realloc(channel->invite_list,
1174 sizeof(*channel->invite_list) *
1176 strlen(channel->invite_list) + 2));
1177 if (add[len - 1] == ',')
1178 add[len - 1] = '\0';
1180 strncat(channel->invite_list, add, len);
1181 strncat(channel->invite_list, ",", 1);
1184 /* Get the invite to be removed and remove it from the list */
1185 del = silc_argument_get_arg_type(cmd->args, 4, &len);
1186 if (del && channel->invite_list) {
1187 char *start, *end, *n;
1189 if (!strncmp(channel->invite_list, del,
1190 strlen(channel->invite_list) - 1)) {
1191 silc_free(channel->invite_list);
1192 channel->invite_list = NULL;
1194 start = strstr(channel->invite_list, del);
1195 if (start && strlen(start) >= len) {
1197 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
1198 strncat(n, channel->invite_list, start - channel->invite_list);
1199 strncat(n, end + 1, ((channel->invite_list +
1200 strlen(channel->invite_list)) - end) - 1);
1201 silc_free(channel->invite_list);
1202 channel->invite_list = n;
1207 /* Send notify to the primary router */
1208 silc_server_send_notify_invite(server, SILC_PRIMARY_ROUTE(server),
1209 SILC_BROADCAST(server), channel,
1210 sender->id, add, del);
1212 /* Send command reply */
1213 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1217 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
1218 SILC_STATUS_OK, 0, ident, 2,
1220 3, channel->invite_list,
1221 channel->invite_list ?
1222 strlen(channel->invite_list) : 0);
1225 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
1226 SILC_STATUS_OK, 0, ident, 1,
1228 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1229 packet->data, packet->len, FALSE);
1230 silc_buffer_free(packet);
1234 silc_free(channel_id);
1235 silc_server_command_free(cmd);
1239 SilcSocketConnection sock;
1243 /* Quits connection to client. This gets called if client won't
1244 close the connection even when it has issued QUIT command. */
1246 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
1248 SilcServer server = app_context;
1249 QuitInternal q = (QuitInternal)context;
1251 /* Free all client specific data, such as client entry and entires
1252 on channels this client may be on. */
1253 silc_server_free_client_data(server, q->sock, q->sock->user_data,
1255 q->sock->user_data = NULL;
1257 /* Close the connection on our side */
1258 silc_server_close_connection(server, q->sock);
1260 silc_socket_free(q->sock);
1261 silc_free(q->signoff);
1265 /* Quits SILC session. This is the normal way to disconnect client. */
1267 SILC_SERVER_CMD_FUNC(quit)
1269 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1270 SilcServer server = cmd->server;
1271 SilcSocketConnection sock = cmd->sock;
1273 unsigned char *tmp = NULL;
1276 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
1278 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1282 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1286 q = silc_calloc(1, sizeof(*q));
1287 q->sock = silc_socket_dup(sock);
1288 q->signoff = tmp ? strdup(tmp) : NULL;
1290 /* We quit the connection with little timeout */
1291 silc_schedule_task_add(server->schedule, sock->sock,
1292 silc_server_command_quit_cb, (void *)q,
1293 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1296 silc_server_command_free(cmd);
1299 /* Server side of command KILL. This command is used by router operator
1300 to remove an client from the SILC Network temporarily. */
1302 SILC_SERVER_CMD_FUNC(kill)
1304 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1305 SilcServer server = cmd->server;
1306 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1307 SilcClientEntry remote_client;
1308 SilcClientID *client_id;
1309 unsigned char *tmp, *comment;
1310 SilcUInt32 tmp_len, tmp_len2;
1313 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
1315 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
1318 /* KILL command works only on router */
1319 if (server->server_type != SILC_ROUTER) {
1320 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1321 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
1325 /* Check whether client has the permissions. */
1326 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
1327 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1328 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
1332 /* Get the client ID */
1333 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1335 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1336 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1340 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1342 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1343 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1348 /* Get the client entry */
1349 remote_client = silc_idlist_find_client_by_id(server->local_list,
1350 client_id, TRUE, NULL);
1352 if (!remote_client) {
1353 remote_client = silc_idlist_find_client_by_id(server->global_list,
1354 client_id, TRUE, NULL);
1356 if (!remote_client) {
1357 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1358 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1365 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
1369 /* Send reply to the sender */
1370 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1373 /* Check if anyone is watching this nickname */
1374 if (server->server_type == SILC_ROUTER)
1375 silc_server_check_watcher_list(server, client, NULL,
1376 SILC_NOTIFY_TYPE_KILLED);
1378 /* Now do the killing */
1379 silc_server_kill_client(server, remote_client, comment, client->id,
1383 silc_server_command_free(cmd);
1386 /* Server side of command INFO. This sends information about us to
1387 the client. If client requested specific server we will send the
1388 command to that server. */
1390 SILC_SERVER_CMD_FUNC(info)
1392 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1393 SilcServer server = cmd->server;
1394 SilcBuffer packet, idp;
1397 char *dest_server, *server_info = NULL, *server_name;
1398 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1399 SilcServerEntry entry = NULL;
1400 SilcServerID *server_id = NULL;
1402 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
1404 /* Get server name */
1405 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1408 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1410 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1412 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1413 SILC_STATUS_ERR_NO_SERVER_ID, 0);
1419 /* Check whether we have this server cached */
1420 entry = silc_idlist_find_server_by_id(server->local_list,
1421 server_id, TRUE, NULL);
1423 entry = silc_idlist_find_server_by_id(server->global_list,
1424 server_id, TRUE, NULL);
1425 if (!entry && server->server_type != SILC_SERVER) {
1426 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1427 SILC_STATUS_ERR_NO_SUCH_SERVER,
1434 /* Some buggy servers has sent request to router about themselves. */
1435 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
1438 if ((!dest_server && !server_id && !entry) || (entry &&
1439 entry == server->id_entry) ||
1440 (dest_server && !cmd->pending &&
1441 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
1442 /* Send our reply */
1443 char info_string[256];
1445 memset(info_string, 0, sizeof(info_string));
1446 snprintf(info_string, sizeof(info_string),
1447 "location: %s server: %s admin: %s <%s>",
1448 server->config->server_info->location,
1449 server->config->server_info->server_type,
1450 server->config->server_info->admin,
1451 server->config->server_info->email);
1453 server_info = info_string;
1454 entry = server->id_entry;
1456 /* Check whether we have this server cached */
1457 if (!entry && dest_server) {
1458 entry = silc_idlist_find_server_by_name(server->global_list,
1459 dest_server, TRUE, NULL);
1461 entry = silc_idlist_find_server_by_name(server->local_list,
1462 dest_server, TRUE, NULL);
1466 if (!cmd->pending &&
1467 server->server_type != SILC_SERVER && entry && !entry->server_info) {
1468 /* Send to the server */
1470 SilcUInt16 old_ident;
1472 old_ident = silc_command_get_ident(cmd->payload);
1473 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1474 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1476 silc_server_packet_send(server, entry->connection,
1477 SILC_PACKET_COMMAND, cmd->packet->flags,
1478 tmpbuf->data, tmpbuf->len, TRUE);
1480 /* Reprocess this packet after received reply from router */
1481 silc_server_command_pending(server, SILC_COMMAND_INFO,
1482 silc_command_get_ident(cmd->payload),
1483 silc_server_command_info,
1484 silc_server_command_dup(cmd));
1485 cmd->pending = TRUE;
1486 silc_command_set_ident(cmd->payload, old_ident);
1487 silc_buffer_free(tmpbuf);
1491 if (!entry && !cmd->pending && !server->standalone) {
1492 /* Send to the primary router */
1494 SilcUInt16 old_ident;
1496 old_ident = silc_command_get_ident(cmd->payload);
1497 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1498 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1500 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
1501 SILC_PACKET_COMMAND, cmd->packet->flags,
1502 tmpbuf->data, tmpbuf->len, TRUE);
1504 /* Reprocess this packet after received reply from router */
1505 silc_server_command_pending(server, SILC_COMMAND_INFO,
1506 silc_command_get_ident(cmd->payload),
1507 silc_server_command_info,
1508 silc_server_command_dup(cmd));
1509 cmd->pending = TRUE;
1510 silc_command_set_ident(cmd->payload, old_ident);
1511 silc_buffer_free(tmpbuf);
1516 silc_free(server_id);
1519 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1520 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
1524 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1526 server_info = entry->server_info;
1527 server_name = entry->server_name;
1529 /* Send the reply */
1530 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
1531 SILC_STATUS_OK, 0, ident, 3,
1532 2, idp->data, idp->len,
1534 strlen(server_name),
1537 strlen(server_info) : 0);
1538 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1539 packet->data, packet->len, FALSE);
1541 silc_buffer_free(packet);
1542 silc_buffer_free(idp);
1545 silc_server_command_free(cmd);
1548 /* Server side of command PING. This just replies to the ping. */
1550 SILC_SERVER_CMD_FUNC(ping)
1552 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1553 SilcServer server = cmd->server;
1558 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
1561 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1563 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1564 SILC_STATUS_ERR_NO_SERVER_ID, 0);
1567 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
1571 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
1572 /* Send our reply */
1573 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1576 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1577 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
1584 silc_server_command_free(cmd);
1587 /* Server side of command STATS. */
1589 SILC_SERVER_CMD_FUNC(stats)
1591 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1592 SilcServer server = cmd->server;
1593 SilcServerID *server_id;
1596 SilcBuffer packet, stats;
1597 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1600 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1);
1603 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1605 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1606 SILC_STATUS_ERR_NO_SERVER_ID, 0);
1609 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1613 /* The ID must be ours */
1614 if (!SILC_ID_SERVER_COMPARE(server->id, server_id)) {
1615 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1616 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
1617 silc_free(server_id);
1620 silc_free(server_id);
1622 /* If we are router then just send everything we got. If we are normal
1623 server then we'll send this to our router to get all the latest
1624 statistical information. */
1625 if (!cmd->pending && server->server_type != SILC_ROUTER &&
1626 !server->standalone) {
1627 /* Send request to our router */
1628 SilcBuffer idp = silc_id_payload_encode(server->router->id,
1630 packet = silc_command_payload_encode_va(SILC_COMMAND_STATS,
1631 ++server->cmd_ident, 1,
1632 1, idp->data, idp->len);
1633 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
1634 SILC_PACKET_COMMAND, 0, packet->data,
1635 packet->len, FALSE);
1637 /* Reprocess this packet after received reply from router */
1638 silc_server_command_pending(server, SILC_COMMAND_STATS,
1640 silc_server_command_stats,
1641 silc_server_command_dup(cmd));
1642 cmd->pending = TRUE;
1643 silc_buffer_free(packet);
1644 silc_buffer_free(idp);
1648 /* Send our reply to sender */
1649 uptime = time(NULL) - server->starttime;
1651 stats = silc_buffer_alloc_size(60);
1652 silc_buffer_format(stats,
1653 SILC_STR_UI_INT(server->starttime),
1654 SILC_STR_UI_INT(uptime),
1655 SILC_STR_UI_INT(server->stat.my_clients),
1656 SILC_STR_UI_INT(server->stat.my_channels),
1657 SILC_STR_UI_INT(server->stat.my_server_ops),
1658 SILC_STR_UI_INT(server->stat.my_router_ops),
1659 SILC_STR_UI_INT(server->stat.cell_clients),
1660 SILC_STR_UI_INT(server->stat.cell_channels),
1661 SILC_STR_UI_INT(server->stat.cell_servers),
1662 SILC_STR_UI_INT(server->stat.clients),
1663 SILC_STR_UI_INT(server->stat.channels),
1664 SILC_STR_UI_INT(server->stat.servers),
1665 SILC_STR_UI_INT(server->stat.routers),
1666 SILC_STR_UI_INT(server->stat.server_ops),
1667 SILC_STR_UI_INT(server->stat.router_ops),
1670 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_STATS,
1671 SILC_STATUS_OK, 0, ident, 2,
1673 3, stats->data, stats->len);
1674 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1675 0, packet->data, packet->len, FALSE);
1676 silc_buffer_free(packet);
1677 silc_buffer_free(stats);
1680 silc_server_command_free(cmd);
1683 /* Internal routine to join channel. The channel sent to this function
1684 has been either created or resolved from ID lists. This joins the sent
1685 client to the channel. */
1687 static void silc_server_command_join_channel(SilcServer server,
1688 SilcServerCommandContext cmd,
1689 SilcChannelEntry channel,
1690 SilcClientID *client_id,
1694 const unsigned char *auth,
1695 SilcUInt32 auth_len)
1697 SilcSocketConnection sock = cmd->sock;
1699 SilcUInt32 tmp_len, user_count;
1700 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
1701 SilcClientEntry client;
1702 SilcChannelClientEntry chl;
1703 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
1704 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1705 char check[512], check2[512];
1706 bool founder = FALSE;
1708 unsigned char *fkey = NULL;
1709 SilcUInt32 fkey_len = 0;
1712 SILC_LOG_DEBUG(("Joining client to channel"));
1717 /* Get the client entry */
1718 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1719 client = (SilcClientEntry)sock->user_data;
1723 client = silc_server_query_client(server, client_id, FALSE,
1730 silc_server_command_send_status_reply(
1731 cmd, SILC_COMMAND_JOIN,
1732 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
1736 /* The client info is being resolved. Reprocess this packet after
1737 receiving the reply to the query. */
1738 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1740 silc_server_command_join,
1741 silc_server_command_dup(cmd));
1742 cmd->pending = TRUE;
1746 cmd->pending = FALSE;
1750 * Check founder auth payload if provided. If client can gain founder
1751 * privileges it can override various conditions on joining the channel,
1752 * and can have directly the founder mode set on the channel.
1754 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1755 SilcIDListData idata = (SilcIDListData)client;
1756 SilcChannelClientEntry chl2;
1757 SilcHashTableList htl;
1759 if (channel->founder_key && idata->public_key &&
1760 silc_pkcs_public_key_compare(channel->founder_key,
1761 idata->public_key)) {
1762 /* Check whether the client is to become founder */
1763 if (silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
1764 channel->founder_key, 0, server->sha1hash,
1765 client->id, SILC_ID_CLIENT)) {
1767 /* There cannot be anyone else as founder on the channel now. This
1768 client is definitely the founder due to this authentication */
1769 silc_hash_table_list(channel->user_list, &htl);
1770 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
1771 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
1772 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
1773 silc_server_force_cumode_change(server, NULL, channel, chl2,
1777 silc_hash_table_list_reset(&htl);
1779 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
1786 * Check channel modes
1790 memset(check, 0, sizeof(check));
1791 memset(check2, 0, sizeof(check2));
1792 silc_strncat(check, sizeof(check),
1793 client->nickname, strlen(client->nickname));
1794 silc_strncat(check, sizeof(check), "!", 1);
1795 silc_strncat(check, sizeof(check),
1796 client->username, strlen(client->username));
1797 if (!strchr(client->username, '@')) {
1798 silc_strncat(check, sizeof(check), "@", 1);
1799 silc_strncat(check, sizeof(check),
1800 cmd->sock->hostname, strlen(cmd->sock->hostname));
1803 silc_strncat(check2, sizeof(check2),
1804 client->nickname, strlen(client->nickname));
1805 if (!strchr(client->nickname, '@')) {
1806 silc_strncat(check2, sizeof(check2), "@", 1);
1807 silc_strncat(check2, sizeof(check2),
1808 server->server_name, strlen(server->server_name));
1810 silc_strncat(check2, sizeof(check2), "!", 1);
1811 silc_strncat(check2, sizeof(check2),
1812 client->username, strlen(client->username));
1813 if (!strchr(client->username, '@')) {
1814 silc_strncat(check2, sizeof(check2), "@", 1);
1815 silc_strncat(check2, sizeof(check2),
1816 cmd->sock->hostname, strlen(cmd->sock->hostname));
1819 /* Check invite list if channel is invite-only channel */
1820 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1821 if (!channel->invite_list ||
1822 (!silc_string_match(channel->invite_list, check) &&
1823 !silc_string_match(channel->invite_list, check2))) {
1824 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1825 SILC_STATUS_ERR_NOT_INVITED, 0);
1830 /* Check ban list if it exists. If the client's nickname, server,
1831 username and/or hostname is in the ban list the access to the
1832 channel is denied. */
1833 if (channel->ban_list) {
1834 if (silc_string_match(channel->ban_list, check) ||
1835 silc_string_match(channel->ban_list, check2)) {
1836 silc_server_command_send_status_reply(
1837 cmd, SILC_COMMAND_JOIN,
1838 SILC_STATUS_ERR_BANNED_FROM_CHANNEL, 0);
1843 /* Check user count limit if set. */
1844 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
1845 if (silc_hash_table_count(channel->user_list) + 1 >
1846 channel->user_limit) {
1847 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1848 SILC_STATUS_ERR_CHANNEL_IS_FULL,
1855 /* Check the channel passphrase if set. */
1856 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1857 /* Get passphrase */
1858 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1860 passphrase = silc_memdup(tmp, tmp_len);
1862 if (!passphrase || !channel->passphrase ||
1863 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
1864 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1865 SILC_STATUS_ERR_BAD_PASSWORD, 0);
1871 * Client is allowed to join to the channel. Make it happen.
1874 /* Check whether the client already is on the channel */
1875 if (silc_server_client_on_channel(client, channel, NULL)) {
1876 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1877 SILC_STATUS_ERR_USER_ON_CHANNEL, 0);
1881 /* Generate new channel key as protocol dictates */
1883 if (!silc_server_create_channel_key(server, channel, 0))
1886 /* Send the channel key. This is broadcasted to the channel but is not
1887 sent to the client who is joining to the channel. */
1888 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
1889 silc_server_send_channel_key(server, NULL, channel,
1890 server->server_type == SILC_ROUTER ?
1891 FALSE : !server->standalone);
1894 /* Join the client to the channel by adding it to channel's user list.
1895 Add also the channel to client entry's channels list for fast cross-
1897 chl = silc_calloc(1, sizeof(*chl));
1899 chl->client = client;
1900 chl->channel = channel;
1901 silc_hash_table_add(channel->user_list, client, chl);
1902 silc_hash_table_add(client->channels, channel, chl);
1903 channel->user_count++;
1904 channel->disabled = FALSE;
1906 /* Get users on the channel */
1907 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
1910 /* Encode Client ID Payload of the original client who wants to join */
1911 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1913 /* Encode command reply packet */
1914 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1915 SILC_PUT32_MSB(channel->mode, mode);
1916 SILC_PUT32_MSB(created, tmp2);
1917 SILC_PUT32_MSB(user_count, tmp3);
1919 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
1920 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1921 cipher = silc_cipher_get_name(channel->channel_key);
1922 keyp = silc_channel_key_payload_encode(silc_id_get_len(channel->id,
1925 strlen(cipher), cipher,
1926 channel->key_len / 8, channel->key);
1930 if (channel->founder_key)
1931 fkey = silc_pkcs_public_key_encode(channel->founder_key, &fkey_len);
1934 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1935 SILC_STATUS_OK, 0, ident, 14,
1936 2, channel->channel_name,
1937 strlen(channel->channel_name),
1938 3, chidp->data, chidp->len,
1939 4, clidp->data, clidp->len,
1942 7, keyp ? keyp->data : NULL,
1943 keyp ? keyp->len : 0,
1944 8, channel->ban_list,
1946 strlen(channel->ban_list) : 0,
1947 9, channel->invite_list,
1948 channel->invite_list ?
1949 strlen(channel->invite_list) : 0,
1952 strlen(channel->topic) : 0,
1953 11, silc_hmac_get_name(channel->hmac),
1954 strlen(silc_hmac_get_name(channel->
1957 13, user_list->data, user_list->len,
1958 14, mode_list->data,
1960 15, fkey, fkey_len);
1962 /* Send command reply */
1963 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
1964 reply->data, reply->len, FALSE);
1966 /* Send JOIN notify to locally connected clients on the channel. If
1967 we are normal server then router will send or have sent JOIN notify
1968 already. However since we've added the client already to our channel
1969 we'll ignore it (in packet_receive.c) so we must send it here. If
1970 we are router then this will send it to local clients and local
1972 SILC_LOG_DEBUG(("Send JOIN notify to channel"));
1973 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
1974 SILC_NOTIFY_TYPE_JOIN, 2,
1975 clidp->data, clidp->len,
1976 chidp->data, chidp->len);
1978 /* Update statistics */
1979 server->stat.my_chanclients++;
1980 if (server->server_type == SILC_ROUTER) {
1981 server->stat.cell_chanclients++;
1982 server->stat.chanclients++;
1985 if (!cmd->pending) {
1986 /* Send JOIN notify packet to our primary router */
1987 silc_server_send_notify_join(server, SILC_PRIMARY_ROUTE(server),
1988 SILC_BROADCAST(server), channel, client->id);
1991 /* Distribute the channel key to all backup routers. */
1992 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
1993 keyp->data, keyp->len, FALSE, TRUE);
1995 /* If client became founder by providing correct founder auth data
1996 notify the mode change to the channel. */
1998 SILC_PUT32_MSB(chl->mode, mode);
1999 SILC_LOG_DEBUG(("Send CUMODE_CHANGE notify to channel"));
2000 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2001 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
2002 clidp->data, clidp->len,
2003 mode, 4, clidp->data, clidp->len,
2008 /* Set CUMODE notify type to network */
2010 silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
2011 SILC_BROADCAST(server), channel,
2012 chl->mode, client->id, SILC_ID_CLIENT,
2013 client->id, channel->founder_key);
2015 silc_buffer_free(reply);
2016 silc_buffer_free(clidp);
2017 silc_buffer_free(chidp);
2018 silc_buffer_free(keyp);
2019 silc_buffer_free(user_list);
2020 silc_buffer_free(mode_list);
2024 silc_free(passphrase);
2027 /* Server side of command JOIN. Joins client into requested channel. If
2028 the channel does not exist it will be created. */
2030 SILC_SERVER_CMD_FUNC(join)
2032 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2033 SilcServer server = cmd->server;
2034 unsigned char *auth;
2035 SilcUInt32 tmp_len, auth_len;
2036 char *tmp, *channel_name = NULL, *cipher, *hmac;
2037 SilcChannelEntry channel;
2038 SilcUInt32 umode = 0;
2039 bool created = FALSE, create_key = TRUE;
2040 SilcClientID *client_id;
2042 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
2044 /* Get channel name */
2045 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2047 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2048 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2055 channel_name[255] = '\0';
2057 if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
2058 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2059 SILC_STATUS_ERR_BAD_CHANNEL, 0);
2063 /* Get Client ID of the client who is joining to the channel */
2064 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2066 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2067 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2071 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2073 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2074 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2079 /* Get cipher, hmac name and auth payload */
2080 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2081 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2082 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
2084 /* See if the channel exists */
2085 channel = silc_idlist_find_channel_by_name(server->local_list,
2086 channel_name, NULL);
2088 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2089 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2091 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2092 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2097 silc_free(client_id);
2098 client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
2101 (channel->disabled && server->server_type != SILC_ROUTER)) {
2102 /* Channel not found or not valid */
2104 /* If we are standalone server we don't have a router, we just create
2105 the channel by ourselves (unless it existed). */
2106 if (server->standalone) {
2108 channel = silc_server_create_new_channel(server, server->id, cipher,
2109 hmac, channel_name, TRUE);
2111 silc_server_command_send_status_reply(
2112 cmd, SILC_COMMAND_JOIN,
2113 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
2115 silc_free(client_id);
2119 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2125 /* The channel does not exist on our server. If we are normal server
2126 we will send JOIN command to our router which will handle the
2127 joining procedure (either creates the channel if it doesn't exist
2128 or joins the client to it). */
2129 if (server->server_type != SILC_ROUTER) {
2131 SilcUInt16 old_ident;
2133 /* If this is pending command callback then we've resolved
2134 it and it didn't work, return since we've notified the
2135 client already in the command reply callback. */
2137 silc_free(client_id);
2141 old_ident = silc_command_get_ident(cmd->payload);
2142 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2143 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2145 /* Send JOIN command to our router */
2146 silc_server_packet_send(server, (SilcSocketConnection)
2147 SILC_PRIMARY_ROUTE(server),
2148 SILC_PACKET_COMMAND, cmd->packet->flags,
2149 tmpbuf->data, tmpbuf->len, TRUE);
2151 /* Reprocess this packet after received reply from router */
2152 silc_server_command_pending(server, SILC_COMMAND_JOIN,
2153 silc_command_get_ident(cmd->payload),
2154 silc_server_command_join,
2155 silc_server_command_dup(cmd));
2156 cmd->pending = TRUE;
2157 silc_command_set_ident(cmd->payload, old_ident);
2158 silc_buffer_free(tmpbuf);
2159 silc_free(client_id);
2163 /* We are router and the channel does not seem exist so we will check
2164 our global list as well for the channel. */
2165 channel = silc_idlist_find_channel_by_name(server->global_list,
2166 channel_name, NULL);
2168 /* Channel really does not exist, create it */
2169 channel = silc_server_create_new_channel(server, server->id, cipher,
2170 hmac, channel_name, TRUE);
2172 silc_server_command_send_status_reply(
2173 cmd, SILC_COMMAND_JOIN,
2174 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
2175 silc_free(client_id);
2179 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2187 /* Channel not found */
2189 /* If the command came from router and we are normal server then
2190 something went wrong with the joining as the channel was not found.
2191 We can't do anything else but ignore this. */
2192 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
2193 server->server_type != SILC_ROUTER) {
2194 silc_free(client_id);
2198 /* We are router and the channel does not seem exist so we will check
2199 our global list as well for the channel. */
2200 channel = silc_idlist_find_channel_by_name(server->global_list,
2201 channel_name, NULL);
2203 /* Channel really does not exist, create it */
2204 channel = silc_server_create_new_channel(server, server->id, cipher,
2205 hmac, channel_name, TRUE);
2207 silc_server_command_send_status_reply(
2208 cmd, SILC_COMMAND_JOIN,
2209 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
2210 silc_free(client_id);
2214 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2221 /* Check whether the channel was created by our router */
2222 if (cmd->pending && context2) {
2223 SilcServerCommandReplyContext reply = context2;
2225 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
2226 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
2227 SILC_GET32_MSB(created, tmp);
2228 if (silc_argument_get_arg_type(reply->args, 7, NULL))
2229 create_key = FALSE; /* Router returned the key already */
2231 if (silc_command_get_status(reply->payload, NULL, NULL) &&
2232 channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2233 /* Save channel passphrase, if user provided it successfully */
2236 pa = silc_argument_get_arg_type(cmd->args, 3, &pa_len);
2238 silc_free(channel->passphrase);
2239 channel->passphrase = silc_memdup(pa, pa_len);
2244 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
2245 !channel->disabled && !silc_hash_table_count(channel->user_list))
2249 /* If the channel does not have global users and is also empty the client
2250 will be the channel founder and operator. */
2251 if (!channel->disabled &&
2252 !channel->global_users && !silc_hash_table_count(channel->user_list))
2253 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2255 /* Join to the channel */
2256 silc_server_command_join_channel(server, cmd, channel, client_id,
2257 created, create_key, umode,
2260 silc_free(client_id);
2263 silc_server_command_free(cmd);
2266 /* Server side of command MOTD. Sends server's current "message of the
2267 day" to the client. */
2269 SILC_SERVER_CMD_FUNC(motd)
2271 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2272 SilcServer server = cmd->server;
2273 SilcBuffer packet, idp;
2274 char *motd, *dest_server;
2275 SilcUInt32 motd_len;
2276 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2278 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
2280 /* Get server name */
2281 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2283 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2284 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
2288 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
2291 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
2293 if (server->config && server->config->server_info &&
2294 server->config->server_info->motd_file) {
2296 motd = silc_file_readfile(server->config->server_info->motd_file,
2302 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
2309 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
2315 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2316 packet->data, packet->len, FALSE);
2317 silc_buffer_free(packet);
2318 silc_buffer_free(idp);
2320 SilcServerEntry entry;
2322 /* Check whether we have this server cached */
2323 entry = silc_idlist_find_server_by_name(server->global_list,
2324 dest_server, TRUE, NULL);
2326 entry = silc_idlist_find_server_by_name(server->local_list,
2327 dest_server, TRUE, NULL);
2330 if (server->server_type != SILC_SERVER && !cmd->pending &&
2331 entry && !entry->motd) {
2332 /* Send to the server */
2334 SilcUInt16 old_ident;
2336 old_ident = silc_command_get_ident(cmd->payload);
2337 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2338 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2340 silc_server_packet_send(server, entry->connection,
2341 SILC_PACKET_COMMAND, cmd->packet->flags,
2342 tmpbuf->data, tmpbuf->len, TRUE);
2344 /* Reprocess this packet after received reply from router */
2345 silc_server_command_pending(server, SILC_COMMAND_MOTD,
2346 silc_command_get_ident(cmd->payload),
2347 silc_server_command_motd,
2348 silc_server_command_dup(cmd));
2349 cmd->pending = TRUE;
2350 silc_command_set_ident(cmd->payload, old_ident);
2351 silc_buffer_free(tmpbuf);
2355 if (!entry && !cmd->pending && !server->standalone) {
2356 /* Send to the primary router */
2358 SilcUInt16 old_ident;
2360 old_ident = silc_command_get_ident(cmd->payload);
2361 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2362 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2364 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
2365 SILC_PACKET_COMMAND, cmd->packet->flags,
2366 tmpbuf->data, tmpbuf->len, TRUE);
2368 /* Reprocess this packet after received reply from router */
2369 silc_server_command_pending(server, SILC_COMMAND_MOTD,
2370 silc_command_get_ident(cmd->payload),
2371 silc_server_command_motd,
2372 silc_server_command_dup(cmd));
2373 cmd->pending = TRUE;
2374 silc_command_set_ident(cmd->payload, old_ident);
2375 silc_buffer_free(tmpbuf);
2380 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2381 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
2385 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
2386 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
2387 SILC_STATUS_OK, 0, ident, 2,
2391 strlen(entry->motd) : 0);
2392 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2393 packet->data, packet->len, FALSE);
2394 silc_buffer_free(packet);
2395 silc_buffer_free(idp);
2399 silc_server_command_free(cmd);
2402 /* Server side of command UMODE. Client can use this command to set/unset
2403 user mode. Client actually cannot set itself to be as server/router
2404 operator so this can be used only to unset the modes. */
2406 SILC_SERVER_CMD_FUNC(umode)
2408 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2409 SilcServer server = cmd->server;
2410 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2412 unsigned char *tmp_mask, m[4];
2413 SilcUInt32 mask = 0;
2414 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2415 bool set_mask = FALSE;
2417 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
2420 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2);
2422 /* Get the client's mode mask */
2423 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2425 SILC_GET32_MSB(mask, tmp_mask);
2430 /* Check that mode changing is allowed. */
2431 if (!silc_server_check_umode_rights(server, client, mask)) {
2432 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2433 SILC_STATUS_ERR_PERM_DENIED, 0);
2437 /* Anonymous mode cannot be set by client */
2438 if (mask & SILC_UMODE_ANONYMOUS) {
2439 if (!(client->mode & SILC_UMODE_ANONYMOUS)) {
2440 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2441 SILC_STATUS_ERR_PERM_DENIED, 0);
2445 if (client->mode & SILC_UMODE_ANONYMOUS) {
2446 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2447 SILC_STATUS_ERR_PERM_DENIED, 0);
2452 /* Update statistics */
2453 if (mask & SILC_UMODE_GONE) {
2454 if (!(client->mode & SILC_UMODE_GONE))
2455 server->stat.my_aways++;
2457 if (client->mode & SILC_UMODE_GONE)
2458 server->stat.my_aways--;
2461 /* Change the mode */
2462 client->mode = mask;
2464 /* Send UMODE change to primary router */
2465 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
2466 SILC_BROADCAST(server), client->id,
2469 /* Check if anyone is watching this nickname */
2470 if (server->server_type == SILC_ROUTER)
2471 silc_server_check_watcher_list(server, client, NULL,
2472 SILC_NOTIFY_TYPE_UMODE_CHANGE);
2475 /* Send command reply to sender */
2476 SILC_PUT32_MSB(client->mode, m);
2477 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
2478 SILC_STATUS_OK, 0, ident, 1,
2480 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2481 packet->data, packet->len, FALSE);
2482 silc_buffer_free(packet);
2485 silc_server_command_free(cmd);
2488 /* Server side command of CMODE. Changes channel mode */
2490 SILC_SERVER_CMD_FUNC(cmode)
2492 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2493 SilcServer server = cmd->server;
2494 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2495 SilcIDListData idata = (SilcIDListData)client;
2496 SilcChannelID *channel_id = NULL;
2497 SilcChannelEntry channel;
2498 SilcChannelClientEntry chl;
2499 SilcBuffer packet, cidp;
2500 unsigned char *tmp, *tmp_id, *tmp_mask;
2501 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
2502 SilcUInt32 mode_mask = 0, old_mask = 0, tmp_len, tmp_len2;
2503 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2504 bool set_mask = FALSE;
2505 SilcPublicKey founder_key = NULL;
2506 unsigned char *fkey = NULL;
2507 SilcUInt32 fkey_len = 0;
2510 silc_server_command_free(cmd);
2514 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 7);
2516 /* Get Channel ID */
2517 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2519 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2520 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2521 silc_server_command_free(cmd);
2524 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
2526 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2527 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2528 silc_server_command_free(cmd);
2532 /* Get channel entry */
2533 channel = silc_idlist_find_channel_by_id(server->local_list,
2536 channel = silc_idlist_find_channel_by_id(server->global_list,
2539 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2540 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
2542 silc_free(channel_id);
2543 silc_server_command_free(cmd);
2547 old_mask = channel->mode;
2549 /* Get the channel mode mask */
2550 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2552 SILC_GET32_MSB(mode_mask, tmp_mask);
2556 /* Check whether this client is on the channel */
2557 if (!silc_server_client_on_channel(client, channel, &chl)) {
2558 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2559 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
2563 /* Check that client has rights to change any requested channel modes */
2564 if (set_mask && !silc_server_check_cmode_rights(server, channel, chl,
2566 SILC_LOG_DEBUG(("Client does not have rights to change mode"));
2567 silc_server_command_send_status_reply(
2568 cmd, SILC_COMMAND_CMODE,
2569 (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) ?
2570 SILC_STATUS_ERR_NO_CHANNEL_PRIV :
2571 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV), 0);
2575 /* If mode mask was not sent as argument then merely return the current
2576 mode mask to the sender. */
2579 SILC_PUT32_MSB(channel->mode, m);
2580 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2581 SILC_STATUS_OK, 0, ident, 2,
2582 2, tmp_id, tmp_len2,
2584 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2585 packet->data, packet->len, FALSE);
2586 silc_buffer_free(packet);
2591 * Check the modes. Modes that requires nothing special operation are
2595 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2596 /* Channel uses private keys to protect traffic. Client(s) has set the
2597 key locally they want to use, server does not know that key. */
2598 /* Nothing interesting to do here */
2600 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2601 /* The mode is removed and we need to generate and distribute
2602 new channel key. Clients are not using private channel keys
2603 anymore after this. */
2605 /* Re-generate channel key */
2606 if (!silc_server_create_channel_key(server, channel, 0))
2609 /* Send the channel key. This sends it to our local clients and if
2610 we are normal server to our router as well. */
2611 silc_server_send_channel_key(server, NULL, channel,
2612 server->server_type == SILC_ROUTER ?
2613 FALSE : !server->standalone);
2615 cipher = (char *)silc_cipher_get_name(channel->channel_key);
2616 hmac = (char *)silc_hmac_get_name(channel->hmac);
2620 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2621 /* User limit is set on channel */
2622 SilcUInt32 user_limit;
2624 /* Get user limit */
2625 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2627 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2628 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2629 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
2633 SILC_GET32_MSB(user_limit, tmp);
2634 channel->user_limit = user_limit;
2637 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2638 /* User limit mode is unset. Remove user limit */
2639 channel->user_limit = 0;
2642 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
2643 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
2644 /* Passphrase has been set to channel */
2646 /* Get the passphrase */
2647 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
2649 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2650 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
2654 /* Save the passphrase */
2655 passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
2658 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2659 /* Passphrase mode is unset. remove the passphrase */
2660 silc_free(channel->passphrase);
2661 channel->passphrase = NULL;
2665 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
2666 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
2667 /* Cipher to use protect the traffic */
2668 SilcCipher newkey, oldkey;
2671 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
2673 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2674 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
2678 /* Delete old cipher and allocate the new one */
2679 if (!silc_cipher_alloc(cipher, &newkey)) {
2680 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2681 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
2685 oldkey = channel->channel_key;
2686 channel->channel_key = newkey;
2688 /* Re-generate channel key */
2689 if (!silc_server_create_channel_key(server, channel, 0)) {
2690 /* We don't have new key, revert to old one */
2691 channel->channel_key = oldkey;
2695 /* Remove old channel key for good */
2696 silc_cipher_free(oldkey);
2698 /* Send the channel key. This sends it to our local clients and if
2699 we are normal server to our router as well. */
2700 silc_server_send_channel_key(server, NULL, channel,
2701 server->server_type == SILC_ROUTER ?
2702 FALSE : !server->standalone);
2705 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2706 /* Cipher mode is unset. Remove the cipher and revert back to
2708 SilcCipher newkey, oldkey;
2709 cipher = channel->cipher;
2711 /* Delete old cipher and allocate default one */
2712 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
2713 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2714 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
2718 oldkey = channel->channel_key;
2719 channel->channel_key = newkey;
2721 /* Re-generate channel key */
2722 if (!silc_server_create_channel_key(server, channel, 0)) {
2723 /* We don't have new key, revert to old one */
2724 channel->channel_key = oldkey;
2728 /* Remove old channel key for good */
2729 silc_cipher_free(oldkey);
2731 /* Send the channel key. This sends it to our local clients and if
2732 we are normal server to our router as well. */
2733 silc_server_send_channel_key(server, NULL, channel,
2734 server->server_type == SILC_ROUTER ?
2735 FALSE : !server->standalone);
2739 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
2740 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
2741 /* HMAC to use protect the traffic */
2742 unsigned char hash[32];
2746 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
2748 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2749 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
2753 /* Delete old hmac and allocate the new one */
2754 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
2755 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2756 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
2760 silc_hmac_free(channel->hmac);
2761 channel->hmac = newhmac;
2763 /* Set the HMAC key out of current channel key. The client must do
2765 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
2766 channel->key_len / 8, hash);
2767 silc_hmac_set_key(channel->hmac, hash,
2768 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
2769 memset(hash, 0, sizeof(hash));
2772 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
2773 /* Hmac mode is unset. Remove the hmac and revert back to
2776 unsigned char hash[32];
2777 hmac = channel->hmac_name;
2779 /* Delete old hmac and allocate default one */
2780 silc_hmac_free(channel->hmac);
2781 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
2782 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2783 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
2787 silc_hmac_free(channel->hmac);
2788 channel->hmac = newhmac;
2790 /* Set the HMAC key out of current channel key. The client must do
2792 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
2793 channel->key_len / 8,
2795 silc_hmac_set_key(channel->hmac, hash,
2796 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
2797 memset(hash, 0, sizeof(hash));
2801 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
2802 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2803 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
2804 /* Set the founder authentication */
2805 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
2807 silc_server_command_send_status_reply(
2808 cmd, SILC_COMMAND_CMODE,
2809 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
2813 /* Verify the payload before setting the mode */
2814 if (!silc_auth_verify_data(tmp, tmp_len, SILC_AUTH_PUBLIC_KEY,
2815 idata->public_key, 0, server->sha1hash,
2816 client->id, SILC_ID_CLIENT)) {
2817 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2818 SILC_STATUS_ERR_AUTH_FAILED,
2823 /* Save the public key */
2824 channel->founder_key = silc_pkcs_public_key_copy(idata->public_key);
2825 if (!channel->founder_key) {
2826 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2827 SILC_STATUS_ERR_AUTH_FAILED,
2832 founder_key = channel->founder_key;
2833 fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
2835 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2836 SILC_STATUS_ERR_AUTH_FAILED,
2838 silc_pkcs_public_key_free(channel->founder_key);
2839 channel->founder_key = NULL;
2845 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2846 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
2847 if (channel->founder_key)
2848 silc_pkcs_public_key_free(channel->founder_key);
2849 channel->founder_key = NULL;
2854 /* Finally, set the mode */
2855 old_mask = channel->mode = mode_mask;
2857 /* Send CMODE_CHANGE notify. */
2858 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2859 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2860 SILC_NOTIFY_TYPE_CMODE_CHANGE, 6,
2861 cidp->data, cidp->len,
2863 cipher, cipher ? strlen(cipher) : 0,
2864 hmac, hmac ? strlen(hmac) : 0,
2865 passphrase, passphrase ?
2866 strlen(passphrase) : 0,
2869 /* Set CMODE notify type to network */
2870 silc_server_send_notify_cmode(server, SILC_PRIMARY_ROUTE(server),
2871 SILC_BROADCAST(server), channel,
2872 mode_mask, client->id, SILC_ID_CLIENT,
2873 cipher, hmac, passphrase, founder_key);
2875 /* Send command reply to sender */
2876 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2877 SILC_STATUS_OK, 0, ident, 2,
2878 2, tmp_id, tmp_len2,
2880 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2881 packet->data, packet->len, FALSE);
2883 silc_buffer_free(packet);
2884 silc_buffer_free(cidp);
2887 channel->mode = old_mask;
2889 silc_free(channel_id);
2890 silc_server_command_free(cmd);
2893 /* Server side of CUMODE command. Changes client's mode on a channel. */
2895 SILC_SERVER_CMD_FUNC(cumode)
2897 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2898 SilcServer server = cmd->server;
2899 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2900 SilcIDListData idata = (SilcIDListData)client;
2901 SilcChannelID *channel_id = NULL;
2902 SilcClientID *client_id = NULL;
2903 SilcChannelEntry channel;
2904 SilcClientEntry target_client;
2905 SilcChannelClientEntry chl;
2906 SilcBuffer packet, idp;
2907 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
2908 SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
2910 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2911 SilcPublicKey founder_key = NULL;
2912 unsigned char *fkey = NULL;
2913 SilcUInt32 fkey_len = 0;
2918 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
2920 /* Get Channel ID */
2921 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
2923 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2924 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2927 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
2929 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2930 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2934 /* Get channel entry */
2935 channel = silc_idlist_find_channel_by_id(server->local_list,
2938 channel = silc_idlist_find_channel_by_id(server->global_list,
2941 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2942 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
2948 /* Check whether sender is on the channel */
2949 if (!silc_server_client_on_channel(client, channel, &chl)) {
2950 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2951 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
2954 sender_mask = chl->mode;
2956 /* Get the target client's channel mode mask */
2957 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2959 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2960 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2964 SILC_GET32_MSB(target_mask, tmp_mask);
2966 /* Get target Client ID */
2967 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2969 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2970 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
2973 client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
2975 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2976 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
2980 /* Get target client's entry */
2981 target_client = silc_idlist_find_client_by_id(server->local_list,
2982 client_id, TRUE, NULL);
2983 if (!target_client) {
2984 target_client = silc_idlist_find_client_by_id(server->global_list,
2985 client_id, TRUE, NULL);
2988 if (target_client != client &&
2989 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
2990 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
2991 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2992 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
2996 /* Check whether target client is on the channel */
2997 if (target_client != client) {
2998 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
2999 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3000 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL, 0);
3009 /* If the target client is founder, no one else can change their mode
3011 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
3012 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3013 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
3018 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
3019 if (target_client != client) {
3020 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3021 SILC_STATUS_ERR_NOT_YOU, 0);
3025 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
3026 /* The client tries to claim the founder rights. */
3027 unsigned char *tmp_auth;
3028 SilcUInt32 tmp_auth_len;
3029 SilcChannelClientEntry chl2;
3030 SilcHashTableList htl;
3032 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
3033 !channel->founder_key || !idata->public_key ||
3034 !silc_pkcs_public_key_compare(channel->founder_key,
3035 idata->public_key)) {
3036 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3037 SILC_STATUS_ERR_AUTH_FAILED, 0);
3041 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
3043 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3044 SILC_STATUS_ERR_AUTH_FAILED, 0);
3048 /* Verify the authentication payload */
3049 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len, SILC_AUTH_PUBLIC_KEY,
3050 channel->founder_key, 0, server->sha1hash,
3051 client->id, SILC_ID_CLIENT)) {
3052 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3053 SILC_STATUS_ERR_AUTH_FAILED, 0);
3058 founder_key = channel->founder_key;
3059 fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
3061 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3062 SILC_STATUS_ERR_AUTH_FAILED, 0);
3066 /* There cannot be anyone else as founder on the channel now. This
3067 client is definitely the founder due to this authentication */
3068 silc_hash_table_list(channel->user_list, &htl);
3069 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
3070 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
3071 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3072 silc_server_force_cumode_change(server, NULL, channel, chl2,
3076 silc_hash_table_list_reset(&htl);
3078 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
3081 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3082 if (target_client == client) {
3083 /* Remove channel founder rights from itself */
3084 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3087 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3088 SILC_STATUS_ERR_NOT_YOU, 0);
3094 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
3095 /* Promote to operator */
3096 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3097 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3098 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3099 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3100 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
3105 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
3109 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
3110 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3111 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3112 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3113 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
3118 /* Demote to normal user */
3119 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
3124 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
3125 if (target_client != client) {
3126 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3127 SILC_STATUS_ERR_NOT_YOU, 0);
3131 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
3132 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
3136 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
3137 if (target_client != client) {
3138 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3139 SILC_STATUS_ERR_NOT_YOU, 0);
3143 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
3148 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
3149 if (target_client != client) {
3150 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3151 SILC_STATUS_ERR_NOT_YOU, 0);
3155 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)) {
3156 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
3160 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
3161 if (target_client != client) {
3162 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3163 SILC_STATUS_ERR_NOT_YOU, 0);
3167 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
3172 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
3173 if (target_client != client) {
3174 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3175 SILC_STATUS_ERR_NOT_YOU, 0);
3179 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)) {
3180 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
3184 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
3185 if (target_client != client) {
3186 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3187 SILC_STATUS_ERR_NOT_YOU, 0);
3191 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
3196 if (target_mask & SILC_CHANNEL_UMODE_QUIET) {
3197 if (!(chl->mode & SILC_CHANNEL_UMODE_QUIET)) {
3198 if (client == target_client) {
3199 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3200 SILC_STATUS_ERR_PERM_DENIED, 0);
3203 chl->mode |= SILC_CHANNEL_UMODE_QUIET;
3207 if (chl->mode & SILC_CHANNEL_UMODE_QUIET) {
3208 if (client == target_client) {
3209 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3210 SILC_STATUS_ERR_PERM_DENIED, 0);
3213 chl->mode &= ~SILC_CHANNEL_UMODE_QUIET;
3218 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3219 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3221 /* Send notify to channel, notify only if mode was actually changed. */
3223 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3224 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
3225 idp->data, idp->len,
3230 /* Set CUMODE notify type to network */
3231 silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
3232 SILC_BROADCAST(server), channel,
3233 target_mask, client->id, SILC_ID_CLIENT,
3234 target_client->id, founder_key);
3237 /* Send command reply to sender */
3238 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
3239 SILC_STATUS_OK, 0, ident, 3,
3241 3, tmp_ch_id, tmp_ch_len,
3242 4, tmp_id, tmp_len);
3243 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3244 packet->data, packet->len, FALSE);
3246 silc_buffer_free(packet);
3247 silc_buffer_free(idp);
3250 silc_free(channel_id);
3251 silc_free(client_id);
3253 silc_server_command_free(cmd);
3256 /* Server side of KICK command. Kicks client out of channel. */
3258 SILC_SERVER_CMD_FUNC(kick)
3260 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3261 SilcServer server = cmd->server;
3262 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3263 SilcClientEntry target_client;
3264 SilcChannelID *channel_id;
3265 SilcClientID *client_id;
3266 SilcChannelEntry channel;
3267 SilcChannelClientEntry chl;
3269 SilcUInt32 tmp_len, target_idp_len;
3270 unsigned char *tmp, *comment, *target_idp;
3275 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
3277 /* Get Channel ID */
3278 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3280 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3281 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3284 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3286 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3287 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3291 /* Get channel entry */
3292 channel = silc_idlist_find_channel_by_id(server->local_list,
3295 channel = silc_idlist_find_channel_by_id(server->local_list,
3298 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3299 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
3305 /* Check whether sender is on the channel */
3306 if (!silc_server_client_on_channel(client, channel, &chl)) {
3307 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3308 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
3312 /* Check that the kicker is channel operator or channel founder */
3313 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
3314 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
3315 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3316 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
3320 /* Get target Client ID */
3321 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
3323 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3324 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
3327 client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
3329 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3330 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
3334 /* Get target client's entry */
3335 target_client = silc_idlist_find_client_by_id(server->local_list,
3336 client_id, TRUE, NULL);
3337 if (!target_client) {
3338 target_client = silc_idlist_find_client_by_id(server->global_list,
3339 client_id, TRUE, NULL);
3342 /* Check whether target client is on the channel */
3343 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
3344 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3345 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL,
3350 /* Check that the target client is not channel founder. Channel founder
3351 cannot be kicked from the channel. */
3352 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3353 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3354 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
3361 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3365 /* Send command reply to sender */
3366 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3369 /* Send KICKED notify to local clients on the channel */
3370 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3371 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3372 SILC_NOTIFY_TYPE_KICKED, 3,
3373 target_idp, target_idp_len,
3374 comment, comment ? strlen(comment) : 0,
3375 idp->data, idp->len);
3376 silc_buffer_free(idp);
3378 /* Send KICKED notify to primary route */
3379 silc_server_send_notify_kicked(server, SILC_PRIMARY_ROUTE(server),
3380 SILC_BROADCAST(server), channel,
3381 target_client->id, client->id, comment);
3383 /* Remove the client from the channel. If the channel does not exist
3384 after removing the client then the client kicked itself off the channel
3385 and we don't have to send anything after that. */
3386 if (!silc_server_remove_from_one_channel(server, NULL, channel,
3387 target_client, FALSE))
3390 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3391 /* Re-generate channel key */
3392 if (!silc_server_create_channel_key(server, channel, 0))
3395 /* Send the channel key to the channel. The key of course is not sent
3396 to the client who was kicked off the channel. */
3397 silc_server_send_channel_key(server, target_client->connection, channel,
3398 server->server_type == SILC_ROUTER ?
3399 FALSE : !server->standalone);
3403 silc_server_command_free(cmd);
3406 /* Server side of OPER command. Client uses this comand to obtain server
3407 operator privileges to this server/router. */
3409 SILC_SERVER_CMD_FUNC(oper)
3411 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3412 SilcServer server = cmd->server;
3413 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3414 unsigned char *username, *auth;
3416 SilcServerConfigAdmin *admin;
3417 SilcIDListData idata = (SilcIDListData)client;
3418 bool result = FALSE;
3419 SilcPublicKey cached_key;
3421 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
3424 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
3426 /* Get the username */
3427 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3429 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3430 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3435 /* Get the admin configuration */
3436 admin = silc_server_config_find_admin(server, cmd->sock->ip,
3437 username, client->nickname);
3439 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
3440 username, client->nickname);
3442 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3443 SILC_STATUS_ERR_AUTH_FAILED,
3445 SILC_LOG_INFO(("OPER authentication failed for username '%s' by"
3446 "nickname '%s' from %s", username,
3447 client->nickname, cmd->sock->hostname));
3452 /* Get the authentication payload */
3453 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3455 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3456 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3461 /* Verify the authentication data. If both passphrase and public key
3462 is set then try both of them. */
3463 if (admin->passphrase)
3464 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
3465 admin->passphrase, admin->passphrase_len,
3466 idata->hash, client->id, SILC_ID_CLIENT);
3467 if (!result && admin->publickeys) {
3468 cached_key = silc_server_get_public_key(server, admin->publickeys);
3471 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
3472 cached_key, 0, idata->hash,
3473 client->id, SILC_ID_CLIENT);
3476 /* Authentication failed */
3477 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3478 SILC_STATUS_ERR_AUTH_FAILED,
3483 /* Client is now server operator */
3484 client->mode |= SILC_UMODE_SERVER_OPERATOR;
3486 /* Update statistics */
3487 if (SILC_IS_LOCAL(client))
3488 server->stat.my_server_ops++;
3489 if (server->server_type == SILC_ROUTER)
3490 server->stat.server_ops++;
3492 /* Send UMODE change to primary router */
3493 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
3494 SILC_BROADCAST(server), client->id,
3497 /* Check if anyone is watching this nickname */
3498 if (server->server_type == SILC_ROUTER)
3499 silc_server_check_watcher_list(server, client, NULL,
3500 SILC_NOTIFY_TYPE_UMODE_CHANGE);
3502 /* Send reply to the sender */
3503 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3507 silc_server_command_free(cmd);
3510 SILC_TASK_CALLBACK(silc_server_command_detach_cb)
3512 SilcServer server = app_context;
3513 QuitInternal q = (QuitInternal)context;
3514 SilcClientID *client_id = (SilcClientID *)q->sock;
3515 SilcClientEntry client;
3516 SilcSocketConnection sock;
3518 client = silc_idlist_find_client_by_id(server->local_list, client_id,
3520 if (client && client->connection) {
3521 sock = client->connection;
3523 /* If there is pending outgoing data for the client then purge it
3524 to the network before closing connection. */
3525 silc_server_packet_queue_purge(server, sock);
3527 /* Close the connection on our side */
3528 client->router = NULL;
3529 client->connection = NULL;
3530 sock->user_data = NULL;
3531 silc_server_close_connection(server, sock);
3534 silc_free(client_id);
3538 SILC_TASK_CALLBACK(silc_server_command_detach_timeout)
3540 SilcServer server = app_context;
3541 QuitInternal q = (QuitInternal)context;
3542 SilcClientID *client_id = (SilcClientID *)q->sock;
3543 SilcClientEntry client;
3545 client = silc_idlist_find_client_by_id(server->local_list, client_id,
3547 if (client && client->mode & SILC_UMODE_DETACHED) {
3548 SILC_LOG_DEBUG(("Detach timeout"));
3549 silc_server_free_client_data(server, NULL, client, TRUE,
3553 silc_free(client_id);
3557 /* Server side of DETACH command. Detached the client from the network
3558 by closing the connection but preserving the session. */
3560 SILC_SERVER_CMD_FUNC(detach)
3562 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3563 SilcServer server = cmd->server;
3564 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3567 if (server->config->detach_disabled) {
3568 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
3569 SILC_STATUS_ERR_UNKNOWN_COMMAND, 0);
3573 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
3576 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
3578 /* Remove operator privileges, since the client may resume in some
3579 other server which to it does not have operator privileges. */
3580 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
3581 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
3583 /* Send the user mode notify to notify that client is detached */
3584 client->mode |= SILC_UMODE_DETACHED;
3585 client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
3586 client->data.status &= ~SILC_IDLIST_STATUS_NOATTR;
3587 client->last_command = 0;
3588 client->fast_command = 0;
3589 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
3590 SILC_BROADCAST(server), client->id,
3592 server->stat.my_detached++;
3594 /* Check if anyone is watching this nickname */
3595 if (server->server_type == SILC_ROUTER)
3596 silc_server_check_watcher_list(server, client, NULL,
3597 SILC_NOTIFY_TYPE_UMODE_CHANGE);
3599 q = silc_calloc(1, sizeof(*q));
3600 q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
3601 silc_schedule_task_add(server->schedule, 0, silc_server_command_detach_cb,
3602 q, 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
3604 if (server->config->detach_timeout) {
3605 q = silc_calloc(1, sizeof(*q));
3606 q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
3607 silc_schedule_task_add(server->schedule, 0,
3608 silc_server_command_detach_timeout,
3609 q, server->config->detach_timeout * 60,
3610 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
3613 /* Send reply to the sender */
3614 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
3618 silc_server_command_free(cmd);
3621 /* Server side of WATCH command. */
3623 SILC_SERVER_CMD_FUNC(watch)
3625 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3626 SilcServer server = cmd->server;
3627 char *add_nick, *del_nick;
3628 SilcUInt32 add_nick_len, del_nick_len, tmp_len;
3630 unsigned char hash[16], *tmp;
3631 SilcClientEntry client;
3632 SilcClientID *client_id = NULL;
3634 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WATCH, cmd, 1, 3);
3636 if (server->server_type != SILC_ROUTER && !server->standalone) {
3637 if (!cmd->pending) {
3638 /* Send the command to router */
3640 SilcUInt16 old_ident;
3642 SILC_LOG_DEBUG(("Forwarding WATCH to router"));
3644 old_ident = silc_command_get_ident(cmd->payload);
3645 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3646 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3648 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
3649 SILC_PACKET_COMMAND, cmd->packet->flags,
3650 tmpbuf->data, tmpbuf->len, TRUE);
3652 /* Reprocess this packet after received reply from router */
3653 silc_server_command_pending(server, SILC_COMMAND_WATCH,
3654 silc_command_get_ident(cmd->payload),
3655 silc_server_command_watch,
3656 silc_server_command_dup(cmd));
3657 cmd->pending = TRUE;
3658 silc_command_set_ident(cmd->payload, old_ident);
3659 silc_buffer_free(tmpbuf);
3660 } else if (context2) {
3661 /* Received reply from router, just send same data to the client. */
3662 SilcServerCommandReplyContext reply = context2;
3665 SILC_LOG_DEBUG(("Received reply to WATCH from router"));
3666 silc_command_get_status(reply->payload, &status, NULL);
3667 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, status,
3674 /* We are router and keep the watch list for local cell */
3676 /* Get the client ID */
3677 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3679 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
3680 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3684 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3686 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
3687 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
3692 /* Get the client entry which must be in local list */
3693 client = silc_idlist_find_client_by_id(server->local_list,
3694 client_id, TRUE, NULL);
3696 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
3697 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
3703 add_nick = silc_argument_get_arg_type(cmd->args, 2, &add_nick_len);
3704 del_nick = silc_argument_get_arg_type(cmd->args, 3, &del_nick_len);
3705 if (!add_nick && !del_nick) {
3706 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
3707 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3712 if (add_nick && add_nick_len > 128)
3713 add_nick[128] = '\0';
3714 if (del_nick && del_nick_len > 128)
3715 del_nick[128] = '\0';
3717 memset(nick, 0, sizeof(nick));
3719 /* Add new nickname to be watched in our cell */
3721 if (silc_server_name_bad_chars(add_nick, strlen(add_nick)) == TRUE) {
3722 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
3723 SILC_STATUS_ERR_BAD_NICKNAME, 0);
3727 /* Hash the nick, we have the hash saved, not nicks because we can
3728 do one to one mapping to the nick from Client ID hash this way. */
3729 silc_to_lower(add_nick, nick, sizeof(nick) - 1);
3730 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
3732 /* Check whether this client is already watching this nickname */
3733 if (silc_hash_table_find_by_context(server->watcher_list, hash,
3735 /* Nickname is alredy being watched for this client */
3736 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
3737 SILC_STATUS_ERR_NICKNAME_IN_USE,
3742 /* Get the nickname from the watcher list and use the same key in
3743 new entries as well. If key doesn't exist then create it. */
3744 if (!silc_hash_table_find(server->watcher_list, hash, (void **)&tmp, NULL))
3745 tmp = silc_memdup(hash, CLIENTID_HASH_LEN);
3747 /* Add the client to the watcher list with the specified nickname hash. */
3748 silc_hash_table_add(server->watcher_list, tmp, client);
3751 /* Delete nickname from watch list */
3753 if (silc_server_name_bad_chars(del_nick, strlen(del_nick)) == TRUE) {
3754 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
3755 SILC_STATUS_ERR_BAD_NICKNAME, 0);
3759 /* Hash the nick, we have the hash saved, not nicks because we can
3760 do one to one mapping to the nick from Client ID hash this way. */
3761 silc_to_lower(del_nick, nick, sizeof(nick) - 1);
3762 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
3764 /* Check that this client is watching for this nickname */
3765 if (!silc_hash_table_find_by_context(server->watcher_list, hash,
3766 client, (void **)&tmp)) {
3767 /* Nickname is alredy being watched for this client */
3768 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
3769 SILC_STATUS_ERR_NO_SUCH_NICK, 0);
3773 /* Delete the nickname from the watcher list. */
3774 silc_hash_table_del_by_context(server->watcher_list, hash, client);
3776 /* Now check whether there still exists entries with this key, if not
3777 then free the key to not leak memory. */
3778 if (!silc_hash_table_find(server->watcher_list, hash, NULL, NULL))
3782 /* Distribute the watch list to backup routers too */
3783 if (server->backup) {
3785 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3786 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3787 silc_server_backup_send(server, NULL, SILC_PACKET_COMMAND,
3788 cmd->packet->flags, tmpbuf->data, tmpbuf->len,
3790 silc_buffer_free(tmpbuf);
3793 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
3797 silc_free(client_id);
3798 silc_server_command_free(cmd);
3801 /* Server side of SILCOPER command. Client uses this comand to obtain router
3802 operator privileges to this router. */
3804 SILC_SERVER_CMD_FUNC(silcoper)
3806 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3807 SilcServer server = cmd->server;
3808 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3809 unsigned char *username, *auth;
3811 SilcServerConfigAdmin *admin;
3812 SilcIDListData idata = (SilcIDListData)client;
3813 bool result = FALSE;
3814 SilcPublicKey cached_key;
3816 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
3819 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
3821 if (server->server_type != SILC_ROUTER) {
3822 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3823 SILC_STATUS_ERR_AUTH_FAILED, 0);
3827 /* Get the username */
3828 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3830 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3831 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3836 /* Get the admin configuration */
3837 admin = silc_server_config_find_admin(server, cmd->sock->ip,
3838 username, client->nickname);
3840 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
3841 username, client->nickname);
3843 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3844 SILC_STATUS_ERR_AUTH_FAILED, 0);
3845 SILC_LOG_INFO(("SILCOPER authentication failed for username '%s' by"
3846 "nickname '%s' from %s", username,
3847 client->nickname, cmd->sock->hostname));
3852 /* Get the authentication payload */
3853 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3855 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3856 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3861 /* Verify the authentication data. If both passphrase and public key
3862 is set then try both of them. */
3863 if (admin->passphrase)
3864 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
3865 admin->passphrase, admin->passphrase_len,
3866 idata->hash, client->id, SILC_ID_CLIENT);
3867 if (!result && admin->publickeys) {
3868 cached_key = silc_server_get_public_key(server, admin->publickeys);
3871 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
3872 cached_key, 0, idata->hash,
3873 client->id, SILC_ID_CLIENT);
3876 /* Authentication failed */
3877 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3878 SILC_STATUS_ERR_AUTH_FAILED, 0);
3882 /* Client is now router operator */
3883 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
3885 /* Update statistics */
3886 if (SILC_IS_LOCAL(client))
3887 server->stat.my_router_ops++;
3888 if (server->server_type == SILC_ROUTER)
3889 server->stat.router_ops++;
3891 /* Send UMODE change to primary router */
3892 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
3893 SILC_BROADCAST(server), client->id,
3896 /* Check if anyone is watching this nickname */
3897 if (server->server_type == SILC_ROUTER)
3898 silc_server_check_watcher_list(server, client, NULL,
3899 SILC_NOTIFY_TYPE_UMODE_CHANGE);
3901 /* Send reply to the sender */
3902 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3906 silc_server_command_free(cmd);
3909 /* Server side of command BAN. This is used to manage the ban list of the
3910 channel. To add clients and remove clients from the ban list. */
3912 SILC_SERVER_CMD_FUNC(ban)
3914 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3915 SilcServer server = cmd->server;
3916 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3918 SilcChannelEntry channel;
3919 SilcChannelClientEntry chl;
3920 SilcChannelID *channel_id = NULL;
3921 unsigned char *id, *add, *del;
3922 SilcUInt32 id_len, tmp_len;
3923 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3925 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
3928 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
3930 /* Get Channel ID */
3931 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
3933 channel_id = silc_id_payload_parse_id(id, id_len, NULL);
3935 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
3936 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3941 /* Get channel entry. The server must know about the channel since the
3942 client is expected to be on the channel. */
3943 channel = silc_idlist_find_channel_by_id(server->local_list,
3946 channel = silc_idlist_find_channel_by_id(server->global_list,
3949 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
3950 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
3956 /* Check whether this client is on the channel */
3957 if (!silc_server_client_on_channel(client, channel, &chl)) {
3958 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
3959 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
3963 /* The client must be at least channel operator. */
3964 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3965 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
3966 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
3970 /* Get the new ban and add it to the ban list */
3971 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3973 if (!channel->ban_list)
3974 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
3976 channel->ban_list = silc_realloc(channel->ban_list,
3977 sizeof(*channel->ban_list) *
3979 strlen(channel->ban_list) + 2));
3980 if (add[tmp_len - 1] == ',')
3981 add[tmp_len - 1] = '\0';
3983 strncat(channel->ban_list, add, tmp_len);
3984 strncat(channel->ban_list, ",", 1);
3987 /* Get the ban to be removed and remove it from the list */
3988 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3989 if (del && channel->ban_list) {
3990 char *start, *end, *n;
3992 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
3993 silc_free(channel->ban_list);
3994 channel->ban_list = NULL;
3996 start = strstr(channel->ban_list, del);
3997 if (start && strlen(start) >= tmp_len) {
3998 end = start + tmp_len;
3999 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4000 strncat(n, channel->ban_list, start - channel->ban_list);
4001 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4003 silc_free(channel->ban_list);
4004 channel->ban_list = n;
4009 /* Send the BAN notify type to our primary router. */
4011 silc_server_send_notify_ban(server, SILC_PRIMARY_ROUTE(server),
4012 SILC_BROADCAST(server), channel, add, del);
4014 /* Send the reply back to the client */
4016 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4017 SILC_STATUS_OK, 0, ident, 2,
4019 3, channel->ban_list,
4021 strlen(channel->ban_list) -1 : 0);
4022 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4023 packet->data, packet->len, FALSE);
4025 silc_buffer_free(packet);
4028 silc_free(channel_id);
4029 silc_server_command_free(cmd);
4032 /* Server side command of LEAVE. Removes client from a channel. */
4034 SILC_SERVER_CMD_FUNC(leave)
4036 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4037 SilcServer server = cmd->server;
4038 SilcSocketConnection sock = cmd->sock;
4039 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4040 SilcChannelID *id = NULL;
4041 SilcChannelEntry channel;
4045 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !id_entry)
4048 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4050 /* Get Channel ID */
4051 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4053 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4054 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4057 id = silc_id_payload_parse_id(tmp, len, NULL);
4059 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4060 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4064 /* Get channel entry */
4065 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4067 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4069 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4070 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4076 /* Check whether this client is on the channel */
4077 if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
4078 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4079 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4083 /* Notify routers that they should remove this client from their list
4084 of clients on the channel. Send LEAVE notify type. */
4085 silc_server_send_notify_leave(server, SILC_PRIMARY_ROUTE(server),
4086 SILC_BROADCAST(server), channel, id_entry->id);
4088 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4089 SILC_STATUS_OK, 0, 2, tmp, len);
4091 /* Remove client from channel */
4092 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4094 /* If the channel does not exist anymore we won't send anything */
4097 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4098 /* Re-generate channel key */
4099 if (!silc_server_create_channel_key(server, channel, 0))
4102 /* Send the channel key */
4103 silc_server_send_channel_key(server, NULL, channel,
4104 server->server_type == SILC_ROUTER ?
4105 FALSE : !server->standalone);
4110 silc_server_command_free(cmd);
4113 /* Server side of command USERS. Resolves clients and their USERS currently
4114 joined on the requested channel. The list of Client ID's and their modes
4115 on the channel is sent back. */
4117 SILC_SERVER_CMD_FUNC(users)
4119 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4120 SilcServer server = cmd->server;
4121 SilcChannelEntry channel;
4122 SilcChannelID *id = NULL;
4123 SilcBuffer packet, idp;
4124 unsigned char *channel_id;
4125 SilcUInt32 channel_id_len;
4126 SilcBuffer client_id_list;
4127 SilcBuffer client_mode_list;
4128 unsigned char lc[4];
4129 SilcUInt32 list_count = 0;
4130 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4133 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
4135 /* Get Channel ID */
4136 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4138 /* Get channel name */
4139 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
4141 if (!channel_id && !channel_name) {
4142 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4143 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4148 id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
4150 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4151 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4156 /* If we are server and we don't know about this channel we will send
4157 the command to our router. If we know about the channel then we also
4158 have the list of users already. */
4160 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4162 channel = silc_idlist_find_channel_by_name(server->local_list,
4163 channel_name, NULL);
4165 if (!channel || (!server->standalone && (channel->disabled ||
4166 !channel->users_resolved))) {
4167 if (server->server_type != SILC_ROUTER && !server->standalone &&
4171 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4172 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4174 /* Send USERS command */
4175 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
4176 SILC_PACKET_COMMAND, cmd->packet->flags,
4177 tmpbuf->data, tmpbuf->len, TRUE);
4179 /* Reprocess this packet after received reply */
4180 silc_server_command_pending(server, SILC_COMMAND_USERS,
4181 silc_command_get_ident(cmd->payload),
4182 silc_server_command_users,
4183 silc_server_command_dup(cmd));
4184 cmd->pending = TRUE;
4185 silc_command_set_ident(cmd->payload, ident);
4186 silc_buffer_free(tmpbuf);
4191 /* Check the global list as well. */
4193 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4195 channel = silc_idlist_find_channel_by_name(server->global_list,
4196 channel_name, NULL);
4198 /* Channel really does not exist */
4199 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4200 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4206 /* If the channel is private or secret do not send anything, unless the
4207 user requesting this command is on the channel or is server */
4208 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
4209 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
4210 && !silc_server_client_on_channel(cmd->sock->user_data, channel,
4212 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4213 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4219 /* Get the users list */
4220 if (!silc_server_get_users_on_channel(server, channel, &client_id_list,
4221 &client_mode_list, &list_count)) {
4223 client_id_list = NULL;
4224 client_mode_list = NULL;
4228 SILC_PUT32_MSB(list_count, lc);
4231 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
4232 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
4233 SILC_STATUS_OK, 0, ident, 4,
4234 2, idp->data, idp->len,
4237 client_id_list->data : NULL,
4239 client_id_list->len : 0,
4240 5, client_mode_list ?
4241 client_mode_list->data : NULL,
4243 client_mode_list->len : 0);
4244 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4245 packet->data, packet->len, FALSE);
4247 silc_buffer_free(idp);
4248 silc_buffer_free(packet);
4250 silc_buffer_free(client_id_list);
4251 if (client_mode_list)
4252 silc_buffer_free(client_mode_list);
4256 silc_server_command_free(cmd);
4259 /* Server side of command GETKEY. This fetches the client's public key
4260 from the server where to the client is connected. */
4262 SILC_SERVER_CMD_FUNC(getkey)
4264 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4265 SilcServer server = cmd->server;
4267 SilcClientEntry client;
4268 SilcServerEntry server_entry;
4269 SilcClientID *client_id = NULL;
4270 SilcServerID *server_id = NULL;
4271 SilcIDPayload idp = NULL;
4272 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4273 unsigned char *tmp, *pkdata;
4274 SilcUInt32 tmp_len, pklen;
4275 SilcBuffer pk = NULL;
4277 SilcPublicKey public_key;
4279 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4281 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4282 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4286 idp = silc_id_payload_parse(tmp, tmp_len);
4288 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4289 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4294 id_type = silc_id_payload_get_type(idp);
4295 if (id_type == SILC_ID_CLIENT) {
4296 client_id = silc_id_payload_get_id(idp);
4298 /* If the client is not found from local list there is no chance it
4299 would be locally connected client so send the command further. */
4300 client = silc_idlist_find_client_by_id(server->local_list,
4301 client_id, TRUE, NULL);
4303 client = silc_idlist_find_client_by_id(server->global_list,
4304 client_id, TRUE, NULL);
4306 if ((!client && !cmd->pending && !server->standalone) ||
4307 (client && !client->connection && !cmd->pending &&
4308 !(client->mode & SILC_UMODE_DETACHED)) ||
4309 (client && !client->data.public_key && !cmd->pending)) {
4311 SilcUInt16 old_ident;
4312 SilcSocketConnection dest_sock;
4314 dest_sock = silc_server_get_client_route(server, NULL, 0,
4315 client_id, NULL, NULL);
4319 old_ident = silc_command_get_ident(cmd->payload);
4320 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4321 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4323 silc_server_packet_send(server, dest_sock,
4324 SILC_PACKET_COMMAND, cmd->packet->flags,
4325 tmpbuf->data, tmpbuf->len, TRUE);
4327 /* Reprocess this packet after received reply from router */
4328 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
4329 silc_command_get_ident(cmd->payload),
4330 silc_server_command_getkey,
4331 silc_server_command_dup(cmd));
4332 cmd->pending = TRUE;
4333 silc_command_set_ident(cmd->payload, old_ident);
4334 silc_buffer_free(tmpbuf);
4339 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4340 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
4345 /* The client is locally connected, just get the public key and
4346 send it back. If they key does not exist then do not send it,
4347 send just OK reply */
4348 public_key = client->data.public_key;
4353 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
4354 pk = silc_buffer_alloc(4 + tmp_len);
4355 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
4356 silc_buffer_format(pk,
4357 SILC_STR_UI_SHORT(tmp_len),
4358 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
4359 SILC_STR_UI_XNSTRING(tmp, tmp_len),
4365 } else if (id_type == SILC_ID_SERVER) {
4366 server_id = silc_id_payload_get_id(idp);
4368 /* If the server is not found from local list there is no chance it
4369 would be locally connected server so send the command further. */
4370 server_entry = silc_idlist_find_server_by_id(server->local_list,
4371 server_id, TRUE, NULL);
4373 server_entry = silc_idlist_find_server_by_id(server->global_list,
4374 server_id, TRUE, NULL);
4376 if (server_entry != server->id_entry &&
4377 ((!server_entry && !cmd->pending && !server->standalone) ||
4378 (server_entry && !server_entry->connection && !cmd->pending &&
4379 !server->standalone) ||
4380 (server_entry && !server_entry->data.public_key && !cmd->pending &&
4381 !server->standalone))) {
4383 SilcUInt16 old_ident;
4385 old_ident = silc_command_get_ident(cmd->payload);
4386 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4387 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4389 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
4390 SILC_PACKET_COMMAND, cmd->packet->flags,
4391 tmpbuf->data, tmpbuf->len, TRUE);
4393 /* Reprocess this packet after received reply from router */
4394 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
4395 silc_command_get_ident(cmd->payload),
4396 silc_server_command_getkey,
4397 silc_server_command_dup(cmd));
4398 cmd->pending = TRUE;
4399 silc_command_set_ident(cmd->payload, old_ident);
4400 silc_buffer_free(tmpbuf);
4404 if (!server_entry) {
4405 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4406 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
4411 /* If they key does not exist then do not send it, send just OK reply */
4412 public_key = (!server_entry->data.public_key ?
4413 (server_entry == server->id_entry ? server->public_key :
4414 NULL) : server_entry->data.public_key);
4419 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
4420 pk = silc_buffer_alloc(4 + tmp_len);
4421 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
4422 silc_buffer_format(pk,
4423 SILC_STR_UI_SHORT(tmp_len),
4424 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
4425 SILC_STR_UI_XNSTRING(tmp, tmp_len),
4435 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4436 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
4437 SILC_STATUS_OK, 0, ident,
4441 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4442 packet->data, packet->len, FALSE);
4443 silc_buffer_free(packet);
4446 silc_buffer_free(pk);
4450 silc_id_payload_free(idp);
4451 silc_free(client_id);
4452 silc_free(server_id);
4453 silc_server_command_free(cmd);
4457 /* Private range commands, specific to this implementation */
4459 /* Server side command of CONNECT. Connects us to the specified remote
4460 server or router. */
4462 SILC_SERVER_CMD_FUNC(connect)
4464 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4465 SilcServer server = cmd->server;
4466 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4467 unsigned char *tmp, *host;
4469 SilcUInt32 port = SILC_PORT;
4471 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
4474 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
4476 /* Check whether client has the permissions. */
4477 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
4478 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
4479 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
4480 SILC_STATUS_ERR_NO_SERVER_PRIV, 0);
4484 if (server->server_type == SILC_ROUTER && !server->backup_router &&
4485 client->mode & SILC_UMODE_SERVER_OPERATOR) {
4486 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
4487 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
4491 /* Get the remote server */
4492 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4494 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
4495 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4501 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4503 SILC_GET32_MSB(port, tmp);
4505 /* Create the connection. It is done with timeout and is async. */
4506 silc_server_create_connection(server, host, port);
4508 /* Send reply to the sender */
4509 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
4513 silc_server_command_free(cmd);
4516 /* Server side command of CLOSE. Closes connection to a specified server. */
4518 SILC_SERVER_CMD_FUNC(close)
4520 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4521 SilcServer server = cmd->server;
4522 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4523 SilcServerEntry server_entry;
4524 SilcSocketConnection sock;
4527 unsigned char *name;
4528 SilcUInt32 port = SILC_PORT;
4530 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
4533 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
4535 /* Check whether client has the permissions. */
4536 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
4537 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
4538 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
4539 SILC_STATUS_ERR_NO_SERVER_PRIV,
4544 /* Get the remote server */
4545 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4547 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
4548 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4554 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4556 SILC_GET32_MSB(port, tmp);
4558 server_entry = silc_idlist_find_server_by_conn(server->local_list,
4559 name, port, FALSE, NULL);
4561 server_entry = silc_idlist_find_server_by_conn(server->global_list,
4562 name, port, FALSE, NULL);
4563 if (!server_entry) {
4564 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
4565 SILC_STATUS_ERR_NO_SERVER_ID, 0);
4569 if (server_entry == server->id_entry) {
4570 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
4571 SILC_STATUS_ERR_NO_SERVER_ID, 0);
4575 /* Send reply to the sender */
4576 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
4579 /* Close the connection to the server */
4580 sock = (SilcSocketConnection)server_entry->connection;
4582 /* If we shutdown primary router connection manually then don't trigger
4583 any reconnect or backup router connections, by setting the router
4585 if (server->router == server_entry) {
4586 server->id_entry->router = NULL;
4587 server->router = NULL;
4588 server->standalone = TRUE;
4590 silc_server_free_sock_user_data(server, sock, NULL);
4591 silc_server_close_connection(server, sock);
4594 silc_server_command_free(cmd);
4597 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4598 active connections. */
4600 SILC_SERVER_CMD_FUNC(shutdown)
4602 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4603 SilcServer server = cmd->server;
4604 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4606 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
4609 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
4611 /* Check whether client has the permission. */
4612 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
4613 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
4614 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
4615 SILC_STATUS_ERR_NO_SERVER_PRIV,
4620 /* Send reply to the sender */
4621 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
4624 /* Then, gracefully, or not, bring the server down. */
4625 silc_server_stop(server);
4629 silc_server_command_free(cmd);