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_SERVER &&
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 strncat(invite, dest->nickname, strlen(dest->nickname));
1128 strncat(invite, "!", 1);
1129 strncat(invite, dest->username, strlen(dest->username));
1130 if (!strchr(dest->username, '@')) {
1131 strncat(invite, "@", 1);
1132 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
1135 len = strlen(invite);
1136 if (!channel->invite_list)
1137 channel->invite_list = silc_calloc(len + 2,
1138 sizeof(*channel->invite_list));
1140 channel->invite_list = silc_realloc(channel->invite_list,
1141 sizeof(*channel->invite_list) *
1143 strlen(channel->invite_list) + 2));
1144 strncat(channel->invite_list, invite, len);
1145 strncat(channel->invite_list, ",", 1);
1147 if (!(dest->mode & SILC_UMODE_BLOCK_INVITE)) {
1148 /* Send notify to the client that is invited to the channel */
1149 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1150 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1151 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
1153 SILC_NOTIFY_TYPE_INVITE, 3,
1154 idp->data, idp->len,
1155 channel->channel_name,
1156 strlen(channel->channel_name),
1157 idp2->data, idp2->len);
1158 silc_buffer_free(idp);
1159 silc_buffer_free(idp2);
1163 /* Add the client to the invite list of the channel */
1164 add = silc_argument_get_arg_type(cmd->args, 3, &len);
1166 if (!channel->invite_list)
1167 channel->invite_list = silc_calloc(len + 2,
1168 sizeof(*channel->invite_list));
1170 channel->invite_list = silc_realloc(channel->invite_list,
1171 sizeof(*channel->invite_list) *
1173 strlen(channel->invite_list) + 2));
1174 if (add[len - 1] == ',')
1175 add[len - 1] = '\0';
1177 strncat(channel->invite_list, add, len);
1178 strncat(channel->invite_list, ",", 1);
1181 /* Get the invite to be removed and remove it from the list */
1182 del = silc_argument_get_arg_type(cmd->args, 4, &len);
1183 if (del && channel->invite_list) {
1184 char *start, *end, *n;
1186 if (!strncmp(channel->invite_list, del,
1187 strlen(channel->invite_list) - 1)) {
1188 silc_free(channel->invite_list);
1189 channel->invite_list = NULL;
1191 start = strstr(channel->invite_list, del);
1192 if (start && strlen(start) >= len) {
1194 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
1195 strncat(n, channel->invite_list, start - channel->invite_list);
1196 strncat(n, end + 1, ((channel->invite_list +
1197 strlen(channel->invite_list)) - end) - 1);
1198 silc_free(channel->invite_list);
1199 channel->invite_list = n;
1204 /* Send notify to the primary router */
1205 silc_server_send_notify_invite(server, SILC_PRIMARY_ROUTE(server),
1206 SILC_BROADCAST(server), channel,
1207 sender->id, add, del);
1209 /* Send command reply */
1210 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1214 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
1215 SILC_STATUS_OK, 0, ident, 2,
1217 3, channel->invite_list,
1218 channel->invite_list ?
1219 strlen(channel->invite_list) : 0);
1222 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
1223 SILC_STATUS_OK, 0, ident, 1,
1225 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1226 packet->data, packet->len, FALSE);
1227 silc_buffer_free(packet);
1231 silc_free(channel_id);
1232 silc_server_command_free(cmd);
1236 SilcSocketConnection sock;
1240 /* Quits connection to client. This gets called if client won't
1241 close the connection even when it has issued QUIT command. */
1243 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
1245 SilcServer server = app_context;
1246 QuitInternal q = (QuitInternal)context;
1248 /* Free all client specific data, such as client entry and entires
1249 on channels this client may be on. */
1250 silc_server_free_client_data(server, q->sock, q->sock->user_data,
1252 q->sock->user_data = NULL;
1254 /* Close the connection on our side */
1255 silc_server_close_connection(server, q->sock);
1257 silc_socket_free(q->sock);
1258 silc_free(q->signoff);
1262 /* Quits SILC session. This is the normal way to disconnect client. */
1264 SILC_SERVER_CMD_FUNC(quit)
1266 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1267 SilcServer server = cmd->server;
1268 SilcSocketConnection sock = cmd->sock;
1270 unsigned char *tmp = NULL;
1273 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
1275 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1279 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1283 q = silc_calloc(1, sizeof(*q));
1284 q->sock = silc_socket_dup(sock);
1285 q->signoff = tmp ? strdup(tmp) : NULL;
1287 /* We quit the connection with little timeout */
1288 silc_schedule_task_add(server->schedule, sock->sock,
1289 silc_server_command_quit_cb, (void *)q,
1290 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1293 silc_server_command_free(cmd);
1296 /* Server side of command KILL. This command is used by router operator
1297 to remove an client from the SILC Network temporarily. */
1299 SILC_SERVER_CMD_FUNC(kill)
1301 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1302 SilcServer server = cmd->server;
1303 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1304 SilcClientEntry remote_client;
1305 SilcClientID *client_id;
1306 unsigned char *tmp, *comment;
1307 SilcUInt32 tmp_len, tmp_len2;
1310 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
1312 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
1315 /* KILL command works only on router */
1316 if (server->server_type != SILC_ROUTER) {
1317 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1318 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
1322 /* Check whether client has the permissions. */
1323 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
1324 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1325 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
1329 /* Get the client ID */
1330 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1332 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1333 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1337 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1339 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1340 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1345 /* Get the client entry */
1346 remote_client = silc_idlist_find_client_by_id(server->local_list,
1347 client_id, TRUE, NULL);
1349 if (!remote_client) {
1350 remote_client = silc_idlist_find_client_by_id(server->global_list,
1351 client_id, TRUE, NULL);
1353 if (!remote_client) {
1354 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1355 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1362 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
1366 /* Send reply to the sender */
1367 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1370 /* Check if anyone is watching this nickname */
1371 if (server->server_type == SILC_ROUTER)
1372 silc_server_check_watcher_list(server, client, NULL,
1373 SILC_NOTIFY_TYPE_KILLED);
1375 /* Now do the killing */
1376 silc_server_kill_client(server, remote_client, comment, client->id,
1380 silc_server_command_free(cmd);
1383 /* Server side of command INFO. This sends information about us to
1384 the client. If client requested specific server we will send the
1385 command to that server. */
1387 SILC_SERVER_CMD_FUNC(info)
1389 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1390 SilcServer server = cmd->server;
1391 SilcBuffer packet, idp;
1394 char *dest_server, *server_info = NULL, *server_name;
1395 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1396 SilcServerEntry entry = NULL;
1397 SilcServerID *server_id = NULL;
1399 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
1401 /* Get server name */
1402 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1405 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1407 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1409 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1410 SILC_STATUS_ERR_NO_SERVER_ID, 0);
1416 /* Check whether we have this server cached */
1417 entry = silc_idlist_find_server_by_id(server->local_list,
1418 server_id, TRUE, NULL);
1420 entry = silc_idlist_find_server_by_id(server->global_list,
1421 server_id, TRUE, NULL);
1422 if (!entry && server->server_type != SILC_SERVER) {
1423 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1424 SILC_STATUS_ERR_NO_SUCH_SERVER,
1431 /* Some buggy servers has sent request to router about themselves. */
1432 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
1435 if ((!dest_server && !server_id && !entry) || (entry &&
1436 entry == server->id_entry) ||
1437 (dest_server && !cmd->pending &&
1438 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
1439 /* Send our reply */
1440 char info_string[256];
1442 memset(info_string, 0, sizeof(info_string));
1443 snprintf(info_string, sizeof(info_string),
1444 "location: %s server: %s admin: %s <%s>",
1445 server->config->server_info->location,
1446 server->config->server_info->server_type,
1447 server->config->server_info->admin,
1448 server->config->server_info->email);
1450 server_info = info_string;
1451 entry = server->id_entry;
1453 /* Check whether we have this server cached */
1454 if (!entry && dest_server) {
1455 entry = silc_idlist_find_server_by_name(server->global_list,
1456 dest_server, TRUE, NULL);
1458 entry = silc_idlist_find_server_by_name(server->local_list,
1459 dest_server, TRUE, NULL);
1463 if (!cmd->pending &&
1464 server->server_type != SILC_SERVER && entry && !entry->server_info) {
1465 /* Send to the server */
1467 SilcUInt16 old_ident;
1469 old_ident = silc_command_get_ident(cmd->payload);
1470 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1471 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1473 silc_server_packet_send(server, entry->connection,
1474 SILC_PACKET_COMMAND, cmd->packet->flags,
1475 tmpbuf->data, tmpbuf->len, TRUE);
1477 /* Reprocess this packet after received reply from router */
1478 silc_server_command_pending(server, SILC_COMMAND_INFO,
1479 silc_command_get_ident(cmd->payload),
1480 silc_server_command_info,
1481 silc_server_command_dup(cmd));
1482 cmd->pending = TRUE;
1483 silc_command_set_ident(cmd->payload, old_ident);
1484 silc_buffer_free(tmpbuf);
1488 if (!entry && !cmd->pending && !server->standalone) {
1489 /* Send to the primary router */
1491 SilcUInt16 old_ident;
1493 old_ident = silc_command_get_ident(cmd->payload);
1494 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1495 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1497 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
1498 SILC_PACKET_COMMAND, cmd->packet->flags,
1499 tmpbuf->data, tmpbuf->len, TRUE);
1501 /* Reprocess this packet after received reply from router */
1502 silc_server_command_pending(server, SILC_COMMAND_INFO,
1503 silc_command_get_ident(cmd->payload),
1504 silc_server_command_info,
1505 silc_server_command_dup(cmd));
1506 cmd->pending = TRUE;
1507 silc_command_set_ident(cmd->payload, old_ident);
1508 silc_buffer_free(tmpbuf);
1513 silc_free(server_id);
1516 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1517 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
1521 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1523 server_info = entry->server_info;
1524 server_name = entry->server_name;
1526 /* Send the reply */
1527 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
1528 SILC_STATUS_OK, 0, ident, 3,
1529 2, idp->data, idp->len,
1531 strlen(server_name),
1534 strlen(server_info) : 0);
1535 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1536 packet->data, packet->len, FALSE);
1538 silc_buffer_free(packet);
1539 silc_buffer_free(idp);
1542 silc_server_command_free(cmd);
1545 /* Server side of command PING. This just replies to the ping. */
1547 SILC_SERVER_CMD_FUNC(ping)
1549 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1550 SilcServer server = cmd->server;
1555 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
1558 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1560 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1561 SILC_STATUS_ERR_NO_SERVER_ID, 0);
1564 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
1568 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
1569 /* Send our reply */
1570 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1573 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1574 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
1581 silc_server_command_free(cmd);
1584 /* Server side of command STATS. */
1586 SILC_SERVER_CMD_FUNC(stats)
1588 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1589 SilcServer server = cmd->server;
1590 SilcServerID *server_id;
1593 SilcBuffer packet, stats;
1594 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1597 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1);
1600 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1602 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1603 SILC_STATUS_ERR_NO_SERVER_ID, 0);
1606 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1610 /* The ID must be ours */
1611 if (!SILC_ID_SERVER_COMPARE(server->id, server_id)) {
1612 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1613 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
1614 silc_free(server_id);
1617 silc_free(server_id);
1619 /* If we are router then just send everything we got. If we are normal
1620 server then we'll send this to our router to get all the latest
1621 statistical information. */
1622 if (!cmd->pending && server->server_type != SILC_ROUTER &&
1623 !server->standalone) {
1624 /* Send request to our router */
1625 SilcBuffer idp = silc_id_payload_encode(server->router->id,
1627 packet = silc_command_payload_encode_va(SILC_COMMAND_STATS,
1628 ++server->cmd_ident, 1,
1629 1, idp->data, idp->len);
1630 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
1631 SILC_PACKET_COMMAND, 0, packet->data,
1632 packet->len, FALSE);
1634 /* Reprocess this packet after received reply from router */
1635 silc_server_command_pending(server, SILC_COMMAND_STATS,
1637 silc_server_command_stats,
1638 silc_server_command_dup(cmd));
1639 cmd->pending = TRUE;
1640 silc_buffer_free(packet);
1641 silc_buffer_free(idp);
1645 /* Send our reply to sender */
1646 uptime = time(NULL) - server->starttime;
1648 stats = silc_buffer_alloc_size(60);
1649 silc_buffer_format(stats,
1650 SILC_STR_UI_INT(server->starttime),
1651 SILC_STR_UI_INT(uptime),
1652 SILC_STR_UI_INT(server->stat.my_clients),
1653 SILC_STR_UI_INT(server->stat.my_channels),
1654 SILC_STR_UI_INT(server->stat.my_server_ops),
1655 SILC_STR_UI_INT(server->stat.my_router_ops),
1656 SILC_STR_UI_INT(server->stat.cell_clients),
1657 SILC_STR_UI_INT(server->stat.cell_channels),
1658 SILC_STR_UI_INT(server->stat.cell_servers),
1659 SILC_STR_UI_INT(server->stat.clients),
1660 SILC_STR_UI_INT(server->stat.channels),
1661 SILC_STR_UI_INT(server->stat.servers),
1662 SILC_STR_UI_INT(server->stat.routers),
1663 SILC_STR_UI_INT(server->stat.server_ops),
1664 SILC_STR_UI_INT(server->stat.router_ops),
1667 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_STATS,
1668 SILC_STATUS_OK, 0, ident, 2,
1670 3, stats->data, stats->len);
1671 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1672 0, packet->data, packet->len, FALSE);
1673 silc_buffer_free(packet);
1674 silc_buffer_free(stats);
1677 silc_server_command_free(cmd);
1680 /* Internal routine to join channel. The channel sent to this function
1681 has been either created or resolved from ID lists. This joins the sent
1682 client to the channel. */
1684 static void silc_server_command_join_channel(SilcServer server,
1685 SilcServerCommandContext cmd,
1686 SilcChannelEntry channel,
1687 SilcClientID *client_id,
1691 const unsigned char *auth,
1692 SilcUInt32 auth_len)
1694 SilcSocketConnection sock = cmd->sock;
1696 SilcUInt32 tmp_len, user_count;
1697 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
1698 SilcClientEntry client;
1699 SilcChannelClientEntry chl;
1700 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
1701 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1702 char check[512], check2[512];
1703 bool founder = FALSE;
1705 unsigned char *fkey = NULL;
1706 SilcUInt32 fkey_len = 0;
1708 SILC_LOG_DEBUG(("Joining client to channel"));
1713 /* Get the client entry */
1714 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1715 client = (SilcClientEntry)sock->user_data;
1719 client = silc_server_query_client(server, client_id, FALSE,
1726 silc_server_command_send_status_reply(
1727 cmd, SILC_COMMAND_JOIN,
1728 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
1732 /* The client info is being resolved. Reprocess this packet after
1733 receiving the reply to the query. */
1734 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1736 silc_server_command_join,
1737 silc_server_command_dup(cmd));
1738 cmd->pending = TRUE;
1742 cmd->pending = FALSE;
1746 * Check founder auth payload if provided. If client can gain founder
1747 * privileges it can override various conditions on joining the channel,
1748 * and can have directly the founder mode set on the channel.
1750 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1751 SilcIDListData idata = (SilcIDListData)client;
1752 SilcChannelClientEntry chl2;
1753 SilcHashTableList htl;
1755 if (channel->founder_key && idata->public_key &&
1756 silc_pkcs_public_key_compare(channel->founder_key,
1757 idata->public_key)) {
1758 /* Check whether the client is to become founder */
1759 if (silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
1760 channel->founder_key, 0, server->sha1hash,
1761 client->id, SILC_ID_CLIENT)) {
1763 /* There cannot be anyone else as founder on the channel now. This
1764 client is definitely the founder due to this authentication */
1765 silc_hash_table_list(channel->user_list, &htl);
1766 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
1767 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
1768 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
1769 silc_server_force_cumode_change(server, NULL, channel, chl2,
1773 silc_hash_table_list_reset(&htl);
1775 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
1782 * Check channel modes
1786 memset(check, 0, sizeof(check));
1787 memset(check2, 0, sizeof(check2));
1788 strncat(check, client->nickname, strlen(client->nickname));
1789 strncat(check, "!", 1);
1790 strncat(check, client->username, strlen(client->username));
1791 if (!strchr(client->username, '@')) {
1792 strncat(check, "@", 1);
1793 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
1796 strncat(check2, client->nickname, strlen(client->nickname));
1797 if (!strchr(client->nickname, '@')) {
1798 strncat(check2, "@", 1);
1799 strncat(check2, server->server_name, strlen(server->server_name));
1801 strncat(check2, "!", 1);
1802 strncat(check2, client->username, strlen(client->username));
1803 if (!strchr(client->username, '@')) {
1804 strncat(check2, "@", 1);
1805 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
1808 /* Check invite list if channel is invite-only channel */
1809 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1810 if (!channel->invite_list ||
1811 (!silc_string_match(channel->invite_list, check) &&
1812 !silc_string_match(channel->invite_list, check2))) {
1813 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1814 SILC_STATUS_ERR_NOT_INVITED, 0);
1819 /* Check ban list if it exists. If the client's nickname, server,
1820 username and/or hostname is in the ban list the access to the
1821 channel is denied. */
1822 if (channel->ban_list) {
1823 if (silc_string_match(channel->ban_list, check) ||
1824 silc_string_match(channel->ban_list, check2)) {
1825 silc_server_command_send_status_reply(
1826 cmd, SILC_COMMAND_JOIN,
1827 SILC_STATUS_ERR_BANNED_FROM_CHANNEL, 0);
1832 /* Check user count limit if set. */
1833 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
1834 if (silc_hash_table_count(channel->user_list) + 1 >
1835 channel->user_limit) {
1836 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1837 SILC_STATUS_ERR_CHANNEL_IS_FULL,
1844 /* Check the channel passphrase if set. */
1845 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1846 /* Get passphrase */
1847 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1849 passphrase = silc_memdup(tmp, tmp_len);
1851 if (!passphrase || !channel->passphrase ||
1852 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
1853 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1854 SILC_STATUS_ERR_BAD_PASSWORD, 0);
1860 * Client is allowed to join to the channel. Make it happen.
1863 /* Check whether the client already is on the channel */
1864 if (silc_server_client_on_channel(client, channel, NULL)) {
1865 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1866 SILC_STATUS_ERR_USER_ON_CHANNEL, 0);
1870 /* Generate new channel key as protocol dictates */
1872 if (!silc_server_create_channel_key(server, channel, 0))
1875 /* Send the channel key. This is broadcasted to the channel but is not
1876 sent to the client who is joining to the channel. */
1877 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
1878 silc_server_send_channel_key(server, NULL, channel,
1879 server->server_type == SILC_ROUTER ?
1880 FALSE : !server->standalone);
1883 /* Join the client to the channel by adding it to channel's user list.
1884 Add also the channel to client entry's channels list for fast cross-
1886 chl = silc_calloc(1, sizeof(*chl));
1888 chl->client = client;
1889 chl->channel = channel;
1890 silc_hash_table_add(channel->user_list, client, chl);
1891 silc_hash_table_add(client->channels, channel, chl);
1892 channel->user_count++;
1893 channel->disabled = FALSE;
1895 /* Get users on the channel */
1896 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
1899 /* Encode Client ID Payload of the original client who wants to join */
1900 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1902 /* Encode command reply packet */
1903 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1904 SILC_PUT32_MSB(channel->mode, mode);
1905 SILC_PUT32_MSB(created, tmp2);
1906 SILC_PUT32_MSB(user_count, tmp3);
1908 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
1909 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1910 keyp = silc_channel_key_payload_encode(silc_id_get_len(channel->id,
1913 strlen(channel->channel_key->
1915 channel->channel_key->cipher->name,
1916 channel->key_len / 8, channel->key);
1920 if (channel->founder_key)
1921 fkey = silc_pkcs_public_key_encode(channel->founder_key, &fkey_len);
1924 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1925 SILC_STATUS_OK, 0, ident, 14,
1926 2, channel->channel_name,
1927 strlen(channel->channel_name),
1928 3, chidp->data, chidp->len,
1929 4, clidp->data, clidp->len,
1932 7, keyp ? keyp->data : NULL,
1933 keyp ? keyp->len : 0,
1934 8, channel->ban_list,
1936 strlen(channel->ban_list) : 0,
1937 9, channel->invite_list,
1938 channel->invite_list ?
1939 strlen(channel->invite_list) : 0,
1942 strlen(channel->topic) : 0,
1943 11, silc_hmac_get_name(channel->hmac),
1944 strlen(silc_hmac_get_name(channel->
1947 13, user_list->data, user_list->len,
1948 14, mode_list->data,
1950 15, fkey, fkey_len);
1952 /* Send command reply */
1953 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
1954 reply->data, reply->len, FALSE);
1956 /* Send JOIN notify to locally connected clients on the channel. If
1957 we are normal server then router will send or have sent JOIN notify
1958 already. However since we've added the client already to our channel
1959 we'll ignore it (in packet_receive.c) so we must send it here. If
1960 we are router then this will send it to local clients and local
1962 SILC_LOG_DEBUG(("Send JOIN notify to channel"));
1963 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
1964 SILC_NOTIFY_TYPE_JOIN, 2,
1965 clidp->data, clidp->len,
1966 chidp->data, chidp->len);
1968 /* Update statistics */
1969 server->stat.my_chanclients++;
1970 if (server->server_type == SILC_ROUTER) {
1971 server->stat.cell_chanclients++;
1972 server->stat.chanclients++;
1975 if (!cmd->pending) {
1976 /* Send JOIN notify packet to our primary router */
1977 silc_server_send_notify_join(server, SILC_PRIMARY_ROUTE(server),
1978 SILC_BROADCAST(server), channel, client->id);
1981 /* Distribute the channel key to all backup routers. */
1982 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
1983 keyp->data, keyp->len, FALSE, TRUE);
1985 /* If client became founder by providing correct founder auth data
1986 notify the mode change to the channel. */
1988 SILC_PUT32_MSB(chl->mode, mode);
1989 SILC_LOG_DEBUG(("Send CUMODE_CHANGE notify to channel"));
1990 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
1991 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
1992 clidp->data, clidp->len,
1993 mode, 4, clidp->data, clidp->len,
1998 /* Set CUMODE notify type to network */
2000 silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
2001 SILC_BROADCAST(server), channel,
2002 chl->mode, client->id, SILC_ID_CLIENT,
2003 client->id, channel->founder_key);
2005 silc_buffer_free(reply);
2006 silc_buffer_free(clidp);
2007 silc_buffer_free(chidp);
2008 silc_buffer_free(keyp);
2009 silc_buffer_free(user_list);
2010 silc_buffer_free(mode_list);
2014 silc_free(passphrase);
2017 /* Server side of command JOIN. Joins client into requested channel. If
2018 the channel does not exist it will be created. */
2020 SILC_SERVER_CMD_FUNC(join)
2022 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2023 SilcServer server = cmd->server;
2024 unsigned char *auth;
2025 SilcUInt32 tmp_len, auth_len;
2026 char *tmp, *channel_name = NULL, *cipher, *hmac;
2027 SilcChannelEntry channel;
2028 SilcUInt32 umode = 0;
2029 bool created = FALSE, create_key = TRUE;
2030 SilcClientID *client_id;
2032 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
2034 /* Get channel name */
2035 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2037 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2038 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2045 channel_name[255] = '\0';
2047 if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
2048 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2049 SILC_STATUS_ERR_BAD_CHANNEL, 0);
2053 /* Get Client ID of the client who is joining to the channel */
2054 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2056 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2057 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2061 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2063 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2064 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2069 /* Get cipher, hmac name and auth payload */
2070 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2071 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2072 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
2074 /* See if the channel exists */
2075 channel = silc_idlist_find_channel_by_name(server->local_list,
2076 channel_name, NULL);
2078 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2079 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2081 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2082 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2087 silc_free(client_id);
2088 client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
2091 (channel->disabled && server->server_type != SILC_ROUTER)) {
2092 /* Channel not found or not valid */
2094 /* If we are standalone server we don't have a router, we just create
2095 the channel by ourselves (unless it existed). */
2096 if (server->standalone) {
2098 channel = silc_server_create_new_channel(server, server->id, cipher,
2099 hmac, channel_name, TRUE);
2101 silc_server_command_send_status_reply(
2102 cmd, SILC_COMMAND_JOIN,
2103 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
2105 silc_free(client_id);
2109 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2115 /* The channel does not exist on our server. If we are normal server
2116 we will send JOIN command to our router which will handle the
2117 joining procedure (either creates the channel if it doesn't exist
2118 or joins the client to it). */
2119 if (server->server_type != SILC_ROUTER) {
2121 SilcUInt16 old_ident;
2123 /* If this is pending command callback then we've resolved
2124 it and it didn't work, return since we've notified the
2125 client already in the command reply callback. */
2127 silc_free(client_id);
2131 old_ident = silc_command_get_ident(cmd->payload);
2132 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2133 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2135 /* Send JOIN command to our router */
2136 silc_server_packet_send(server, (SilcSocketConnection)
2137 SILC_PRIMARY_ROUTE(server),
2138 SILC_PACKET_COMMAND, cmd->packet->flags,
2139 tmpbuf->data, tmpbuf->len, TRUE);
2141 /* Reprocess this packet after received reply from router */
2142 silc_server_command_pending(server, SILC_COMMAND_JOIN,
2143 silc_command_get_ident(cmd->payload),
2144 silc_server_command_join,
2145 silc_server_command_dup(cmd));
2146 cmd->pending = TRUE;
2147 silc_command_set_ident(cmd->payload, old_ident);
2148 silc_buffer_free(tmpbuf);
2149 silc_free(client_id);
2153 /* We are router and the channel does not seem exist so we will check
2154 our global list as well for the channel. */
2155 channel = silc_idlist_find_channel_by_name(server->global_list,
2156 channel_name, NULL);
2158 /* Channel really does not exist, create it */
2159 channel = silc_server_create_new_channel(server, server->id, cipher,
2160 hmac, channel_name, TRUE);
2162 silc_server_command_send_status_reply(
2163 cmd, SILC_COMMAND_JOIN,
2164 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
2165 silc_free(client_id);
2169 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2177 /* Channel not found */
2179 /* If the command came from router and we are normal server then
2180 something went wrong with the joining as the channel was not found.
2181 We can't do anything else but ignore this. */
2182 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
2183 server->server_type != SILC_ROUTER) {
2184 silc_free(client_id);
2188 /* We are router and the channel does not seem exist so we will check
2189 our global list as well for the channel. */
2190 channel = silc_idlist_find_channel_by_name(server->global_list,
2191 channel_name, NULL);
2193 /* Channel really does not exist, create it */
2194 channel = silc_server_create_new_channel(server, server->id, cipher,
2195 hmac, channel_name, TRUE);
2197 silc_server_command_send_status_reply(
2198 cmd, SILC_COMMAND_JOIN,
2199 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
2200 silc_free(client_id);
2204 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2211 /* Check whether the channel was created by our router */
2212 if (cmd->pending && context2) {
2213 SilcServerCommandReplyContext reply = context2;
2215 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
2216 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
2217 SILC_GET32_MSB(created, tmp);
2218 if (silc_argument_get_arg_type(reply->args, 7, NULL))
2219 create_key = FALSE; /* Router returned the key already */
2221 if (silc_command_get_status(reply->payload, NULL, NULL) &&
2222 channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2223 /* Save channel passphrase, if user provided it successfully */
2226 pa = silc_argument_get_arg_type(cmd->args, 3, &pa_len);
2228 silc_free(channel->passphrase);
2229 channel->passphrase = silc_memdup(pa, pa_len);
2234 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
2235 !channel->disabled && !silc_hash_table_count(channel->user_list))
2239 /* If the channel does not have global users and is also empty the client
2240 will be the channel founder and operator. */
2241 if (!channel->disabled &&
2242 !channel->global_users && !silc_hash_table_count(channel->user_list))
2243 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2245 /* Join to the channel */
2246 silc_server_command_join_channel(server, cmd, channel, client_id,
2247 created, create_key, umode,
2250 silc_free(client_id);
2253 silc_server_command_free(cmd);
2256 /* Server side of command MOTD. Sends server's current "message of the
2257 day" to the client. */
2259 SILC_SERVER_CMD_FUNC(motd)
2261 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2262 SilcServer server = cmd->server;
2263 SilcBuffer packet, idp;
2264 char *motd, *dest_server;
2265 SilcUInt32 motd_len;
2266 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2268 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
2270 /* Get server name */
2271 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2273 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2274 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
2278 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
2281 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
2283 if (server->config && server->config->server_info &&
2284 server->config->server_info->motd_file) {
2286 motd = silc_file_readfile(server->config->server_info->motd_file,
2292 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
2299 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
2305 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2306 packet->data, packet->len, FALSE);
2307 silc_buffer_free(packet);
2308 silc_buffer_free(idp);
2310 SilcServerEntry entry;
2312 /* Check whether we have this server cached */
2313 entry = silc_idlist_find_server_by_name(server->global_list,
2314 dest_server, TRUE, NULL);
2316 entry = silc_idlist_find_server_by_name(server->local_list,
2317 dest_server, TRUE, NULL);
2320 if (server->server_type != SILC_SERVER && !cmd->pending &&
2321 entry && !entry->motd) {
2322 /* Send to the server */
2324 SilcUInt16 old_ident;
2326 old_ident = silc_command_get_ident(cmd->payload);
2327 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2328 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2330 silc_server_packet_send(server, entry->connection,
2331 SILC_PACKET_COMMAND, cmd->packet->flags,
2332 tmpbuf->data, tmpbuf->len, TRUE);
2334 /* Reprocess this packet after received reply from router */
2335 silc_server_command_pending(server, SILC_COMMAND_MOTD,
2336 silc_command_get_ident(cmd->payload),
2337 silc_server_command_motd,
2338 silc_server_command_dup(cmd));
2339 cmd->pending = TRUE;
2340 silc_command_set_ident(cmd->payload, old_ident);
2341 silc_buffer_free(tmpbuf);
2345 if (!entry && !cmd->pending && !server->standalone) {
2346 /* Send to the primary router */
2348 SilcUInt16 old_ident;
2350 old_ident = silc_command_get_ident(cmd->payload);
2351 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2352 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2354 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
2355 SILC_PACKET_COMMAND, cmd->packet->flags,
2356 tmpbuf->data, tmpbuf->len, TRUE);
2358 /* Reprocess this packet after received reply from router */
2359 silc_server_command_pending(server, SILC_COMMAND_MOTD,
2360 silc_command_get_ident(cmd->payload),
2361 silc_server_command_motd,
2362 silc_server_command_dup(cmd));
2363 cmd->pending = TRUE;
2364 silc_command_set_ident(cmd->payload, old_ident);
2365 silc_buffer_free(tmpbuf);
2370 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2371 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
2375 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
2376 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
2377 SILC_STATUS_OK, 0, ident, 2,
2381 strlen(entry->motd) : 0);
2382 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2383 packet->data, packet->len, FALSE);
2384 silc_buffer_free(packet);
2385 silc_buffer_free(idp);
2389 silc_server_command_free(cmd);
2392 /* Server side of command UMODE. Client can use this command to set/unset
2393 user mode. Client actually cannot set itself to be as server/router
2394 operator so this can be used only to unset the modes. */
2396 SILC_SERVER_CMD_FUNC(umode)
2398 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2399 SilcServer server = cmd->server;
2400 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2402 unsigned char *tmp_mask, m[4];
2403 SilcUInt32 mask = 0;
2404 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2405 bool set_mask = FALSE;
2407 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
2410 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2);
2412 /* Get the client's mode mask */
2413 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2415 SILC_GET32_MSB(mask, tmp_mask);
2420 /* Check that mode changing is allowed. */
2421 if (!silc_server_check_umode_rights(server, client, mask)) {
2422 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2423 SILC_STATUS_ERR_PERM_DENIED, 0);
2427 /* Anonymous mode cannot be set by client */
2428 if (mask & SILC_UMODE_ANONYMOUS) {
2429 if (!(client->mode & SILC_UMODE_ANONYMOUS)) {
2430 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2431 SILC_STATUS_ERR_PERM_DENIED, 0);
2435 if (client->mode & SILC_UMODE_ANONYMOUS) {
2436 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2437 SILC_STATUS_ERR_PERM_DENIED, 0);
2442 /* Update statistics */
2443 if (mask & SILC_UMODE_GONE) {
2444 if (!(client->mode & SILC_UMODE_GONE))
2445 server->stat.my_aways++;
2447 if (client->mode & SILC_UMODE_GONE)
2448 server->stat.my_aways--;
2451 /* Change the mode */
2452 client->mode = mask;
2454 /* Send UMODE change to primary router */
2455 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
2456 SILC_BROADCAST(server), client->id,
2459 /* Check if anyone is watching this nickname */
2460 if (server->server_type == SILC_ROUTER)
2461 silc_server_check_watcher_list(server, client, NULL,
2462 SILC_NOTIFY_TYPE_UMODE_CHANGE);
2465 /* Send command reply to sender */
2466 SILC_PUT32_MSB(client->mode, m);
2467 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
2468 SILC_STATUS_OK, 0, ident, 1,
2470 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2471 packet->data, packet->len, FALSE);
2472 silc_buffer_free(packet);
2475 silc_server_command_free(cmd);
2478 /* Server side command of CMODE. Changes channel mode */
2480 SILC_SERVER_CMD_FUNC(cmode)
2482 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2483 SilcServer server = cmd->server;
2484 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2485 SilcIDListData idata = (SilcIDListData)client;
2486 SilcChannelID *channel_id = NULL;
2487 SilcChannelEntry channel;
2488 SilcChannelClientEntry chl;
2489 SilcBuffer packet, cidp;
2490 unsigned char *tmp, *tmp_id, *tmp_mask;
2491 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
2492 SilcUInt32 mode_mask = 0, old_mask = 0, tmp_len, tmp_len2;
2493 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2494 bool set_mask = FALSE;
2495 SilcPublicKey founder_key = NULL;
2496 unsigned char *fkey = NULL;
2497 SilcUInt32 fkey_len = 0;
2500 silc_server_command_free(cmd);
2504 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 7);
2506 /* Get Channel ID */
2507 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2509 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2510 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2511 silc_server_command_free(cmd);
2514 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
2516 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2517 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2518 silc_server_command_free(cmd);
2522 /* Get channel entry */
2523 channel = silc_idlist_find_channel_by_id(server->local_list,
2526 channel = silc_idlist_find_channel_by_id(server->global_list,
2529 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2530 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
2532 silc_free(channel_id);
2533 silc_server_command_free(cmd);
2537 old_mask = channel->mode;
2539 /* Get the channel mode mask */
2540 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2542 SILC_GET32_MSB(mode_mask, tmp_mask);
2546 /* Check whether this client is on the channel */
2547 if (!silc_server_client_on_channel(client, channel, &chl)) {
2548 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2549 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
2553 /* Check that client has rights to change any requested channel modes */
2554 if (set_mask && !silc_server_check_cmode_rights(server, channel, chl,
2556 SILC_LOG_DEBUG(("Client does not have rights to change mode"));
2557 silc_server_command_send_status_reply(
2558 cmd, SILC_COMMAND_CMODE,
2559 (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) ?
2560 SILC_STATUS_ERR_NO_CHANNEL_PRIV :
2561 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV), 0);
2565 /* If mode mask was not sent as argument then merely return the current
2566 mode mask to the sender. */
2569 SILC_PUT32_MSB(channel->mode, m);
2570 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2571 SILC_STATUS_OK, 0, ident, 2,
2572 2, tmp_id, tmp_len2,
2574 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2575 packet->data, packet->len, FALSE);
2576 silc_buffer_free(packet);
2581 * Check the modes. Modes that requires nothing special operation are
2585 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2586 /* Channel uses private keys to protect traffic. Client(s) has set the
2587 key locally they want to use, server does not know that key. */
2588 /* Nothing interesting to do here */
2590 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2591 /* The mode is removed and we need to generate and distribute
2592 new channel key. Clients are not using private channel keys
2593 anymore after this. */
2595 /* Re-generate channel key */
2596 if (!silc_server_create_channel_key(server, channel, 0))
2599 /* Send the channel key. This sends it to our local clients and if
2600 we are normal server to our router as well. */
2601 silc_server_send_channel_key(server, NULL, channel,
2602 server->server_type == SILC_ROUTER ?
2603 FALSE : !server->standalone);
2605 cipher = channel->channel_key->cipher->name;
2606 hmac = (char *)silc_hmac_get_name(channel->hmac);
2610 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2611 /* User limit is set on channel */
2612 SilcUInt32 user_limit;
2614 /* Get user limit */
2615 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2617 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2618 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2619 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
2623 SILC_GET32_MSB(user_limit, tmp);
2624 channel->user_limit = user_limit;
2627 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2628 /* User limit mode is unset. Remove user limit */
2629 channel->user_limit = 0;
2632 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
2633 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
2634 /* Passphrase has been set to channel */
2636 /* Get the passphrase */
2637 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
2639 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2640 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
2644 /* Save the passphrase */
2645 passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
2648 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2649 /* Passphrase mode is unset. remove the passphrase */
2650 silc_free(channel->passphrase);
2651 channel->passphrase = NULL;
2655 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
2656 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
2657 /* Cipher to use protect the traffic */
2658 SilcCipher newkey, oldkey;
2661 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
2663 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2664 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
2668 /* Delete old cipher and allocate the new one */
2669 if (!silc_cipher_alloc(cipher, &newkey)) {
2670 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2671 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
2675 oldkey = channel->channel_key;
2676 channel->channel_key = newkey;
2678 /* Re-generate channel key */
2679 if (!silc_server_create_channel_key(server, channel, 0)) {
2680 /* We don't have new key, revert to old one */
2681 channel->channel_key = oldkey;
2685 /* Remove old channel key for good */
2686 silc_cipher_free(oldkey);
2688 /* Send the channel key. This sends it to our local clients and if
2689 we are normal server to our router as well. */
2690 silc_server_send_channel_key(server, NULL, channel,
2691 server->server_type == SILC_ROUTER ?
2692 FALSE : !server->standalone);
2695 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2696 /* Cipher mode is unset. Remove the cipher and revert back to
2698 SilcCipher newkey, oldkey;
2699 cipher = channel->cipher;
2701 /* Delete old cipher and allocate default one */
2702 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
2703 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2704 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
2708 oldkey = channel->channel_key;
2709 channel->channel_key = newkey;
2711 /* Re-generate channel key */
2712 if (!silc_server_create_channel_key(server, channel, 0)) {
2713 /* We don't have new key, revert to old one */
2714 channel->channel_key = oldkey;
2718 /* Remove old channel key for good */
2719 silc_cipher_free(oldkey);
2721 /* Send the channel key. This sends it to our local clients and if
2722 we are normal server to our router as well. */
2723 silc_server_send_channel_key(server, NULL, channel,
2724 server->server_type == SILC_ROUTER ?
2725 FALSE : !server->standalone);
2729 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
2730 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
2731 /* HMAC to use protect the traffic */
2732 unsigned char hash[32];
2736 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
2738 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2739 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
2743 /* Delete old hmac and allocate the new one */
2744 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
2745 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2746 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
2750 silc_hmac_free(channel->hmac);
2751 channel->hmac = newhmac;
2753 /* Set the HMAC key out of current channel key. The client must do
2755 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
2756 channel->key_len / 8, hash);
2757 silc_hmac_set_key(channel->hmac, hash,
2758 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
2759 memset(hash, 0, sizeof(hash));
2762 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
2763 /* Hmac mode is unset. Remove the hmac and revert back to
2766 unsigned char hash[32];
2767 hmac = channel->hmac_name;
2769 /* Delete old hmac and allocate default one */
2770 silc_hmac_free(channel->hmac);
2771 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
2772 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2773 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
2777 silc_hmac_free(channel->hmac);
2778 channel->hmac = newhmac;
2780 /* Set the HMAC key out of current channel key. The client must do
2782 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
2783 channel->key_len / 8,
2785 silc_hmac_set_key(channel->hmac, hash,
2786 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
2787 memset(hash, 0, sizeof(hash));
2791 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
2792 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2793 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
2794 /* Set the founder authentication */
2795 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
2797 silc_server_command_send_status_reply(
2798 cmd, SILC_COMMAND_CMODE,
2799 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
2803 /* Verify the payload before setting the mode */
2804 if (!silc_auth_verify_data(tmp, tmp_len, SILC_AUTH_PUBLIC_KEY,
2805 idata->public_key, 0, server->sha1hash,
2806 client->id, SILC_ID_CLIENT)) {
2807 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2808 SILC_STATUS_ERR_AUTH_FAILED,
2813 /* Save the public key */
2814 channel->founder_key = silc_pkcs_public_key_copy(idata->public_key);
2815 if (!channel->founder_key) {
2816 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2817 SILC_STATUS_ERR_AUTH_FAILED,
2822 founder_key = channel->founder_key;
2823 fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
2825 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2826 SILC_STATUS_ERR_AUTH_FAILED,
2828 silc_pkcs_public_key_free(channel->founder_key);
2829 channel->founder_key = NULL;
2835 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2836 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
2837 if (channel->founder_key)
2838 silc_pkcs_public_key_free(channel->founder_key);
2839 channel->founder_key = NULL;
2844 /* Finally, set the mode */
2845 old_mask = channel->mode = mode_mask;
2847 /* Send CMODE_CHANGE notify. */
2848 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2849 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2850 SILC_NOTIFY_TYPE_CMODE_CHANGE, 6,
2851 cidp->data, cidp->len,
2853 cipher, cipher ? strlen(cipher) : 0,
2854 hmac, hmac ? strlen(hmac) : 0,
2855 passphrase, passphrase ?
2856 strlen(passphrase) : 0,
2859 /* Set CMODE notify type to network */
2860 silc_server_send_notify_cmode(server, SILC_PRIMARY_ROUTE(server),
2861 SILC_BROADCAST(server), channel,
2862 mode_mask, client->id, SILC_ID_CLIENT,
2863 cipher, hmac, passphrase, founder_key);
2865 /* Send command reply to sender */
2866 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2867 SILC_STATUS_OK, 0, ident, 2,
2868 2, tmp_id, tmp_len2,
2870 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2871 packet->data, packet->len, FALSE);
2873 silc_buffer_free(packet);
2874 silc_buffer_free(cidp);
2877 channel->mode = old_mask;
2879 silc_free(channel_id);
2880 silc_server_command_free(cmd);
2883 /* Server side of CUMODE command. Changes client's mode on a channel. */
2885 SILC_SERVER_CMD_FUNC(cumode)
2887 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2888 SilcServer server = cmd->server;
2889 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2890 SilcIDListData idata = (SilcIDListData)client;
2891 SilcChannelID *channel_id;
2892 SilcClientID *client_id;
2893 SilcChannelEntry channel;
2894 SilcClientEntry target_client;
2895 SilcChannelClientEntry chl;
2896 SilcBuffer packet, idp;
2897 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
2898 SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
2900 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2901 SilcPublicKey founder_key = NULL;
2902 unsigned char *fkey = NULL;
2903 SilcUInt32 fkey_len = 0;
2908 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
2910 /* Get Channel ID */
2911 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
2913 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2914 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2917 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
2919 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2920 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2924 /* Get channel entry */
2925 channel = silc_idlist_find_channel_by_id(server->local_list,
2928 channel = silc_idlist_find_channel_by_id(server->global_list,
2931 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2932 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
2938 /* Check whether sender is on the channel */
2939 if (!silc_server_client_on_channel(client, channel, &chl)) {
2940 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2941 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
2944 sender_mask = chl->mode;
2946 /* Get the target client's channel mode mask */
2947 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2949 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2950 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2954 SILC_GET32_MSB(target_mask, tmp_mask);
2956 /* Get target Client ID */
2957 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2959 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2960 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
2963 client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
2965 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2966 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
2970 /* Get target client's entry */
2971 target_client = silc_idlist_find_client_by_id(server->local_list,
2972 client_id, TRUE, NULL);
2973 if (!target_client) {
2974 target_client = silc_idlist_find_client_by_id(server->global_list,
2975 client_id, TRUE, NULL);
2978 if (target_client != client &&
2979 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
2980 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
2981 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2982 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
2986 /* Check whether target client is on the channel */
2987 if (target_client != client) {
2988 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
2989 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2990 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL, 0);
2999 /* If the target client is founder, no one else can change their mode
3001 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
3002 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3003 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
3008 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
3009 if (target_client != client) {
3010 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3011 SILC_STATUS_ERR_NOT_YOU, 0);
3015 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
3016 /* The client tries to claim the founder rights. */
3017 unsigned char *tmp_auth;
3018 SilcUInt32 tmp_auth_len;
3019 SilcChannelClientEntry chl2;
3020 SilcHashTableList htl;
3022 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
3023 !channel->founder_key || !idata->public_key ||
3024 !silc_pkcs_public_key_compare(channel->founder_key,
3025 idata->public_key)) {
3026 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3027 SILC_STATUS_ERR_AUTH_FAILED, 0);
3031 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
3033 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3034 SILC_STATUS_ERR_AUTH_FAILED, 0);
3038 /* Verify the authentication payload */
3039 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len, SILC_AUTH_PUBLIC_KEY,
3040 channel->founder_key, 0, server->sha1hash,
3041 client->id, SILC_ID_CLIENT)) {
3042 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3043 SILC_STATUS_ERR_AUTH_FAILED, 0);
3048 founder_key = channel->founder_key;
3049 fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
3051 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3052 SILC_STATUS_ERR_AUTH_FAILED, 0);
3056 /* There cannot be anyone else as founder on the channel now. This
3057 client is definitely the founder due to this authentication */
3058 silc_hash_table_list(channel->user_list, &htl);
3059 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
3060 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
3061 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3062 silc_server_force_cumode_change(server, NULL, channel, chl2,
3066 silc_hash_table_list_reset(&htl);
3068 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
3071 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3072 if (target_client == client) {
3073 /* Remove channel founder rights from itself */
3074 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3077 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3078 SILC_STATUS_ERR_NOT_YOU, 0);
3084 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
3085 /* Promote to operator */
3086 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3087 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3088 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3089 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3090 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
3095 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
3099 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
3100 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3101 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3102 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3103 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
3108 /* Demote to normal user */
3109 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
3114 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
3115 if (target_client != client) {
3116 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3117 SILC_STATUS_ERR_NOT_YOU, 0);
3121 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
3122 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
3126 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
3127 if (target_client != client) {
3128 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3129 SILC_STATUS_ERR_NOT_YOU, 0);
3133 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
3138 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
3139 if (target_client != client) {
3140 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3141 SILC_STATUS_ERR_NOT_YOU, 0);
3145 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)) {
3146 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
3150 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
3151 if (target_client != client) {
3152 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3153 SILC_STATUS_ERR_NOT_YOU, 0);
3157 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
3162 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
3163 if (target_client != client) {
3164 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3165 SILC_STATUS_ERR_NOT_YOU, 0);
3169 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)) {
3170 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
3174 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
3175 if (target_client != client) {
3176 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3177 SILC_STATUS_ERR_NOT_YOU, 0);
3181 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
3186 if (target_mask & SILC_CHANNEL_UMODE_QUIET) {
3187 if (!(chl->mode & SILC_CHANNEL_UMODE_QUIET)) {
3188 if (client == target_client) {
3189 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3190 SILC_STATUS_ERR_PERM_DENIED, 0);
3193 chl->mode |= 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;
3208 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3209 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3211 /* Send notify to channel, notify only if mode was actually changed. */
3213 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3214 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
3215 idp->data, idp->len,
3220 /* Set CUMODE notify type to network */
3221 silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
3222 SILC_BROADCAST(server), channel,
3223 target_mask, client->id, SILC_ID_CLIENT,
3224 target_client->id, founder_key);
3227 /* Send command reply to sender */
3228 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
3229 SILC_STATUS_OK, 0, ident, 3,
3231 3, tmp_ch_id, tmp_ch_len,
3232 4, tmp_id, tmp_len);
3233 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3234 packet->data, packet->len, FALSE);
3236 silc_buffer_free(packet);
3237 silc_free(channel_id);
3238 silc_free(client_id);
3239 silc_buffer_free(idp);
3243 silc_server_command_free(cmd);
3246 /* Server side of KICK command. Kicks client out of channel. */
3248 SILC_SERVER_CMD_FUNC(kick)
3250 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3251 SilcServer server = cmd->server;
3252 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3253 SilcClientEntry target_client;
3254 SilcChannelID *channel_id;
3255 SilcClientID *client_id;
3256 SilcChannelEntry channel;
3257 SilcChannelClientEntry chl;
3259 SilcUInt32 tmp_len, target_idp_len;
3260 unsigned char *tmp, *comment, *target_idp;
3265 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
3267 /* Get Channel ID */
3268 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3270 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3271 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3274 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3276 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3277 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3281 /* Get channel entry */
3282 channel = silc_idlist_find_channel_by_id(server->local_list,
3285 channel = silc_idlist_find_channel_by_id(server->local_list,
3288 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3289 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
3295 /* Check whether sender is on the channel */
3296 if (!silc_server_client_on_channel(client, channel, &chl)) {
3297 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3298 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
3302 /* Check that the kicker is channel operator or channel founder */
3303 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
3304 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
3305 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3306 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
3310 /* Get target Client ID */
3311 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
3313 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3314 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
3317 client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
3319 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3320 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
3324 /* Get target client's entry */
3325 target_client = silc_idlist_find_client_by_id(server->local_list,
3326 client_id, TRUE, NULL);
3327 if (!target_client) {
3328 target_client = silc_idlist_find_client_by_id(server->global_list,
3329 client_id, TRUE, NULL);
3332 /* Check whether target client is on the channel */
3333 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
3334 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3335 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL,
3340 /* Check that the target client is not channel founder. Channel founder
3341 cannot be kicked from the channel. */
3342 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3343 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3344 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
3351 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3355 /* Send command reply to sender */
3356 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3359 /* Send KICKED notify to local clients on the channel */
3360 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3361 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3362 SILC_NOTIFY_TYPE_KICKED, 3,
3363 target_idp, target_idp_len,
3364 comment, comment ? strlen(comment) : 0,
3365 idp->data, idp->len);
3366 silc_buffer_free(idp);
3368 /* Send KICKED notify to primary route */
3369 silc_server_send_notify_kicked(server, SILC_PRIMARY_ROUTE(server),
3370 SILC_BROADCAST(server), channel,
3371 target_client->id, client->id, comment);
3373 /* Remove the client from the channel. If the channel does not exist
3374 after removing the client then the client kicked itself off the channel
3375 and we don't have to send anything after that. */
3376 if (!silc_server_remove_from_one_channel(server, NULL, channel,
3377 target_client, FALSE))
3380 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3381 /* Re-generate channel key */
3382 if (!silc_server_create_channel_key(server, channel, 0))
3385 /* Send the channel key to the channel. The key of course is not sent
3386 to the client who was kicked off the channel. */
3387 silc_server_send_channel_key(server, target_client->connection, channel,
3388 server->server_type == SILC_ROUTER ?
3389 FALSE : !server->standalone);
3393 silc_server_command_free(cmd);
3396 /* Server side of OPER command. Client uses this comand to obtain server
3397 operator privileges to this server/router. */
3399 SILC_SERVER_CMD_FUNC(oper)
3401 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3402 SilcServer server = cmd->server;
3403 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3404 unsigned char *username, *auth;
3406 SilcServerConfigAdmin *admin;
3407 SilcIDListData idata = (SilcIDListData)client;
3408 bool result = FALSE;
3409 SilcPublicKey cached_key;
3411 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
3414 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
3416 /* Get the username */
3417 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3419 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3420 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3425 /* Get the admin configuration */
3426 admin = silc_server_config_find_admin(server, cmd->sock->ip,
3427 username, client->nickname);
3429 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
3430 username, client->nickname);
3432 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3433 SILC_STATUS_ERR_AUTH_FAILED,
3439 /* Get the authentication payload */
3440 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3442 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3443 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3448 /* Verify the authentication data. If both passphrase and public key
3449 is set then try both of them. */
3450 if (admin->passphrase)
3451 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
3452 admin->passphrase, admin->passphrase_len,
3453 idata->hash, client->id, SILC_ID_CLIENT);
3454 if (!result && admin->publickeys) {
3455 cached_key = silc_server_get_public_key(server, admin->publickeys);
3458 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
3459 cached_key, 0, idata->hash,
3460 client->id, SILC_ID_CLIENT);
3463 /* Authentication failed */
3464 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3465 SILC_STATUS_ERR_AUTH_FAILED,
3470 /* Client is now server operator */
3471 client->mode |= SILC_UMODE_SERVER_OPERATOR;
3473 /* Update statistics */
3474 if (SILC_IS_LOCAL(client))
3475 server->stat.my_server_ops++;
3476 if (server->server_type == SILC_ROUTER)
3477 server->stat.server_ops++;
3479 /* Send UMODE change to primary router */
3480 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
3481 SILC_BROADCAST(server), client->id,
3484 /* Check if anyone is watching this nickname */
3485 if (server->server_type == SILC_ROUTER)
3486 silc_server_check_watcher_list(server, client, NULL,
3487 SILC_NOTIFY_TYPE_UMODE_CHANGE);
3489 /* Send reply to the sender */
3490 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3494 silc_server_command_free(cmd);
3497 SILC_TASK_CALLBACK(silc_server_command_detach_cb)
3499 SilcServer server = app_context;
3500 QuitInternal q = (QuitInternal)context;
3501 SilcClientID *client_id = (SilcClientID *)q->sock;
3502 SilcClientEntry client;
3503 SilcSocketConnection sock;
3505 client = silc_idlist_find_client_by_id(server->local_list, client_id,
3507 if (client && client->connection) {
3508 sock = client->connection;
3510 /* If there is pending outgoing data for the client then purge it
3511 to the network before closing connection. */
3512 silc_server_packet_queue_purge(server, sock);
3514 /* Close the connection on our side */
3515 client->router = NULL;
3516 client->connection = NULL;
3517 sock->user_data = NULL;
3518 silc_server_close_connection(server, sock);
3521 silc_free(client_id);
3525 SILC_TASK_CALLBACK(silc_server_command_detach_timeout)
3527 SilcServer server = app_context;
3528 QuitInternal q = (QuitInternal)context;
3529 SilcClientID *client_id = (SilcClientID *)q->sock;
3530 SilcClientEntry client;
3532 client = silc_idlist_find_client_by_id(server->local_list, client_id,
3534 if (client && client->mode & SILC_UMODE_DETACHED) {
3535 SILC_LOG_DEBUG(("Detach timeout"));
3536 silc_server_free_client_data(server, NULL, client, TRUE,
3540 silc_free(client_id);
3544 /* Server side of DETACH command. Detached the client from the network
3545 by closing the connection but preserving the session. */
3547 SILC_SERVER_CMD_FUNC(detach)
3549 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3550 SilcServer server = cmd->server;
3551 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3554 if (server->config->detach_disabled) {
3555 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
3556 SILC_STATUS_ERR_UNKNOWN_COMMAND, 0);
3560 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
3563 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
3565 /* Remove operator privileges, since the client may resume in some
3566 other server which to it does not have operator privileges. */
3567 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
3568 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
3570 /* Send the user mode notify to notify that client is detached */
3571 client->mode |= SILC_UMODE_DETACHED;
3572 client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
3573 client->data.status &= ~SILC_IDLIST_STATUS_NOATTR;
3574 client->last_command = 0;
3575 client->fast_command = 0;
3576 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
3577 SILC_BROADCAST(server), client->id,
3579 server->stat.my_detached++;
3581 /* Check if anyone is watching this nickname */
3582 if (server->server_type == SILC_ROUTER)
3583 silc_server_check_watcher_list(server, client, NULL,
3584 SILC_NOTIFY_TYPE_UMODE_CHANGE);
3586 q = silc_calloc(1, sizeof(*q));
3587 q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
3588 silc_schedule_task_add(server->schedule, 0, silc_server_command_detach_cb,
3589 q, 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
3591 if (server->config->detach_timeout) {
3592 q = silc_calloc(1, sizeof(*q));
3593 q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
3594 silc_schedule_task_add(server->schedule, 0,
3595 silc_server_command_detach_timeout,
3596 q, server->config->detach_timeout * 60,
3597 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
3600 /* Send reply to the sender */
3601 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
3605 silc_server_command_free(cmd);
3608 /* Server side of WATCH command. */
3610 SILC_SERVER_CMD_FUNC(watch)
3612 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3613 SilcServer server = cmd->server;
3614 char *add_nick, *del_nick;
3615 SilcUInt32 add_nick_len, del_nick_len, tmp_len;
3617 unsigned char hash[16], *tmp;
3618 SilcClientEntry client;
3619 SilcClientID *client_id = NULL;
3621 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WATCH, cmd, 1, 3);
3623 if (server->server_type == SILC_SERVER && !server->standalone) {
3624 if (!cmd->pending) {
3625 /* Send the command to router */
3627 SilcUInt16 old_ident;
3629 old_ident = silc_command_get_ident(cmd->payload);
3630 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3631 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3633 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
3634 SILC_PACKET_COMMAND, cmd->packet->flags,
3635 tmpbuf->data, tmpbuf->len, TRUE);
3637 /* Reprocess this packet after received reply from router */
3638 silc_server_command_pending(server, SILC_COMMAND_WATCH,
3639 silc_command_get_ident(cmd->payload),
3640 silc_server_command_watch,
3641 silc_server_command_dup(cmd));
3642 cmd->pending = TRUE;
3643 silc_command_set_ident(cmd->payload, old_ident);
3644 silc_buffer_free(tmpbuf);
3645 } else if (context2) {
3646 /* Received reply from router, just send same data to the client. */
3647 SilcServerCommandReplyContext reply = context2;
3649 silc_command_get_status(reply->payload, &status, NULL);
3650 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, status,
3657 /* We are router and keep the watch list for local cell */
3659 /* Get the client ID */
3660 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3662 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
3663 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3667 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3669 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
3670 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
3675 /* Get the client entry which must be in local list */
3676 client = silc_idlist_find_client_by_id(server->local_list,
3677 client_id, TRUE, NULL);
3679 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
3680 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
3686 add_nick = silc_argument_get_arg_type(cmd->args, 2, &add_nick_len);
3687 del_nick = silc_argument_get_arg_type(cmd->args, 3, &del_nick_len);
3688 if (!add_nick && !del_nick) {
3689 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
3690 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3695 if (add_nick && add_nick_len > 128)
3696 add_nick[128] = '\0';
3697 if (del_nick && del_nick_len > 128)
3698 del_nick[128] = '\0';
3700 memset(nick, 0, sizeof(nick));
3702 /* Add new nickname to be watched in our cell */
3704 if (silc_server_name_bad_chars(add_nick, strlen(add_nick)) == TRUE) {
3705 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
3706 SILC_STATUS_ERR_BAD_NICKNAME, 0);
3710 /* Hash the nick, we have the hash saved, not nicks because we can
3711 do one to one mapping to the nick from Client ID hash this way. */
3712 silc_to_lower(add_nick, nick, sizeof(nick) - 1);
3713 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
3715 /* Check whether this client is already watching this nickname */
3716 if (silc_hash_table_find_by_context(server->watcher_list, hash,
3718 /* Nickname is alredy being watched for this client */
3719 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
3720 SILC_STATUS_ERR_NICKNAME_IN_USE,
3725 /* Get the nickname from the watcher list and use the same key in
3726 new entries as well. If key doesn't exist then create it. */
3727 if (!silc_hash_table_find(server->watcher_list, hash, (void **)&tmp, NULL))
3728 tmp = silc_memdup(hash, CLIENTID_HASH_LEN);
3730 /* Add the client to the watcher list with the specified nickname hash. */
3731 silc_hash_table_add(server->watcher_list, tmp, client);
3734 /* Delete nickname from watch list */
3736 if (silc_server_name_bad_chars(del_nick, strlen(del_nick)) == TRUE) {
3737 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
3738 SILC_STATUS_ERR_BAD_NICKNAME, 0);
3742 /* Hash the nick, we have the hash saved, not nicks because we can
3743 do one to one mapping to the nick from Client ID hash this way. */
3744 silc_to_lower(del_nick, nick, sizeof(nick) - 1);
3745 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
3747 /* Check that this client is watching for this nickname */
3748 if (!silc_hash_table_find_by_context(server->watcher_list, hash,
3749 client, (void **)&tmp)) {
3750 /* Nickname is alredy being watched for this client */
3751 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
3752 SILC_STATUS_ERR_NO_SUCH_NICK, 0);
3756 /* Delete the nickname from the watcher list. */
3757 silc_hash_table_del_by_context(server->watcher_list, hash, client);
3759 /* Now check whether there still exists entries with this key, if not
3760 then free the key to not leak memory. */
3761 if (!silc_hash_table_find(server->watcher_list, hash, NULL, NULL))
3765 /* Distribute the watch list to backup routers too */
3766 if (server->backup) {
3768 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3769 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3770 silc_server_backup_send(server, NULL, SILC_PACKET_COMMAND,
3771 cmd->packet->flags, tmpbuf->data, tmpbuf->len,
3773 silc_buffer_free(tmpbuf);
3776 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
3780 silc_free(client_id);
3781 silc_server_command_free(cmd);
3784 /* Server side of SILCOPER command. Client uses this comand to obtain router
3785 operator privileges to this router. */
3787 SILC_SERVER_CMD_FUNC(silcoper)
3789 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3790 SilcServer server = cmd->server;
3791 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3792 unsigned char *username, *auth;
3794 SilcServerConfigAdmin *admin;
3795 SilcIDListData idata = (SilcIDListData)client;
3796 bool result = FALSE;
3797 SilcPublicKey cached_key;
3799 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
3802 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
3804 if (server->server_type != SILC_ROUTER) {
3805 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3806 SILC_STATUS_ERR_AUTH_FAILED, 0);
3810 /* Get the username */
3811 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3813 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3814 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3819 /* Get the admin configuration */
3820 admin = silc_server_config_find_admin(server, cmd->sock->ip,
3821 username, client->nickname);
3823 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
3824 username, client->nickname);
3826 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3827 SILC_STATUS_ERR_AUTH_FAILED, 0);
3832 /* Get the authentication payload */
3833 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3835 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3836 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3841 /* Verify the authentication data. If both passphrase and public key
3842 is set then try both of them. */
3843 if (admin->passphrase)
3844 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
3845 admin->passphrase, admin->passphrase_len,
3846 idata->hash, client->id, SILC_ID_CLIENT);
3847 if (!result && admin->publickeys) {
3848 cached_key = silc_server_get_public_key(server, admin->publickeys);
3851 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
3852 cached_key, 0, idata->hash,
3853 client->id, SILC_ID_CLIENT);
3856 /* Authentication failed */
3857 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3858 SILC_STATUS_ERR_AUTH_FAILED, 0);
3862 /* Client is now router operator */
3863 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
3865 /* Update statistics */
3866 if (SILC_IS_LOCAL(client))
3867 server->stat.my_router_ops++;
3868 if (server->server_type == SILC_ROUTER)
3869 server->stat.router_ops++;
3871 /* Send UMODE change to primary router */
3872 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
3873 SILC_BROADCAST(server), client->id,
3876 /* Check if anyone is watching this nickname */
3877 if (server->server_type == SILC_ROUTER)
3878 silc_server_check_watcher_list(server, client, NULL,
3879 SILC_NOTIFY_TYPE_UMODE_CHANGE);
3881 /* Send reply to the sender */
3882 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3886 silc_server_command_free(cmd);
3889 /* Server side of command BAN. This is used to manage the ban list of the
3890 channel. To add clients and remove clients from the ban list. */
3892 SILC_SERVER_CMD_FUNC(ban)
3894 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3895 SilcServer server = cmd->server;
3896 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3898 SilcChannelEntry channel;
3899 SilcChannelClientEntry chl;
3900 SilcChannelID *channel_id = NULL;
3901 unsigned char *id, *add, *del;
3902 SilcUInt32 id_len, tmp_len;
3903 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3905 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
3908 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
3910 /* Get Channel ID */
3911 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
3913 channel_id = silc_id_payload_parse_id(id, id_len, NULL);
3915 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
3916 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3921 /* Get channel entry. The server must know about the channel since the
3922 client is expected to be on the channel. */
3923 channel = silc_idlist_find_channel_by_id(server->local_list,
3926 channel = silc_idlist_find_channel_by_id(server->global_list,
3929 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
3930 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
3936 /* Check whether this client is on the channel */
3937 if (!silc_server_client_on_channel(client, channel, &chl)) {
3938 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
3939 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
3943 /* The client must be at least channel operator. */
3944 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3945 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
3946 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
3950 /* Get the new ban and add it to the ban list */
3951 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3953 if (!channel->ban_list)
3954 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
3956 channel->ban_list = silc_realloc(channel->ban_list,
3957 sizeof(*channel->ban_list) *
3959 strlen(channel->ban_list) + 2));
3960 if (add[tmp_len - 1] == ',')
3961 add[tmp_len - 1] = '\0';
3963 strncat(channel->ban_list, add, tmp_len);
3964 strncat(channel->ban_list, ",", 1);
3967 /* Get the ban to be removed and remove it from the list */
3968 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3969 if (del && channel->ban_list) {
3970 char *start, *end, *n;
3972 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
3973 silc_free(channel->ban_list);
3974 channel->ban_list = NULL;
3976 start = strstr(channel->ban_list, del);
3977 if (start && strlen(start) >= tmp_len) {
3978 end = start + tmp_len;
3979 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
3980 strncat(n, channel->ban_list, start - channel->ban_list);
3981 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
3983 silc_free(channel->ban_list);
3984 channel->ban_list = n;
3989 /* Send the BAN notify type to our primary router. */
3991 silc_server_send_notify_ban(server, SILC_PRIMARY_ROUTE(server),
3992 SILC_BROADCAST(server), channel, add, del);
3994 /* Send the reply back to the client */
3996 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
3997 SILC_STATUS_OK, 0, ident, 2,
3999 3, channel->ban_list,
4001 strlen(channel->ban_list) -1 : 0);
4002 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4003 packet->data, packet->len, FALSE);
4005 silc_buffer_free(packet);
4008 silc_free(channel_id);
4009 silc_server_command_free(cmd);
4012 /* Server side command of LEAVE. Removes client from a channel. */
4014 SILC_SERVER_CMD_FUNC(leave)
4016 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4017 SilcServer server = cmd->server;
4018 SilcSocketConnection sock = cmd->sock;
4019 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4020 SilcChannelID *id = NULL;
4021 SilcChannelEntry channel;
4025 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !id_entry)
4028 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4030 /* Get Channel ID */
4031 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4033 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4034 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4037 id = silc_id_payload_parse_id(tmp, len, NULL);
4039 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4040 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4044 /* Get channel entry */
4045 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4047 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4049 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4050 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4056 /* Check whether this client is on the channel */
4057 if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
4058 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4059 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4063 /* Notify routers that they should remove this client from their list
4064 of clients on the channel. Send LEAVE notify type. */
4065 silc_server_send_notify_leave(server, SILC_PRIMARY_ROUTE(server),
4066 SILC_BROADCAST(server), channel, id_entry->id);
4068 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4069 SILC_STATUS_OK, 0, 2, tmp, len);
4071 /* Remove client from channel */
4072 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4074 /* If the channel does not exist anymore we won't send anything */
4077 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4078 /* Re-generate channel key */
4079 if (!silc_server_create_channel_key(server, channel, 0))
4082 /* Send the channel key */
4083 silc_server_send_channel_key(server, NULL, channel,
4084 server->server_type == SILC_ROUTER ?
4085 FALSE : !server->standalone);
4090 silc_server_command_free(cmd);
4093 /* Server side of command USERS. Resolves clients and their USERS currently
4094 joined on the requested channel. The list of Client ID's and their modes
4095 on the channel is sent back. */
4097 SILC_SERVER_CMD_FUNC(users)
4099 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4100 SilcServer server = cmd->server;
4101 SilcChannelEntry channel;
4102 SilcChannelID *id = NULL;
4103 SilcBuffer packet, idp;
4104 unsigned char *channel_id;
4105 SilcUInt32 channel_id_len;
4106 SilcBuffer client_id_list;
4107 SilcBuffer client_mode_list;
4108 unsigned char lc[4];
4109 SilcUInt32 list_count = 0;
4110 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4113 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
4115 /* Get Channel ID */
4116 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4118 /* Get channel name */
4119 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
4121 if (!channel_id && !channel_name) {
4122 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4123 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4128 id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
4130 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4131 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4136 /* If we are server and we don't know about this channel we will send
4137 the command to our router. If we know about the channel then we also
4138 have the list of users already. */
4140 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4142 channel = silc_idlist_find_channel_by_name(server->local_list,
4143 channel_name, NULL);
4145 if (!channel || (!server->standalone && (channel->disabled ||
4146 !channel->users_resolved))) {
4147 if (server->server_type != SILC_ROUTER && !server->standalone &&
4151 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4152 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4154 /* Send USERS command */
4155 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
4156 SILC_PACKET_COMMAND, cmd->packet->flags,
4157 tmpbuf->data, tmpbuf->len, TRUE);
4159 /* Reprocess this packet after received reply */
4160 silc_server_command_pending(server, SILC_COMMAND_USERS,
4161 silc_command_get_ident(cmd->payload),
4162 silc_server_command_users,
4163 silc_server_command_dup(cmd));
4164 cmd->pending = TRUE;
4165 silc_command_set_ident(cmd->payload, ident);
4166 silc_buffer_free(tmpbuf);
4171 /* Check the global list as well. */
4173 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4175 channel = silc_idlist_find_channel_by_name(server->global_list,
4176 channel_name, NULL);
4178 /* Channel really does not exist */
4179 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4180 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4186 /* If the channel is private or secret do not send anything, unless the
4187 user requesting this command is on the channel or is server */
4188 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
4189 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
4190 && !silc_server_client_on_channel(cmd->sock->user_data, channel,
4192 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4193 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4199 /* Get the users list */
4200 if (!silc_server_get_users_on_channel(server, channel, &client_id_list,
4201 &client_mode_list, &list_count)) {
4203 client_id_list = NULL;
4204 client_mode_list = NULL;
4208 SILC_PUT32_MSB(list_count, lc);
4211 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
4212 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
4213 SILC_STATUS_OK, 0, ident, 4,
4214 2, idp->data, idp->len,
4217 client_id_list->data : NULL,
4219 client_id_list->len : 0,
4220 5, client_mode_list ?
4221 client_mode_list->data : NULL,
4223 client_mode_list->len : 0);
4224 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4225 packet->data, packet->len, FALSE);
4227 silc_buffer_free(idp);
4228 silc_buffer_free(packet);
4230 silc_buffer_free(client_id_list);
4231 if (client_mode_list)
4232 silc_buffer_free(client_mode_list);
4236 silc_server_command_free(cmd);
4239 /* Server side of command GETKEY. This fetches the client's public key
4240 from the server where to the client is connected. */
4242 SILC_SERVER_CMD_FUNC(getkey)
4244 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4245 SilcServer server = cmd->server;
4247 SilcClientEntry client;
4248 SilcServerEntry server_entry;
4249 SilcClientID *client_id = NULL;
4250 SilcServerID *server_id = NULL;
4251 SilcIDPayload idp = NULL;
4252 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4253 unsigned char *tmp, *pkdata;
4254 SilcUInt32 tmp_len, pklen;
4255 SilcBuffer pk = NULL;
4257 SilcPublicKey public_key;
4259 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4261 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4262 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4266 idp = silc_id_payload_parse(tmp, tmp_len);
4268 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4269 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4274 id_type = silc_id_payload_get_type(idp);
4275 if (id_type == SILC_ID_CLIENT) {
4276 client_id = silc_id_payload_get_id(idp);
4278 /* If the client is not found from local list there is no chance it
4279 would be locally connected client so send the command further. */
4280 client = silc_idlist_find_client_by_id(server->local_list,
4281 client_id, TRUE, NULL);
4283 client = silc_idlist_find_client_by_id(server->global_list,
4284 client_id, TRUE, NULL);
4286 if ((!client && !cmd->pending && !server->standalone) ||
4287 (client && !client->connection && !cmd->pending &&
4288 !(client->mode & SILC_UMODE_DETACHED)) ||
4289 (client && !client->data.public_key && !cmd->pending)) {
4291 SilcUInt16 old_ident;
4292 SilcSocketConnection dest_sock;
4294 dest_sock = silc_server_get_client_route(server, NULL, 0,
4295 client_id, NULL, NULL);
4299 old_ident = silc_command_get_ident(cmd->payload);
4300 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4301 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4303 silc_server_packet_send(server, dest_sock,
4304 SILC_PACKET_COMMAND, cmd->packet->flags,
4305 tmpbuf->data, tmpbuf->len, TRUE);
4307 /* Reprocess this packet after received reply from router */
4308 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
4309 silc_command_get_ident(cmd->payload),
4310 silc_server_command_getkey,
4311 silc_server_command_dup(cmd));
4312 cmd->pending = TRUE;
4313 silc_command_set_ident(cmd->payload, old_ident);
4314 silc_buffer_free(tmpbuf);
4319 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4320 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
4325 /* The client is locally connected, just get the public key and
4326 send it back. If they key does not exist then do not send it,
4327 send just OK reply */
4328 public_key = client->data.public_key;
4333 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
4334 pk = silc_buffer_alloc(4 + tmp_len);
4335 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
4336 silc_buffer_format(pk,
4337 SILC_STR_UI_SHORT(tmp_len),
4338 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
4339 SILC_STR_UI_XNSTRING(tmp, tmp_len),
4345 } else if (id_type == SILC_ID_SERVER) {
4346 server_id = silc_id_payload_get_id(idp);
4348 /* If the server is not found from local list there is no chance it
4349 would be locally connected server so send the command further. */
4350 server_entry = silc_idlist_find_server_by_id(server->local_list,
4351 server_id, TRUE, NULL);
4353 server_entry = silc_idlist_find_server_by_id(server->global_list,
4354 server_id, TRUE, NULL);
4356 if (server_entry != server->id_entry &&
4357 ((!server_entry && !cmd->pending && !server->standalone) ||
4358 (server_entry && !server_entry->connection && !cmd->pending &&
4359 !server->standalone) ||
4360 (server_entry && !server_entry->data.public_key && !cmd->pending &&
4361 !server->standalone))) {
4363 SilcUInt16 old_ident;
4365 old_ident = silc_command_get_ident(cmd->payload);
4366 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4367 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4369 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
4370 SILC_PACKET_COMMAND, cmd->packet->flags,
4371 tmpbuf->data, tmpbuf->len, TRUE);
4373 /* Reprocess this packet after received reply from router */
4374 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
4375 silc_command_get_ident(cmd->payload),
4376 silc_server_command_getkey,
4377 silc_server_command_dup(cmd));
4378 cmd->pending = TRUE;
4379 silc_command_set_ident(cmd->payload, old_ident);
4380 silc_buffer_free(tmpbuf);
4384 if (!server_entry) {
4385 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4386 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
4391 /* If they key does not exist then do not send it, send just OK reply */
4392 public_key = (!server_entry->data.public_key ?
4393 (server_entry == server->id_entry ? server->public_key :
4394 NULL) : server_entry->data.public_key);
4399 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
4400 pk = silc_buffer_alloc(4 + tmp_len);
4401 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
4402 silc_buffer_format(pk,
4403 SILC_STR_UI_SHORT(tmp_len),
4404 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
4405 SILC_STR_UI_XNSTRING(tmp, tmp_len),
4415 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4416 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
4417 SILC_STATUS_OK, 0, ident,
4421 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4422 packet->data, packet->len, FALSE);
4423 silc_buffer_free(packet);
4426 silc_buffer_free(pk);
4430 silc_id_payload_free(idp);
4431 silc_free(client_id);
4432 silc_free(server_id);
4433 silc_server_command_free(cmd);
4437 /* Private range commands, specific to this implementation */
4439 /* Server side command of CONNECT. Connects us to the specified remote
4440 server or router. */
4442 SILC_SERVER_CMD_FUNC(connect)
4444 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4445 SilcServer server = cmd->server;
4446 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4447 unsigned char *tmp, *host;
4449 SilcUInt32 port = SILC_PORT;
4451 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
4454 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
4456 /* Check whether client has the permissions. */
4457 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
4458 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
4459 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
4460 SILC_STATUS_ERR_NO_SERVER_PRIV, 0);
4464 if (server->server_type == SILC_ROUTER &&
4465 client->mode & SILC_UMODE_SERVER_OPERATOR) {
4466 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
4467 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
4471 /* Get the remote server */
4472 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4474 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
4475 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4481 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4483 SILC_GET32_MSB(port, tmp);
4485 /* Create the connection. It is done with timeout and is async. */
4486 silc_server_create_connection(server, host, port);
4488 /* Send reply to the sender */
4489 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
4493 silc_server_command_free(cmd);
4496 /* Server side command of CLOSE. Closes connection to a specified server. */
4498 SILC_SERVER_CMD_FUNC(close)
4500 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4501 SilcServer server = cmd->server;
4502 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4503 SilcServerEntry server_entry;
4504 SilcSocketConnection sock;
4507 unsigned char *name;
4508 SilcUInt32 port = SILC_PORT;
4510 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
4513 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
4515 /* Check whether client has the permissions. */
4516 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
4517 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
4518 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
4519 SILC_STATUS_ERR_NO_SERVER_PRIV,
4524 /* Get the remote server */
4525 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4527 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
4528 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4534 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4536 SILC_GET32_MSB(port, tmp);
4538 server_entry = silc_idlist_find_server_by_conn(server->local_list,
4539 name, port, FALSE, NULL);
4541 server_entry = silc_idlist_find_server_by_conn(server->global_list,
4542 name, port, FALSE, NULL);
4543 if (!server_entry) {
4544 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
4545 SILC_STATUS_ERR_NO_SERVER_ID, 0);
4549 if (server_entry == server->id_entry) {
4550 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
4551 SILC_STATUS_ERR_NO_SERVER_ID, 0);
4555 /* Send reply to the sender */
4556 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
4559 /* Close the connection to the server */
4560 sock = (SilcSocketConnection)server_entry->connection;
4562 /* If we shutdown primary router connection manually then don't trigger
4563 any reconnect or backup router connections, by setting the router
4565 if (server->router == server_entry) {
4566 server->id_entry->router = NULL;
4567 server->router = NULL;
4568 server->standalone = TRUE;
4570 silc_server_free_sock_user_data(server, sock, NULL);
4571 silc_server_close_connection(server, sock);
4574 silc_server_command_free(cmd);
4577 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4578 active connections. */
4580 SILC_SERVER_CMD_FUNC(shutdown)
4582 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4583 SilcServer server = cmd->server;
4584 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4586 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
4589 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
4591 /* Check whether client has the permission. */
4592 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
4593 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
4594 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
4595 SILC_STATUS_ERR_NO_SERVER_PRIV,
4600 /* Send reply to the sender */
4601 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
4604 /* Then, gracefully, or not, bring the server down. */
4605 silc_server_stop(server);
4609 silc_server_command_free(cmd);