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 silc_strncat(invite, sizeof(invite),
1128 dest->nickname, strlen(dest->nickname));
1129 silc_strncat(invite, sizeof(invite), "!", 1);
1130 silc_strncat(invite, sizeof(invite),
1131 dest->username, strlen(dest->username));
1132 if (!strchr(dest->username, '@')) {
1133 silc_strncat(invite, sizeof(invite), "@", 1);
1134 silc_strncat(invite, sizeof(invite), cmd->sock->hostname,
1135 strlen(cmd->sock->hostname));
1138 len = strlen(invite);
1139 if (!channel->invite_list)
1140 channel->invite_list = silc_calloc(len + 2,
1141 sizeof(*channel->invite_list));
1143 channel->invite_list = silc_realloc(channel->invite_list,
1144 sizeof(*channel->invite_list) *
1146 strlen(channel->invite_list) + 2));
1147 strncat(channel->invite_list, invite, len);
1148 strncat(channel->invite_list, ",", 1);
1150 if (!(dest->mode & SILC_UMODE_BLOCK_INVITE)) {
1151 /* Send notify to the client that is invited to the channel */
1152 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1153 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1154 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
1156 SILC_NOTIFY_TYPE_INVITE, 3,
1157 idp->data, idp->len,
1158 channel->channel_name,
1159 strlen(channel->channel_name),
1160 idp2->data, idp2->len);
1161 silc_buffer_free(idp);
1162 silc_buffer_free(idp2);
1166 /* Add the client to the invite list of the channel */
1167 add = silc_argument_get_arg_type(cmd->args, 3, &len);
1169 if (!channel->invite_list)
1170 channel->invite_list = silc_calloc(len + 2,
1171 sizeof(*channel->invite_list));
1173 channel->invite_list = silc_realloc(channel->invite_list,
1174 sizeof(*channel->invite_list) *
1176 strlen(channel->invite_list) + 2));
1177 if (add[len - 1] == ',')
1178 add[len - 1] = '\0';
1180 strncat(channel->invite_list, add, len);
1181 strncat(channel->invite_list, ",", 1);
1184 /* Get the invite to be removed and remove it from the list */
1185 del = silc_argument_get_arg_type(cmd->args, 4, &len);
1186 if (del && channel->invite_list) {
1187 char *start, *end, *n;
1189 if (!strncmp(channel->invite_list, del,
1190 strlen(channel->invite_list) - 1)) {
1191 silc_free(channel->invite_list);
1192 channel->invite_list = NULL;
1194 start = strstr(channel->invite_list, del);
1195 if (start && strlen(start) >= len) {
1197 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
1198 strncat(n, channel->invite_list, start - channel->invite_list);
1199 strncat(n, end + 1, ((channel->invite_list +
1200 strlen(channel->invite_list)) - end) - 1);
1201 silc_free(channel->invite_list);
1202 channel->invite_list = n;
1207 /* Send notify to the primary router */
1208 silc_server_send_notify_invite(server, SILC_PRIMARY_ROUTE(server),
1209 SILC_BROADCAST(server), channel,
1210 sender->id, add, del);
1212 /* Send command reply */
1213 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1217 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
1218 SILC_STATUS_OK, 0, ident, 2,
1220 3, channel->invite_list,
1221 channel->invite_list ?
1222 strlen(channel->invite_list) : 0);
1225 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
1226 SILC_STATUS_OK, 0, ident, 1,
1228 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1229 packet->data, packet->len, FALSE);
1230 silc_buffer_free(packet);
1234 silc_free(channel_id);
1235 silc_server_command_free(cmd);
1239 SilcSocketConnection sock;
1243 /* Quits connection to client. This gets called if client won't
1244 close the connection even when it has issued QUIT command. */
1246 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
1248 SilcServer server = app_context;
1249 QuitInternal q = (QuitInternal)context;
1251 /* Free all client specific data, such as client entry and entires
1252 on channels this client may be on. */
1253 silc_server_free_client_data(server, q->sock, q->sock->user_data,
1255 q->sock->user_data = NULL;
1257 /* Close the connection on our side */
1258 silc_server_close_connection(server, q->sock);
1260 silc_socket_free(q->sock);
1261 silc_free(q->signoff);
1265 /* Quits SILC session. This is the normal way to disconnect client. */
1267 SILC_SERVER_CMD_FUNC(quit)
1269 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1270 SilcServer server = cmd->server;
1271 SilcSocketConnection sock = cmd->sock;
1273 unsigned char *tmp = NULL;
1276 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
1278 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1282 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1286 q = silc_calloc(1, sizeof(*q));
1287 q->sock = silc_socket_dup(sock);
1288 q->signoff = tmp ? strdup(tmp) : NULL;
1290 /* We quit the connection with little timeout */
1291 silc_schedule_task_add(server->schedule, sock->sock,
1292 silc_server_command_quit_cb, (void *)q,
1293 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1296 silc_server_command_free(cmd);
1299 /* Server side of command KILL. This command is used by router operator
1300 to remove an client from the SILC Network temporarily. */
1302 SILC_SERVER_CMD_FUNC(kill)
1304 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1305 SilcServer server = cmd->server;
1306 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1307 SilcClientEntry remote_client;
1308 SilcClientID *client_id;
1309 unsigned char *tmp, *comment;
1310 SilcUInt32 tmp_len, tmp_len2;
1313 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
1315 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
1318 /* KILL command works only on router */
1319 if (server->server_type != SILC_ROUTER) {
1320 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1321 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
1325 /* Check whether client has the permissions. */
1326 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
1327 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1328 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
1332 /* Get the client ID */
1333 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1335 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1336 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1340 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1342 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1343 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1348 /* Get the client entry */
1349 remote_client = silc_idlist_find_client_by_id(server->local_list,
1350 client_id, TRUE, NULL);
1352 if (!remote_client) {
1353 remote_client = silc_idlist_find_client_by_id(server->global_list,
1354 client_id, TRUE, NULL);
1356 if (!remote_client) {
1357 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1358 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1365 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
1369 /* Send reply to the sender */
1370 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
1373 /* Check if anyone is watching this nickname */
1374 if (server->server_type == SILC_ROUTER)
1375 silc_server_check_watcher_list(server, client, NULL,
1376 SILC_NOTIFY_TYPE_KILLED);
1378 /* Now do the killing */
1379 silc_server_kill_client(server, remote_client, comment, client->id,
1383 silc_server_command_free(cmd);
1386 /* Server side of command INFO. This sends information about us to
1387 the client. If client requested specific server we will send the
1388 command to that server. */
1390 SILC_SERVER_CMD_FUNC(info)
1392 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1393 SilcServer server = cmd->server;
1394 SilcBuffer packet, idp;
1397 char *dest_server, *server_info = NULL, *server_name;
1398 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1399 SilcServerEntry entry = NULL;
1400 SilcServerID *server_id = NULL;
1402 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
1404 /* Get server name */
1405 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1408 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1410 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1412 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1413 SILC_STATUS_ERR_NO_SERVER_ID, 0);
1419 /* Check whether we have this server cached */
1420 entry = silc_idlist_find_server_by_id(server->local_list,
1421 server_id, TRUE, NULL);
1423 entry = silc_idlist_find_server_by_id(server->global_list,
1424 server_id, TRUE, NULL);
1425 if (!entry && server->server_type != SILC_SERVER) {
1426 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1427 SILC_STATUS_ERR_NO_SUCH_SERVER,
1434 /* Some buggy servers has sent request to router about themselves. */
1435 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
1438 if ((!dest_server && !server_id && !entry) || (entry &&
1439 entry == server->id_entry) ||
1440 (dest_server && !cmd->pending &&
1441 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
1442 /* Send our reply */
1443 char info_string[256];
1445 memset(info_string, 0, sizeof(info_string));
1446 snprintf(info_string, sizeof(info_string),
1447 "location: %s server: %s admin: %s <%s>",
1448 server->config->server_info->location,
1449 server->config->server_info->server_type,
1450 server->config->server_info->admin,
1451 server->config->server_info->email);
1453 server_info = info_string;
1454 entry = server->id_entry;
1456 /* Check whether we have this server cached */
1457 if (!entry && dest_server) {
1458 entry = silc_idlist_find_server_by_name(server->global_list,
1459 dest_server, TRUE, NULL);
1461 entry = silc_idlist_find_server_by_name(server->local_list,
1462 dest_server, TRUE, NULL);
1466 if (!cmd->pending &&
1467 server->server_type != SILC_SERVER && entry && !entry->server_info) {
1468 /* Send to the server */
1470 SilcUInt16 old_ident;
1472 old_ident = silc_command_get_ident(cmd->payload);
1473 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1474 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1476 silc_server_packet_send(server, entry->connection,
1477 SILC_PACKET_COMMAND, cmd->packet->flags,
1478 tmpbuf->data, tmpbuf->len, TRUE);
1480 /* Reprocess this packet after received reply from router */
1481 silc_server_command_pending(server, SILC_COMMAND_INFO,
1482 silc_command_get_ident(cmd->payload),
1483 silc_server_command_info,
1484 silc_server_command_dup(cmd));
1485 cmd->pending = TRUE;
1486 silc_command_set_ident(cmd->payload, old_ident);
1487 silc_buffer_free(tmpbuf);
1491 if (!entry && !cmd->pending && !server->standalone) {
1492 /* Send to the primary router */
1494 SilcUInt16 old_ident;
1496 old_ident = silc_command_get_ident(cmd->payload);
1497 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1498 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1500 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
1501 SILC_PACKET_COMMAND, cmd->packet->flags,
1502 tmpbuf->data, tmpbuf->len, TRUE);
1504 /* Reprocess this packet after received reply from router */
1505 silc_server_command_pending(server, SILC_COMMAND_INFO,
1506 silc_command_get_ident(cmd->payload),
1507 silc_server_command_info,
1508 silc_server_command_dup(cmd));
1509 cmd->pending = TRUE;
1510 silc_command_set_ident(cmd->payload, old_ident);
1511 silc_buffer_free(tmpbuf);
1516 silc_free(server_id);
1519 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1520 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
1524 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1526 server_info = entry->server_info;
1527 server_name = entry->server_name;
1529 /* Send the reply */
1530 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
1531 SILC_STATUS_OK, 0, ident, 3,
1532 2, idp->data, idp->len,
1534 strlen(server_name),
1537 strlen(server_info) : 0);
1538 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1539 packet->data, packet->len, FALSE);
1541 silc_buffer_free(packet);
1542 silc_buffer_free(idp);
1545 silc_server_command_free(cmd);
1548 /* Server side of command PING. This just replies to the ping. */
1550 SILC_SERVER_CMD_FUNC(ping)
1552 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1553 SilcServer server = cmd->server;
1558 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
1561 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1563 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1564 SILC_STATUS_ERR_NO_SERVER_ID, 0);
1567 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
1571 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
1572 /* Send our reply */
1573 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1576 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1577 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
1584 silc_server_command_free(cmd);
1587 /* Server side of command STATS. */
1589 SILC_SERVER_CMD_FUNC(stats)
1591 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1592 SilcServer server = cmd->server;
1593 SilcServerID *server_id;
1596 SilcBuffer packet, stats;
1597 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1600 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1);
1603 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1605 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1606 SILC_STATUS_ERR_NO_SERVER_ID, 0);
1609 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1613 /* The ID must be ours */
1614 if (!SILC_ID_SERVER_COMPARE(server->id, server_id)) {
1615 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1616 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
1617 silc_free(server_id);
1620 silc_free(server_id);
1622 /* If we are router then just send everything we got. If we are normal
1623 server then we'll send this to our router to get all the latest
1624 statistical information. */
1625 if (!cmd->pending && server->server_type != SILC_ROUTER &&
1626 !server->standalone) {
1627 /* Send request to our router */
1628 SilcBuffer idp = silc_id_payload_encode(server->router->id,
1630 packet = silc_command_payload_encode_va(SILC_COMMAND_STATS,
1631 ++server->cmd_ident, 1,
1632 1, idp->data, idp->len);
1633 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
1634 SILC_PACKET_COMMAND, 0, packet->data,
1635 packet->len, FALSE);
1637 /* Reprocess this packet after received reply from router */
1638 silc_server_command_pending(server, SILC_COMMAND_STATS,
1640 silc_server_command_stats,
1641 silc_server_command_dup(cmd));
1642 cmd->pending = TRUE;
1643 silc_buffer_free(packet);
1644 silc_buffer_free(idp);
1648 /* Send our reply to sender */
1649 uptime = time(NULL) - server->starttime;
1651 stats = silc_buffer_alloc_size(60);
1652 silc_buffer_format(stats,
1653 SILC_STR_UI_INT(server->starttime),
1654 SILC_STR_UI_INT(uptime),
1655 SILC_STR_UI_INT(server->stat.my_clients),
1656 SILC_STR_UI_INT(server->stat.my_channels),
1657 SILC_STR_UI_INT(server->stat.my_server_ops),
1658 SILC_STR_UI_INT(server->stat.my_router_ops),
1659 SILC_STR_UI_INT(server->stat.cell_clients),
1660 SILC_STR_UI_INT(server->stat.cell_channels),
1661 SILC_STR_UI_INT(server->stat.cell_servers),
1662 SILC_STR_UI_INT(server->stat.clients),
1663 SILC_STR_UI_INT(server->stat.channels),
1664 SILC_STR_UI_INT(server->stat.servers),
1665 SILC_STR_UI_INT(server->stat.routers),
1666 SILC_STR_UI_INT(server->stat.server_ops),
1667 SILC_STR_UI_INT(server->stat.router_ops),
1670 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_STATS,
1671 SILC_STATUS_OK, 0, ident, 2,
1673 3, stats->data, stats->len);
1674 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1675 0, packet->data, packet->len, FALSE);
1676 silc_buffer_free(packet);
1677 silc_buffer_free(stats);
1680 silc_server_command_free(cmd);
1683 /* Internal routine to join channel. The channel sent to this function
1684 has been either created or resolved from ID lists. This joins the sent
1685 client to the channel. */
1687 static void silc_server_command_join_channel(SilcServer server,
1688 SilcServerCommandContext cmd,
1689 SilcChannelEntry channel,
1690 SilcClientID *client_id,
1694 const unsigned char *auth,
1695 SilcUInt32 auth_len)
1697 SilcSocketConnection sock = cmd->sock;
1699 SilcUInt32 tmp_len, user_count;
1700 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
1701 SilcClientEntry client;
1702 SilcChannelClientEntry chl;
1703 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
1704 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1705 char check[512], check2[512];
1706 bool founder = FALSE;
1708 unsigned char *fkey = NULL;
1709 SilcUInt32 fkey_len = 0;
1711 SILC_LOG_DEBUG(("Joining client to channel"));
1716 /* Get the client entry */
1717 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1718 client = (SilcClientEntry)sock->user_data;
1722 client = silc_server_query_client(server, client_id, FALSE,
1729 silc_server_command_send_status_reply(
1730 cmd, SILC_COMMAND_JOIN,
1731 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
1735 /* The client info is being resolved. Reprocess this packet after
1736 receiving the reply to the query. */
1737 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1739 silc_server_command_join,
1740 silc_server_command_dup(cmd));
1741 cmd->pending = TRUE;
1745 cmd->pending = FALSE;
1749 * Check founder auth payload if provided. If client can gain founder
1750 * privileges it can override various conditions on joining the channel,
1751 * and can have directly the founder mode set on the channel.
1753 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1754 SilcIDListData idata = (SilcIDListData)client;
1755 SilcChannelClientEntry chl2;
1756 SilcHashTableList htl;
1758 if (channel->founder_key && idata->public_key &&
1759 silc_pkcs_public_key_compare(channel->founder_key,
1760 idata->public_key)) {
1761 /* Check whether the client is to become founder */
1762 if (silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
1763 channel->founder_key, 0, server->sha1hash,
1764 client->id, SILC_ID_CLIENT)) {
1766 /* There cannot be anyone else as founder on the channel now. This
1767 client is definitely the founder due to this authentication */
1768 silc_hash_table_list(channel->user_list, &htl);
1769 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
1770 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
1771 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
1772 silc_server_force_cumode_change(server, NULL, channel, chl2,
1776 silc_hash_table_list_reset(&htl);
1778 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
1785 * Check channel modes
1789 memset(check, 0, sizeof(check));
1790 memset(check2, 0, sizeof(check2));
1791 silc_strncat(check, sizeof(check),
1792 client->nickname, strlen(client->nickname));
1793 silc_strncat(check, sizeof(check), "!", 1);
1794 silc_strncat(check, sizeof(check),
1795 client->username, strlen(client->username));
1796 if (!strchr(client->username, '@')) {
1797 silc_strncat(check, sizeof(check), "@", 1);
1798 silc_strncat(check, sizeof(check),
1799 cmd->sock->hostname, strlen(cmd->sock->hostname));
1802 silc_strncat(check2, sizeof(check2),
1803 client->nickname, strlen(client->nickname));
1804 if (!strchr(client->nickname, '@')) {
1805 silc_strncat(check2, sizeof(check2), "@", 1);
1806 silc_strncat(check2, sizeof(check2),
1807 server->server_name, strlen(server->server_name));
1809 silc_strncat(check2, sizeof(check2), "!", 1);
1810 silc_strncat(check2, sizeof(check2),
1811 client->username, strlen(client->username));
1812 if (!strchr(client->username, '@')) {
1813 silc_strncat(check2, sizeof(check2), "@", 1);
1814 silc_strncat(check2, sizeof(check2),
1815 cmd->sock->hostname, strlen(cmd->sock->hostname));
1818 /* Check invite list if channel is invite-only channel */
1819 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1820 if (!channel->invite_list ||
1821 (!silc_string_match(channel->invite_list, check) &&
1822 !silc_string_match(channel->invite_list, check2))) {
1823 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1824 SILC_STATUS_ERR_NOT_INVITED, 0);
1829 /* Check ban list if it exists. If the client's nickname, server,
1830 username and/or hostname is in the ban list the access to the
1831 channel is denied. */
1832 if (channel->ban_list) {
1833 if (silc_string_match(channel->ban_list, check) ||
1834 silc_string_match(channel->ban_list, check2)) {
1835 silc_server_command_send_status_reply(
1836 cmd, SILC_COMMAND_JOIN,
1837 SILC_STATUS_ERR_BANNED_FROM_CHANNEL, 0);
1842 /* Check user count limit if set. */
1843 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
1844 if (silc_hash_table_count(channel->user_list) + 1 >
1845 channel->user_limit) {
1846 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1847 SILC_STATUS_ERR_CHANNEL_IS_FULL,
1854 /* Check the channel passphrase if set. */
1855 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1856 /* Get passphrase */
1857 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1859 passphrase = silc_memdup(tmp, tmp_len);
1861 if (!passphrase || !channel->passphrase ||
1862 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
1863 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1864 SILC_STATUS_ERR_BAD_PASSWORD, 0);
1870 * Client is allowed to join to the channel. Make it happen.
1873 /* Check whether the client already is on the channel */
1874 if (silc_server_client_on_channel(client, channel, NULL)) {
1875 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1876 SILC_STATUS_ERR_USER_ON_CHANNEL, 0);
1880 /* Generate new channel key as protocol dictates */
1882 if (!silc_server_create_channel_key(server, channel, 0))
1885 /* Send the channel key. This is broadcasted to the channel but is not
1886 sent to the client who is joining to the channel. */
1887 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
1888 silc_server_send_channel_key(server, NULL, channel,
1889 server->server_type == SILC_ROUTER ?
1890 FALSE : !server->standalone);
1893 /* Join the client to the channel by adding it to channel's user list.
1894 Add also the channel to client entry's channels list for fast cross-
1896 chl = silc_calloc(1, sizeof(*chl));
1898 chl->client = client;
1899 chl->channel = channel;
1900 silc_hash_table_add(channel->user_list, client, chl);
1901 silc_hash_table_add(client->channels, channel, chl);
1902 channel->user_count++;
1903 channel->disabled = FALSE;
1905 /* Get users on the channel */
1906 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
1909 /* Encode Client ID Payload of the original client who wants to join */
1910 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1912 /* Encode command reply packet */
1913 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1914 SILC_PUT32_MSB(channel->mode, mode);
1915 SILC_PUT32_MSB(created, tmp2);
1916 SILC_PUT32_MSB(user_count, tmp3);
1918 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
1919 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1920 keyp = silc_channel_key_payload_encode(silc_id_get_len(channel->id,
1923 strlen(channel->channel_key->
1925 channel->channel_key->cipher->name,
1926 channel->key_len / 8, channel->key);
1930 if (channel->founder_key)
1931 fkey = silc_pkcs_public_key_encode(channel->founder_key, &fkey_len);
1934 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1935 SILC_STATUS_OK, 0, ident, 14,
1936 2, channel->channel_name,
1937 strlen(channel->channel_name),
1938 3, chidp->data, chidp->len,
1939 4, clidp->data, clidp->len,
1942 7, keyp ? keyp->data : NULL,
1943 keyp ? keyp->len : 0,
1944 8, channel->ban_list,
1946 strlen(channel->ban_list) : 0,
1947 9, channel->invite_list,
1948 channel->invite_list ?
1949 strlen(channel->invite_list) : 0,
1952 strlen(channel->topic) : 0,
1953 11, silc_hmac_get_name(channel->hmac),
1954 strlen(silc_hmac_get_name(channel->
1957 13, user_list->data, user_list->len,
1958 14, mode_list->data,
1960 15, fkey, fkey_len);
1962 /* Send command reply */
1963 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
1964 reply->data, reply->len, FALSE);
1966 /* Send JOIN notify to locally connected clients on the channel. If
1967 we are normal server then router will send or have sent JOIN notify
1968 already. However since we've added the client already to our channel
1969 we'll ignore it (in packet_receive.c) so we must send it here. If
1970 we are router then this will send it to local clients and local
1972 SILC_LOG_DEBUG(("Send JOIN notify to channel"));
1973 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
1974 SILC_NOTIFY_TYPE_JOIN, 2,
1975 clidp->data, clidp->len,
1976 chidp->data, chidp->len);
1978 /* Update statistics */
1979 server->stat.my_chanclients++;
1980 if (server->server_type == SILC_ROUTER) {
1981 server->stat.cell_chanclients++;
1982 server->stat.chanclients++;
1985 if (!cmd->pending) {
1986 /* Send JOIN notify packet to our primary router */
1987 silc_server_send_notify_join(server, SILC_PRIMARY_ROUTE(server),
1988 SILC_BROADCAST(server), channel, client->id);
1991 /* Distribute the channel key to all backup routers. */
1992 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
1993 keyp->data, keyp->len, FALSE, TRUE);
1995 /* If client became founder by providing correct founder auth data
1996 notify the mode change to the channel. */
1998 SILC_PUT32_MSB(chl->mode, mode);
1999 SILC_LOG_DEBUG(("Send CUMODE_CHANGE notify to channel"));
2000 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2001 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
2002 clidp->data, clidp->len,
2003 mode, 4, clidp->data, clidp->len,
2008 /* Set CUMODE notify type to network */
2010 silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
2011 SILC_BROADCAST(server), channel,
2012 chl->mode, client->id, SILC_ID_CLIENT,
2013 client->id, channel->founder_key);
2015 silc_buffer_free(reply);
2016 silc_buffer_free(clidp);
2017 silc_buffer_free(chidp);
2018 silc_buffer_free(keyp);
2019 silc_buffer_free(user_list);
2020 silc_buffer_free(mode_list);
2024 silc_free(passphrase);
2027 /* Server side of command JOIN. Joins client into requested channel. If
2028 the channel does not exist it will be created. */
2030 SILC_SERVER_CMD_FUNC(join)
2032 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2033 SilcServer server = cmd->server;
2034 unsigned char *auth;
2035 SilcUInt32 tmp_len, auth_len;
2036 char *tmp, *channel_name = NULL, *cipher, *hmac;
2037 SilcChannelEntry channel;
2038 SilcUInt32 umode = 0;
2039 bool created = FALSE, create_key = TRUE;
2040 SilcClientID *client_id;
2042 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
2044 /* Get channel name */
2045 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2047 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2048 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2055 channel_name[255] = '\0';
2057 if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
2058 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2059 SILC_STATUS_ERR_BAD_CHANNEL, 0);
2063 /* Get Client ID of the client who is joining to the channel */
2064 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2066 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2067 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2071 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2073 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2074 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2079 /* Get cipher, hmac name and auth payload */
2080 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2081 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2082 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
2084 /* See if the channel exists */
2085 channel = silc_idlist_find_channel_by_name(server->local_list,
2086 channel_name, NULL);
2088 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2089 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2091 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2092 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2097 silc_free(client_id);
2098 client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
2101 (channel->disabled && server->server_type != SILC_ROUTER)) {
2102 /* Channel not found or not valid */
2104 /* If we are standalone server we don't have a router, we just create
2105 the channel by ourselves (unless it existed). */
2106 if (server->standalone) {
2108 channel = silc_server_create_new_channel(server, server->id, cipher,
2109 hmac, channel_name, TRUE);
2111 silc_server_command_send_status_reply(
2112 cmd, SILC_COMMAND_JOIN,
2113 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
2115 silc_free(client_id);
2119 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2125 /* The channel does not exist on our server. If we are normal server
2126 we will send JOIN command to our router which will handle the
2127 joining procedure (either creates the channel if it doesn't exist
2128 or joins the client to it). */
2129 if (server->server_type != SILC_ROUTER) {
2131 SilcUInt16 old_ident;
2133 /* If this is pending command callback then we've resolved
2134 it and it didn't work, return since we've notified the
2135 client already in the command reply callback. */
2137 silc_free(client_id);
2141 old_ident = silc_command_get_ident(cmd->payload);
2142 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2143 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2145 /* Send JOIN command to our router */
2146 silc_server_packet_send(server, (SilcSocketConnection)
2147 SILC_PRIMARY_ROUTE(server),
2148 SILC_PACKET_COMMAND, cmd->packet->flags,
2149 tmpbuf->data, tmpbuf->len, TRUE);
2151 /* Reprocess this packet after received reply from router */
2152 silc_server_command_pending(server, SILC_COMMAND_JOIN,
2153 silc_command_get_ident(cmd->payload),
2154 silc_server_command_join,
2155 silc_server_command_dup(cmd));
2156 cmd->pending = TRUE;
2157 silc_command_set_ident(cmd->payload, old_ident);
2158 silc_buffer_free(tmpbuf);
2159 silc_free(client_id);
2163 /* We are router and the channel does not seem exist so we will check
2164 our global list as well for the channel. */
2165 channel = silc_idlist_find_channel_by_name(server->global_list,
2166 channel_name, NULL);
2168 /* Channel really does not exist, create it */
2169 channel = silc_server_create_new_channel(server, server->id, cipher,
2170 hmac, channel_name, TRUE);
2172 silc_server_command_send_status_reply(
2173 cmd, SILC_COMMAND_JOIN,
2174 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
2175 silc_free(client_id);
2179 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2187 /* Channel not found */
2189 /* If the command came from router and we are normal server then
2190 something went wrong with the joining as the channel was not found.
2191 We can't do anything else but ignore this. */
2192 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
2193 server->server_type != SILC_ROUTER) {
2194 silc_free(client_id);
2198 /* We are router and the channel does not seem exist so we will check
2199 our global list as well for the channel. */
2200 channel = silc_idlist_find_channel_by_name(server->global_list,
2201 channel_name, NULL);
2203 /* Channel really does not exist, create it */
2204 channel = silc_server_create_new_channel(server, server->id, cipher,
2205 hmac, channel_name, TRUE);
2207 silc_server_command_send_status_reply(
2208 cmd, SILC_COMMAND_JOIN,
2209 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
2210 silc_free(client_id);
2214 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2221 /* Check whether the channel was created by our router */
2222 if (cmd->pending && context2) {
2223 SilcServerCommandReplyContext reply = context2;
2225 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
2226 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
2227 SILC_GET32_MSB(created, tmp);
2228 if (silc_argument_get_arg_type(reply->args, 7, NULL))
2229 create_key = FALSE; /* Router returned the key already */
2231 if (silc_command_get_status(reply->payload, NULL, NULL) &&
2232 channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2233 /* Save channel passphrase, if user provided it successfully */
2236 pa = silc_argument_get_arg_type(cmd->args, 3, &pa_len);
2238 silc_free(channel->passphrase);
2239 channel->passphrase = silc_memdup(pa, pa_len);
2244 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
2245 !channel->disabled && !silc_hash_table_count(channel->user_list))
2249 /* If the channel does not have global users and is also empty the client
2250 will be the channel founder and operator. */
2251 if (!channel->disabled &&
2252 !channel->global_users && !silc_hash_table_count(channel->user_list))
2253 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2255 /* Join to the channel */
2256 silc_server_command_join_channel(server, cmd, channel, client_id,
2257 created, create_key, umode,
2260 silc_free(client_id);
2263 silc_server_command_free(cmd);
2266 /* Server side of command MOTD. Sends server's current "message of the
2267 day" to the client. */
2269 SILC_SERVER_CMD_FUNC(motd)
2271 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2272 SilcServer server = cmd->server;
2273 SilcBuffer packet, idp;
2274 char *motd, *dest_server;
2275 SilcUInt32 motd_len;
2276 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2278 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
2280 /* Get server name */
2281 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2283 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2284 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
2288 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
2291 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
2293 if (server->config && server->config->server_info &&
2294 server->config->server_info->motd_file) {
2296 motd = silc_file_readfile(server->config->server_info->motd_file,
2302 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
2309 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
2315 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2316 packet->data, packet->len, FALSE);
2317 silc_buffer_free(packet);
2318 silc_buffer_free(idp);
2320 SilcServerEntry entry;
2322 /* Check whether we have this server cached */
2323 entry = silc_idlist_find_server_by_name(server->global_list,
2324 dest_server, TRUE, NULL);
2326 entry = silc_idlist_find_server_by_name(server->local_list,
2327 dest_server, TRUE, NULL);
2330 if (server->server_type != SILC_SERVER && !cmd->pending &&
2331 entry && !entry->motd) {
2332 /* Send to the server */
2334 SilcUInt16 old_ident;
2336 old_ident = silc_command_get_ident(cmd->payload);
2337 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2338 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2340 silc_server_packet_send(server, entry->connection,
2341 SILC_PACKET_COMMAND, cmd->packet->flags,
2342 tmpbuf->data, tmpbuf->len, TRUE);
2344 /* Reprocess this packet after received reply from router */
2345 silc_server_command_pending(server, SILC_COMMAND_MOTD,
2346 silc_command_get_ident(cmd->payload),
2347 silc_server_command_motd,
2348 silc_server_command_dup(cmd));
2349 cmd->pending = TRUE;
2350 silc_command_set_ident(cmd->payload, old_ident);
2351 silc_buffer_free(tmpbuf);
2355 if (!entry && !cmd->pending && !server->standalone) {
2356 /* Send to the primary router */
2358 SilcUInt16 old_ident;
2360 old_ident = silc_command_get_ident(cmd->payload);
2361 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2362 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2364 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
2365 SILC_PACKET_COMMAND, cmd->packet->flags,
2366 tmpbuf->data, tmpbuf->len, TRUE);
2368 /* Reprocess this packet after received reply from router */
2369 silc_server_command_pending(server, SILC_COMMAND_MOTD,
2370 silc_command_get_ident(cmd->payload),
2371 silc_server_command_motd,
2372 silc_server_command_dup(cmd));
2373 cmd->pending = TRUE;
2374 silc_command_set_ident(cmd->payload, old_ident);
2375 silc_buffer_free(tmpbuf);
2380 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2381 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
2385 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
2386 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
2387 SILC_STATUS_OK, 0, ident, 2,
2391 strlen(entry->motd) : 0);
2392 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2393 packet->data, packet->len, FALSE);
2394 silc_buffer_free(packet);
2395 silc_buffer_free(idp);
2399 silc_server_command_free(cmd);
2402 /* Server side of command UMODE. Client can use this command to set/unset
2403 user mode. Client actually cannot set itself to be as server/router
2404 operator so this can be used only to unset the modes. */
2406 SILC_SERVER_CMD_FUNC(umode)
2408 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2409 SilcServer server = cmd->server;
2410 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2412 unsigned char *tmp_mask, m[4];
2413 SilcUInt32 mask = 0;
2414 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2415 bool set_mask = FALSE;
2417 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
2420 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2);
2422 /* Get the client's mode mask */
2423 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2425 SILC_GET32_MSB(mask, tmp_mask);
2430 /* Check that mode changing is allowed. */
2431 if (!silc_server_check_umode_rights(server, client, mask)) {
2432 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2433 SILC_STATUS_ERR_PERM_DENIED, 0);
2437 /* Anonymous mode cannot be set by client */
2438 if (mask & SILC_UMODE_ANONYMOUS) {
2439 if (!(client->mode & SILC_UMODE_ANONYMOUS)) {
2440 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2441 SILC_STATUS_ERR_PERM_DENIED, 0);
2445 if (client->mode & SILC_UMODE_ANONYMOUS) {
2446 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2447 SILC_STATUS_ERR_PERM_DENIED, 0);
2452 /* Update statistics */
2453 if (mask & SILC_UMODE_GONE) {
2454 if (!(client->mode & SILC_UMODE_GONE))
2455 server->stat.my_aways++;
2457 if (client->mode & SILC_UMODE_GONE)
2458 server->stat.my_aways--;
2461 /* Change the mode */
2462 client->mode = mask;
2464 /* Send UMODE change to primary router */
2465 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
2466 SILC_BROADCAST(server), client->id,
2469 /* Check if anyone is watching this nickname */
2470 if (server->server_type == SILC_ROUTER)
2471 silc_server_check_watcher_list(server, client, NULL,
2472 SILC_NOTIFY_TYPE_UMODE_CHANGE);
2475 /* Send command reply to sender */
2476 SILC_PUT32_MSB(client->mode, m);
2477 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
2478 SILC_STATUS_OK, 0, ident, 1,
2480 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2481 packet->data, packet->len, FALSE);
2482 silc_buffer_free(packet);
2485 silc_server_command_free(cmd);
2488 /* Server side command of CMODE. Changes channel mode */
2490 SILC_SERVER_CMD_FUNC(cmode)
2492 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2493 SilcServer server = cmd->server;
2494 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2495 SilcIDListData idata = (SilcIDListData)client;
2496 SilcChannelID *channel_id = NULL;
2497 SilcChannelEntry channel;
2498 SilcChannelClientEntry chl;
2499 SilcBuffer packet, cidp;
2500 unsigned char *tmp, *tmp_id, *tmp_mask;
2501 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
2502 SilcUInt32 mode_mask = 0, old_mask = 0, tmp_len, tmp_len2;
2503 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2504 bool set_mask = FALSE;
2505 SilcPublicKey founder_key = NULL;
2506 unsigned char *fkey = NULL;
2507 SilcUInt32 fkey_len = 0;
2510 silc_server_command_free(cmd);
2514 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 7);
2516 /* Get Channel ID */
2517 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2519 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2520 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2521 silc_server_command_free(cmd);
2524 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
2526 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2527 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2528 silc_server_command_free(cmd);
2532 /* Get channel entry */
2533 channel = silc_idlist_find_channel_by_id(server->local_list,
2536 channel = silc_idlist_find_channel_by_id(server->global_list,
2539 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2540 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
2542 silc_free(channel_id);
2543 silc_server_command_free(cmd);
2547 old_mask = channel->mode;
2549 /* Get the channel mode mask */
2550 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2552 SILC_GET32_MSB(mode_mask, tmp_mask);
2556 /* Check whether this client is on the channel */
2557 if (!silc_server_client_on_channel(client, channel, &chl)) {
2558 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2559 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
2563 /* Check that client has rights to change any requested channel modes */
2564 if (set_mask && !silc_server_check_cmode_rights(server, channel, chl,
2566 SILC_LOG_DEBUG(("Client does not have rights to change mode"));
2567 silc_server_command_send_status_reply(
2568 cmd, SILC_COMMAND_CMODE,
2569 (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) ?
2570 SILC_STATUS_ERR_NO_CHANNEL_PRIV :
2571 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV), 0);
2575 /* If mode mask was not sent as argument then merely return the current
2576 mode mask to the sender. */
2579 SILC_PUT32_MSB(channel->mode, m);
2580 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2581 SILC_STATUS_OK, 0, ident, 2,
2582 2, tmp_id, tmp_len2,
2584 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2585 packet->data, packet->len, FALSE);
2586 silc_buffer_free(packet);
2591 * Check the modes. Modes that requires nothing special operation are
2595 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2596 /* Channel uses private keys to protect traffic. Client(s) has set the
2597 key locally they want to use, server does not know that key. */
2598 /* Nothing interesting to do here */
2600 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2601 /* The mode is removed and we need to generate and distribute
2602 new channel key. Clients are not using private channel keys
2603 anymore after this. */
2605 /* Re-generate channel key */
2606 if (!silc_server_create_channel_key(server, channel, 0))
2609 /* Send the channel key. This sends it to our local clients and if
2610 we are normal server to our router as well. */
2611 silc_server_send_channel_key(server, NULL, channel,
2612 server->server_type == SILC_ROUTER ?
2613 FALSE : !server->standalone);
2615 cipher = channel->channel_key->cipher->name;
2616 hmac = (char *)silc_hmac_get_name(channel->hmac);
2620 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2621 /* User limit is set on channel */
2622 SilcUInt32 user_limit;
2624 /* Get user limit */
2625 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2627 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2628 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2629 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
2633 SILC_GET32_MSB(user_limit, tmp);
2634 channel->user_limit = user_limit;
2637 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2638 /* User limit mode is unset. Remove user limit */
2639 channel->user_limit = 0;
2642 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
2643 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
2644 /* Passphrase has been set to channel */
2646 /* Get the passphrase */
2647 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
2649 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2650 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
2654 /* Save the passphrase */
2655 passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
2658 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2659 /* Passphrase mode is unset. remove the passphrase */
2660 silc_free(channel->passphrase);
2661 channel->passphrase = NULL;
2665 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
2666 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
2667 /* Cipher to use protect the traffic */
2668 SilcCipher newkey, oldkey;
2671 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
2673 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2674 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
2678 /* Delete old cipher and allocate the new one */
2679 if (!silc_cipher_alloc(cipher, &newkey)) {
2680 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2681 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
2685 oldkey = channel->channel_key;
2686 channel->channel_key = newkey;
2688 /* Re-generate channel key */
2689 if (!silc_server_create_channel_key(server, channel, 0)) {
2690 /* We don't have new key, revert to old one */
2691 channel->channel_key = oldkey;
2695 /* Remove old channel key for good */
2696 silc_cipher_free(oldkey);
2698 /* Send the channel key. This sends it to our local clients and if
2699 we are normal server to our router as well. */
2700 silc_server_send_channel_key(server, NULL, channel,
2701 server->server_type == SILC_ROUTER ?
2702 FALSE : !server->standalone);
2705 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2706 /* Cipher mode is unset. Remove the cipher and revert back to
2708 SilcCipher newkey, oldkey;
2709 cipher = channel->cipher;
2711 /* Delete old cipher and allocate default one */
2712 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
2713 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2714 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
2718 oldkey = channel->channel_key;
2719 channel->channel_key = newkey;
2721 /* Re-generate channel key */
2722 if (!silc_server_create_channel_key(server, channel, 0)) {
2723 /* We don't have new key, revert to old one */
2724 channel->channel_key = oldkey;
2728 /* Remove old channel key for good */
2729 silc_cipher_free(oldkey);
2731 /* Send the channel key. This sends it to our local clients and if
2732 we are normal server to our router as well. */
2733 silc_server_send_channel_key(server, NULL, channel,
2734 server->server_type == SILC_ROUTER ?
2735 FALSE : !server->standalone);
2739 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
2740 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
2741 /* HMAC to use protect the traffic */
2742 unsigned char hash[32];
2746 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
2748 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2749 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
2753 /* Delete old hmac and allocate the new one */
2754 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
2755 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2756 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
2760 silc_hmac_free(channel->hmac);
2761 channel->hmac = newhmac;
2763 /* Set the HMAC key out of current channel key. The client must do
2765 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
2766 channel->key_len / 8, hash);
2767 silc_hmac_set_key(channel->hmac, hash,
2768 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
2769 memset(hash, 0, sizeof(hash));
2772 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
2773 /* Hmac mode is unset. Remove the hmac and revert back to
2776 unsigned char hash[32];
2777 hmac = channel->hmac_name;
2779 /* Delete old hmac and allocate default one */
2780 silc_hmac_free(channel->hmac);
2781 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
2782 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2783 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
2787 silc_hmac_free(channel->hmac);
2788 channel->hmac = newhmac;
2790 /* Set the HMAC key out of current channel key. The client must do
2792 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
2793 channel->key_len / 8,
2795 silc_hmac_set_key(channel->hmac, hash,
2796 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
2797 memset(hash, 0, sizeof(hash));
2801 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
2802 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2803 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
2804 /* Set the founder authentication */
2805 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
2807 silc_server_command_send_status_reply(
2808 cmd, SILC_COMMAND_CMODE,
2809 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
2813 /* Verify the payload before setting the mode */
2814 if (!silc_auth_verify_data(tmp, tmp_len, SILC_AUTH_PUBLIC_KEY,
2815 idata->public_key, 0, server->sha1hash,
2816 client->id, SILC_ID_CLIENT)) {
2817 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2818 SILC_STATUS_ERR_AUTH_FAILED,
2823 /* Save the public key */
2824 channel->founder_key = silc_pkcs_public_key_copy(idata->public_key);
2825 if (!channel->founder_key) {
2826 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2827 SILC_STATUS_ERR_AUTH_FAILED,
2832 founder_key = channel->founder_key;
2833 fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
2835 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2836 SILC_STATUS_ERR_AUTH_FAILED,
2838 silc_pkcs_public_key_free(channel->founder_key);
2839 channel->founder_key = NULL;
2845 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2846 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
2847 if (channel->founder_key)
2848 silc_pkcs_public_key_free(channel->founder_key);
2849 channel->founder_key = NULL;
2854 /* Finally, set the mode */
2855 old_mask = channel->mode = mode_mask;
2857 /* Send CMODE_CHANGE notify. */
2858 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2859 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2860 SILC_NOTIFY_TYPE_CMODE_CHANGE, 6,
2861 cidp->data, cidp->len,
2863 cipher, cipher ? strlen(cipher) : 0,
2864 hmac, hmac ? strlen(hmac) : 0,
2865 passphrase, passphrase ?
2866 strlen(passphrase) : 0,
2869 /* Set CMODE notify type to network */
2870 silc_server_send_notify_cmode(server, SILC_PRIMARY_ROUTE(server),
2871 SILC_BROADCAST(server), channel,
2872 mode_mask, client->id, SILC_ID_CLIENT,
2873 cipher, hmac, passphrase, founder_key);
2875 /* Send command reply to sender */
2876 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2877 SILC_STATUS_OK, 0, ident, 2,
2878 2, tmp_id, tmp_len2,
2880 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2881 packet->data, packet->len, FALSE);
2883 silc_buffer_free(packet);
2884 silc_buffer_free(cidp);
2887 channel->mode = old_mask;
2889 silc_free(channel_id);
2890 silc_server_command_free(cmd);
2893 /* Server side of CUMODE command. Changes client's mode on a channel. */
2895 SILC_SERVER_CMD_FUNC(cumode)
2897 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2898 SilcServer server = cmd->server;
2899 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2900 SilcIDListData idata = (SilcIDListData)client;
2901 SilcChannelID *channel_id;
2902 SilcClientID *client_id;
2903 SilcChannelEntry channel;
2904 SilcClientEntry target_client;
2905 SilcChannelClientEntry chl;
2906 SilcBuffer packet, idp;
2907 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
2908 SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
2910 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2911 SilcPublicKey founder_key = NULL;
2912 unsigned char *fkey = NULL;
2913 SilcUInt32 fkey_len = 0;
2918 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
2920 /* Get Channel ID */
2921 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
2923 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2924 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2927 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
2929 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2930 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2934 /* Get channel entry */
2935 channel = silc_idlist_find_channel_by_id(server->local_list,
2938 channel = silc_idlist_find_channel_by_id(server->global_list,
2941 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2942 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
2948 /* Check whether sender is on the channel */
2949 if (!silc_server_client_on_channel(client, channel, &chl)) {
2950 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2951 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
2954 sender_mask = chl->mode;
2956 /* Get the target client's channel mode mask */
2957 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2959 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2960 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2964 SILC_GET32_MSB(target_mask, tmp_mask);
2966 /* Get target Client ID */
2967 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2969 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2970 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
2973 client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
2975 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2976 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
2980 /* Get target client's entry */
2981 target_client = silc_idlist_find_client_by_id(server->local_list,
2982 client_id, TRUE, NULL);
2983 if (!target_client) {
2984 target_client = silc_idlist_find_client_by_id(server->global_list,
2985 client_id, TRUE, NULL);
2988 if (target_client != client &&
2989 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
2990 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
2991 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2992 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
2996 /* Check whether target client is on the channel */
2997 if (target_client != client) {
2998 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
2999 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3000 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL, 0);
3009 /* If the target client is founder, no one else can change their mode
3011 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
3012 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3013 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
3018 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
3019 if (target_client != client) {
3020 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3021 SILC_STATUS_ERR_NOT_YOU, 0);
3025 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
3026 /* The client tries to claim the founder rights. */
3027 unsigned char *tmp_auth;
3028 SilcUInt32 tmp_auth_len;
3029 SilcChannelClientEntry chl2;
3030 SilcHashTableList htl;
3032 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
3033 !channel->founder_key || !idata->public_key ||
3034 !silc_pkcs_public_key_compare(channel->founder_key,
3035 idata->public_key)) {
3036 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3037 SILC_STATUS_ERR_AUTH_FAILED, 0);
3041 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
3043 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3044 SILC_STATUS_ERR_AUTH_FAILED, 0);
3048 /* Verify the authentication payload */
3049 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len, SILC_AUTH_PUBLIC_KEY,
3050 channel->founder_key, 0, server->sha1hash,
3051 client->id, SILC_ID_CLIENT)) {
3052 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3053 SILC_STATUS_ERR_AUTH_FAILED, 0);
3058 founder_key = channel->founder_key;
3059 fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
3061 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3062 SILC_STATUS_ERR_AUTH_FAILED, 0);
3066 /* There cannot be anyone else as founder on the channel now. This
3067 client is definitely the founder due to this authentication */
3068 silc_hash_table_list(channel->user_list, &htl);
3069 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
3070 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
3071 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3072 silc_server_force_cumode_change(server, NULL, channel, chl2,
3076 silc_hash_table_list_reset(&htl);
3078 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
3081 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3082 if (target_client == client) {
3083 /* Remove channel founder rights from itself */
3084 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3087 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3088 SILC_STATUS_ERR_NOT_YOU, 0);
3094 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
3095 /* Promote to operator */
3096 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3097 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3098 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3099 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3100 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
3105 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
3109 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
3110 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3111 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3112 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3113 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
3118 /* Demote to normal user */
3119 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
3124 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
3125 if (target_client != client) {
3126 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3127 SILC_STATUS_ERR_NOT_YOU, 0);
3131 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
3132 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
3136 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
3137 if (target_client != client) {
3138 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3139 SILC_STATUS_ERR_NOT_YOU, 0);
3143 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
3148 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
3149 if (target_client != client) {
3150 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3151 SILC_STATUS_ERR_NOT_YOU, 0);
3155 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)) {
3156 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
3160 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
3161 if (target_client != client) {
3162 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3163 SILC_STATUS_ERR_NOT_YOU, 0);
3167 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
3172 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
3173 if (target_client != client) {
3174 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3175 SILC_STATUS_ERR_NOT_YOU, 0);
3179 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)) {
3180 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
3184 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
3185 if (target_client != client) {
3186 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3187 SILC_STATUS_ERR_NOT_YOU, 0);
3191 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
3196 if (target_mask & SILC_CHANNEL_UMODE_QUIET) {
3197 if (!(chl->mode & SILC_CHANNEL_UMODE_QUIET)) {
3198 if (client == target_client) {
3199 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3200 SILC_STATUS_ERR_PERM_DENIED, 0);
3203 chl->mode |= SILC_CHANNEL_UMODE_QUIET;
3207 if (chl->mode & SILC_CHANNEL_UMODE_QUIET) {
3208 if (client == target_client) {
3209 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3210 SILC_STATUS_ERR_PERM_DENIED, 0);
3213 chl->mode &= ~SILC_CHANNEL_UMODE_QUIET;
3218 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3219 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3221 /* Send notify to channel, notify only if mode was actually changed. */
3223 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3224 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
3225 idp->data, idp->len,
3230 /* Set CUMODE notify type to network */
3231 silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
3232 SILC_BROADCAST(server), channel,
3233 target_mask, client->id, SILC_ID_CLIENT,
3234 target_client->id, founder_key);
3237 /* Send command reply to sender */
3238 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
3239 SILC_STATUS_OK, 0, ident, 3,
3241 3, tmp_ch_id, tmp_ch_len,
3242 4, tmp_id, tmp_len);
3243 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3244 packet->data, packet->len, FALSE);
3246 silc_buffer_free(packet);
3247 silc_free(channel_id);
3248 silc_free(client_id);
3249 silc_buffer_free(idp);
3253 silc_server_command_free(cmd);
3256 /* Server side of KICK command. Kicks client out of channel. */
3258 SILC_SERVER_CMD_FUNC(kick)
3260 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3261 SilcServer server = cmd->server;
3262 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3263 SilcClientEntry target_client;
3264 SilcChannelID *channel_id;
3265 SilcClientID *client_id;
3266 SilcChannelEntry channel;
3267 SilcChannelClientEntry chl;
3269 SilcUInt32 tmp_len, target_idp_len;
3270 unsigned char *tmp, *comment, *target_idp;
3275 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
3277 /* Get Channel ID */
3278 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3280 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3281 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3284 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3286 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3287 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3291 /* Get channel entry */
3292 channel = silc_idlist_find_channel_by_id(server->local_list,
3295 channel = silc_idlist_find_channel_by_id(server->local_list,
3298 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3299 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
3305 /* Check whether sender is on the channel */
3306 if (!silc_server_client_on_channel(client, channel, &chl)) {
3307 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3308 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
3312 /* Check that the kicker is channel operator or channel founder */
3313 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
3314 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
3315 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3316 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
3320 /* Get target Client ID */
3321 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
3323 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3324 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
3327 client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
3329 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3330 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
3334 /* Get target client's entry */
3335 target_client = silc_idlist_find_client_by_id(server->local_list,
3336 client_id, TRUE, NULL);
3337 if (!target_client) {
3338 target_client = silc_idlist_find_client_by_id(server->global_list,
3339 client_id, TRUE, NULL);
3342 /* Check whether target client is on the channel */
3343 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
3344 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3345 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL,
3350 /* Check that the target client is not channel founder. Channel founder
3351 cannot be kicked from the channel. */
3352 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3353 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3354 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
3361 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3365 /* Send command reply to sender */
3366 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3369 /* Send KICKED notify to local clients on the channel */
3370 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3371 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3372 SILC_NOTIFY_TYPE_KICKED, 3,
3373 target_idp, target_idp_len,
3374 comment, comment ? strlen(comment) : 0,
3375 idp->data, idp->len);
3376 silc_buffer_free(idp);
3378 /* Send KICKED notify to primary route */
3379 silc_server_send_notify_kicked(server, SILC_PRIMARY_ROUTE(server),
3380 SILC_BROADCAST(server), channel,
3381 target_client->id, client->id, comment);
3383 /* Remove the client from the channel. If the channel does not exist
3384 after removing the client then the client kicked itself off the channel
3385 and we don't have to send anything after that. */
3386 if (!silc_server_remove_from_one_channel(server, NULL, channel,
3387 target_client, FALSE))
3390 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3391 /* Re-generate channel key */
3392 if (!silc_server_create_channel_key(server, channel, 0))
3395 /* Send the channel key to the channel. The key of course is not sent
3396 to the client who was kicked off the channel. */
3397 silc_server_send_channel_key(server, target_client->connection, channel,
3398 server->server_type == SILC_ROUTER ?
3399 FALSE : !server->standalone);
3403 silc_server_command_free(cmd);
3406 /* Server side of OPER command. Client uses this comand to obtain server
3407 operator privileges to this server/router. */
3409 SILC_SERVER_CMD_FUNC(oper)
3411 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3412 SilcServer server = cmd->server;
3413 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3414 unsigned char *username, *auth;
3416 SilcServerConfigAdmin *admin;
3417 SilcIDListData idata = (SilcIDListData)client;
3418 bool result = FALSE;
3419 SilcPublicKey cached_key;
3421 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
3424 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
3426 /* Get the username */
3427 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3429 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3430 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3435 /* Get the admin configuration */
3436 admin = silc_server_config_find_admin(server, cmd->sock->ip,
3437 username, client->nickname);
3439 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
3440 username, client->nickname);
3442 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3443 SILC_STATUS_ERR_AUTH_FAILED,
3449 /* Get the authentication payload */
3450 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3452 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3453 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3458 /* Verify the authentication data. If both passphrase and public key
3459 is set then try both of them. */
3460 if (admin->passphrase)
3461 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
3462 admin->passphrase, admin->passphrase_len,
3463 idata->hash, client->id, SILC_ID_CLIENT);
3464 if (!result && admin->publickeys) {
3465 cached_key = silc_server_get_public_key(server, admin->publickeys);
3468 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
3469 cached_key, 0, idata->hash,
3470 client->id, SILC_ID_CLIENT);
3473 /* Authentication failed */
3474 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3475 SILC_STATUS_ERR_AUTH_FAILED,
3480 /* Client is now server operator */
3481 client->mode |= SILC_UMODE_SERVER_OPERATOR;
3483 /* Update statistics */
3484 if (SILC_IS_LOCAL(client))
3485 server->stat.my_server_ops++;
3486 if (server->server_type == SILC_ROUTER)
3487 server->stat.server_ops++;
3489 /* Send UMODE change to primary router */
3490 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
3491 SILC_BROADCAST(server), client->id,
3494 /* Check if anyone is watching this nickname */
3495 if (server->server_type == SILC_ROUTER)
3496 silc_server_check_watcher_list(server, client, NULL,
3497 SILC_NOTIFY_TYPE_UMODE_CHANGE);
3499 /* Send reply to the sender */
3500 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3504 silc_server_command_free(cmd);
3507 SILC_TASK_CALLBACK(silc_server_command_detach_cb)
3509 SilcServer server = app_context;
3510 QuitInternal q = (QuitInternal)context;
3511 SilcClientID *client_id = (SilcClientID *)q->sock;
3512 SilcClientEntry client;
3513 SilcSocketConnection sock;
3515 client = silc_idlist_find_client_by_id(server->local_list, client_id,
3517 if (client && client->connection) {
3518 sock = client->connection;
3520 /* If there is pending outgoing data for the client then purge it
3521 to the network before closing connection. */
3522 silc_server_packet_queue_purge(server, sock);
3524 /* Close the connection on our side */
3525 client->router = NULL;
3526 client->connection = NULL;
3527 sock->user_data = NULL;
3528 silc_server_close_connection(server, sock);
3531 silc_free(client_id);
3535 SILC_TASK_CALLBACK(silc_server_command_detach_timeout)
3537 SilcServer server = app_context;
3538 QuitInternal q = (QuitInternal)context;
3539 SilcClientID *client_id = (SilcClientID *)q->sock;
3540 SilcClientEntry client;
3542 client = silc_idlist_find_client_by_id(server->local_list, client_id,
3544 if (client && client->mode & SILC_UMODE_DETACHED) {
3545 SILC_LOG_DEBUG(("Detach timeout"));
3546 silc_server_free_client_data(server, NULL, client, TRUE,
3550 silc_free(client_id);
3554 /* Server side of DETACH command. Detached the client from the network
3555 by closing the connection but preserving the session. */
3557 SILC_SERVER_CMD_FUNC(detach)
3559 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3560 SilcServer server = cmd->server;
3561 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3564 if (server->config->detach_disabled) {
3565 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
3566 SILC_STATUS_ERR_UNKNOWN_COMMAND, 0);
3570 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
3573 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
3575 /* Remove operator privileges, since the client may resume in some
3576 other server which to it does not have operator privileges. */
3577 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
3578 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
3580 /* Send the user mode notify to notify that client is detached */
3581 client->mode |= SILC_UMODE_DETACHED;
3582 client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
3583 client->data.status &= ~SILC_IDLIST_STATUS_NOATTR;
3584 client->last_command = 0;
3585 client->fast_command = 0;
3586 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
3587 SILC_BROADCAST(server), client->id,
3589 server->stat.my_detached++;
3591 /* Check if anyone is watching this nickname */
3592 if (server->server_type == SILC_ROUTER)
3593 silc_server_check_watcher_list(server, client, NULL,
3594 SILC_NOTIFY_TYPE_UMODE_CHANGE);
3596 q = silc_calloc(1, sizeof(*q));
3597 q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
3598 silc_schedule_task_add(server->schedule, 0, silc_server_command_detach_cb,
3599 q, 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
3601 if (server->config->detach_timeout) {
3602 q = silc_calloc(1, sizeof(*q));
3603 q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
3604 silc_schedule_task_add(server->schedule, 0,
3605 silc_server_command_detach_timeout,
3606 q, server->config->detach_timeout * 60,
3607 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
3610 /* Send reply to the sender */
3611 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
3615 silc_server_command_free(cmd);
3618 /* Server side of WATCH command. */
3620 SILC_SERVER_CMD_FUNC(watch)
3622 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3623 SilcServer server = cmd->server;
3624 char *add_nick, *del_nick;
3625 SilcUInt32 add_nick_len, del_nick_len, tmp_len;
3627 unsigned char hash[16], *tmp;
3628 SilcClientEntry client;
3629 SilcClientID *client_id = NULL;
3631 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WATCH, cmd, 1, 3);
3633 if (server->server_type == SILC_SERVER && !server->standalone) {
3634 if (!cmd->pending) {
3635 /* Send the command to router */
3637 SilcUInt16 old_ident;
3639 old_ident = silc_command_get_ident(cmd->payload);
3640 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3641 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3643 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
3644 SILC_PACKET_COMMAND, cmd->packet->flags,
3645 tmpbuf->data, tmpbuf->len, TRUE);
3647 /* Reprocess this packet after received reply from router */
3648 silc_server_command_pending(server, SILC_COMMAND_WATCH,
3649 silc_command_get_ident(cmd->payload),
3650 silc_server_command_watch,
3651 silc_server_command_dup(cmd));
3652 cmd->pending = TRUE;
3653 silc_command_set_ident(cmd->payload, old_ident);
3654 silc_buffer_free(tmpbuf);
3655 } else if (context2) {
3656 /* Received reply from router, just send same data to the client. */
3657 SilcServerCommandReplyContext reply = context2;
3659 silc_command_get_status(reply->payload, &status, NULL);
3660 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, status,
3667 /* We are router and keep the watch list for local cell */
3669 /* Get the client ID */
3670 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3672 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
3673 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3677 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3679 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
3680 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
3685 /* Get the client entry which must be in local list */
3686 client = silc_idlist_find_client_by_id(server->local_list,
3687 client_id, TRUE, NULL);
3689 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
3690 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
3696 add_nick = silc_argument_get_arg_type(cmd->args, 2, &add_nick_len);
3697 del_nick = silc_argument_get_arg_type(cmd->args, 3, &del_nick_len);
3698 if (!add_nick && !del_nick) {
3699 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
3700 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3705 if (add_nick && add_nick_len > 128)
3706 add_nick[128] = '\0';
3707 if (del_nick && del_nick_len > 128)
3708 del_nick[128] = '\0';
3710 memset(nick, 0, sizeof(nick));
3712 /* Add new nickname to be watched in our cell */
3714 if (silc_server_name_bad_chars(add_nick, strlen(add_nick)) == TRUE) {
3715 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
3716 SILC_STATUS_ERR_BAD_NICKNAME, 0);
3720 /* Hash the nick, we have the hash saved, not nicks because we can
3721 do one to one mapping to the nick from Client ID hash this way. */
3722 silc_to_lower(add_nick, nick, sizeof(nick) - 1);
3723 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
3725 /* Check whether this client is already watching this nickname */
3726 if (silc_hash_table_find_by_context(server->watcher_list, hash,
3728 /* Nickname is alredy being watched for this client */
3729 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
3730 SILC_STATUS_ERR_NICKNAME_IN_USE,
3735 /* Get the nickname from the watcher list and use the same key in
3736 new entries as well. If key doesn't exist then create it. */
3737 if (!silc_hash_table_find(server->watcher_list, hash, (void **)&tmp, NULL))
3738 tmp = silc_memdup(hash, CLIENTID_HASH_LEN);
3740 /* Add the client to the watcher list with the specified nickname hash. */
3741 silc_hash_table_add(server->watcher_list, tmp, client);
3744 /* Delete nickname from watch list */
3746 if (silc_server_name_bad_chars(del_nick, strlen(del_nick)) == TRUE) {
3747 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
3748 SILC_STATUS_ERR_BAD_NICKNAME, 0);
3752 /* Hash the nick, we have the hash saved, not nicks because we can
3753 do one to one mapping to the nick from Client ID hash this way. */
3754 silc_to_lower(del_nick, nick, sizeof(nick) - 1);
3755 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
3757 /* Check that this client is watching for this nickname */
3758 if (!silc_hash_table_find_by_context(server->watcher_list, hash,
3759 client, (void **)&tmp)) {
3760 /* Nickname is alredy being watched for this client */
3761 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
3762 SILC_STATUS_ERR_NO_SUCH_NICK, 0);
3766 /* Delete the nickname from the watcher list. */
3767 silc_hash_table_del_by_context(server->watcher_list, hash, client);
3769 /* Now check whether there still exists entries with this key, if not
3770 then free the key to not leak memory. */
3771 if (!silc_hash_table_find(server->watcher_list, hash, NULL, NULL))
3775 /* Distribute the watch list to backup routers too */
3776 if (server->backup) {
3778 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3779 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3780 silc_server_backup_send(server, NULL, SILC_PACKET_COMMAND,
3781 cmd->packet->flags, tmpbuf->data, tmpbuf->len,
3783 silc_buffer_free(tmpbuf);
3786 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
3790 silc_free(client_id);
3791 silc_server_command_free(cmd);
3794 /* Server side of SILCOPER command. Client uses this comand to obtain router
3795 operator privileges to this router. */
3797 SILC_SERVER_CMD_FUNC(silcoper)
3799 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3800 SilcServer server = cmd->server;
3801 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3802 unsigned char *username, *auth;
3804 SilcServerConfigAdmin *admin;
3805 SilcIDListData idata = (SilcIDListData)client;
3806 bool result = FALSE;
3807 SilcPublicKey cached_key;
3809 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
3812 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
3814 if (server->server_type != SILC_ROUTER) {
3815 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3816 SILC_STATUS_ERR_AUTH_FAILED, 0);
3820 /* Get the username */
3821 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3823 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3824 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3829 /* Get the admin configuration */
3830 admin = silc_server_config_find_admin(server, cmd->sock->ip,
3831 username, client->nickname);
3833 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
3834 username, client->nickname);
3836 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3837 SILC_STATUS_ERR_AUTH_FAILED, 0);
3842 /* Get the authentication payload */
3843 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3845 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3846 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3851 /* Verify the authentication data. If both passphrase and public key
3852 is set then try both of them. */
3853 if (admin->passphrase)
3854 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
3855 admin->passphrase, admin->passphrase_len,
3856 idata->hash, client->id, SILC_ID_CLIENT);
3857 if (!result && admin->publickeys) {
3858 cached_key = silc_server_get_public_key(server, admin->publickeys);
3861 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
3862 cached_key, 0, idata->hash,
3863 client->id, SILC_ID_CLIENT);
3866 /* Authentication failed */
3867 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3868 SILC_STATUS_ERR_AUTH_FAILED, 0);
3872 /* Client is now router operator */
3873 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
3875 /* Update statistics */
3876 if (SILC_IS_LOCAL(client))
3877 server->stat.my_router_ops++;
3878 if (server->server_type == SILC_ROUTER)
3879 server->stat.router_ops++;
3881 /* Send UMODE change to primary router */
3882 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
3883 SILC_BROADCAST(server), client->id,
3886 /* Check if anyone is watching this nickname */
3887 if (server->server_type == SILC_ROUTER)
3888 silc_server_check_watcher_list(server, client, NULL,
3889 SILC_NOTIFY_TYPE_UMODE_CHANGE);
3891 /* Send reply to the sender */
3892 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3896 silc_server_command_free(cmd);
3899 /* Server side of command BAN. This is used to manage the ban list of the
3900 channel. To add clients and remove clients from the ban list. */
3902 SILC_SERVER_CMD_FUNC(ban)
3904 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3905 SilcServer server = cmd->server;
3906 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3908 SilcChannelEntry channel;
3909 SilcChannelClientEntry chl;
3910 SilcChannelID *channel_id = NULL;
3911 unsigned char *id, *add, *del;
3912 SilcUInt32 id_len, tmp_len;
3913 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3915 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
3918 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
3920 /* Get Channel ID */
3921 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
3923 channel_id = silc_id_payload_parse_id(id, id_len, NULL);
3925 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
3926 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3931 /* Get channel entry. The server must know about the channel since the
3932 client is expected to be on the channel. */
3933 channel = silc_idlist_find_channel_by_id(server->local_list,
3936 channel = silc_idlist_find_channel_by_id(server->global_list,
3939 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
3940 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
3946 /* Check whether this client is on the channel */
3947 if (!silc_server_client_on_channel(client, channel, &chl)) {
3948 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
3949 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
3953 /* The client must be at least channel operator. */
3954 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3955 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
3956 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
3960 /* Get the new ban and add it to the ban list */
3961 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3963 if (!channel->ban_list)
3964 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
3966 channel->ban_list = silc_realloc(channel->ban_list,
3967 sizeof(*channel->ban_list) *
3969 strlen(channel->ban_list) + 2));
3970 if (add[tmp_len - 1] == ',')
3971 add[tmp_len - 1] = '\0';
3973 strncat(channel->ban_list, add, tmp_len);
3974 strncat(channel->ban_list, ",", 1);
3977 /* Get the ban to be removed and remove it from the list */
3978 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3979 if (del && channel->ban_list) {
3980 char *start, *end, *n;
3982 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
3983 silc_free(channel->ban_list);
3984 channel->ban_list = NULL;
3986 start = strstr(channel->ban_list, del);
3987 if (start && strlen(start) >= tmp_len) {
3988 end = start + tmp_len;
3989 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
3990 strncat(n, channel->ban_list, start - channel->ban_list);
3991 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
3993 silc_free(channel->ban_list);
3994 channel->ban_list = n;
3999 /* Send the BAN notify type to our primary router. */
4001 silc_server_send_notify_ban(server, SILC_PRIMARY_ROUTE(server),
4002 SILC_BROADCAST(server), channel, add, del);
4004 /* Send the reply back to the client */
4006 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4007 SILC_STATUS_OK, 0, ident, 2,
4009 3, channel->ban_list,
4011 strlen(channel->ban_list) -1 : 0);
4012 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4013 packet->data, packet->len, FALSE);
4015 silc_buffer_free(packet);
4018 silc_free(channel_id);
4019 silc_server_command_free(cmd);
4022 /* Server side command of LEAVE. Removes client from a channel. */
4024 SILC_SERVER_CMD_FUNC(leave)
4026 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4027 SilcServer server = cmd->server;
4028 SilcSocketConnection sock = cmd->sock;
4029 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4030 SilcChannelID *id = NULL;
4031 SilcChannelEntry channel;
4035 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !id_entry)
4038 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4040 /* Get Channel ID */
4041 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4043 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4044 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4047 id = silc_id_payload_parse_id(tmp, len, NULL);
4049 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4050 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4054 /* Get channel entry */
4055 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4057 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4059 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4060 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4066 /* Check whether this client is on the channel */
4067 if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
4068 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4069 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4073 /* Notify routers that they should remove this client from their list
4074 of clients on the channel. Send LEAVE notify type. */
4075 silc_server_send_notify_leave(server, SILC_PRIMARY_ROUTE(server),
4076 SILC_BROADCAST(server), channel, id_entry->id);
4078 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4079 SILC_STATUS_OK, 0, 2, tmp, len);
4081 /* Remove client from channel */
4082 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4084 /* If the channel does not exist anymore we won't send anything */
4087 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4088 /* Re-generate channel key */
4089 if (!silc_server_create_channel_key(server, channel, 0))
4092 /* Send the channel key */
4093 silc_server_send_channel_key(server, NULL, channel,
4094 server->server_type == SILC_ROUTER ?
4095 FALSE : !server->standalone);
4100 silc_server_command_free(cmd);
4103 /* Server side of command USERS. Resolves clients and their USERS currently
4104 joined on the requested channel. The list of Client ID's and their modes
4105 on the channel is sent back. */
4107 SILC_SERVER_CMD_FUNC(users)
4109 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4110 SilcServer server = cmd->server;
4111 SilcChannelEntry channel;
4112 SilcChannelID *id = NULL;
4113 SilcBuffer packet, idp;
4114 unsigned char *channel_id;
4115 SilcUInt32 channel_id_len;
4116 SilcBuffer client_id_list;
4117 SilcBuffer client_mode_list;
4118 unsigned char lc[4];
4119 SilcUInt32 list_count = 0;
4120 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4123 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
4125 /* Get Channel ID */
4126 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4128 /* Get channel name */
4129 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
4131 if (!channel_id && !channel_name) {
4132 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4133 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4138 id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
4140 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4141 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4146 /* If we are server and we don't know about this channel we will send
4147 the command to our router. If we know about the channel then we also
4148 have the list of users already. */
4150 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4152 channel = silc_idlist_find_channel_by_name(server->local_list,
4153 channel_name, NULL);
4155 if (!channel || (!server->standalone && (channel->disabled ||
4156 !channel->users_resolved))) {
4157 if (server->server_type != SILC_ROUTER && !server->standalone &&
4161 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4162 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4164 /* Send USERS command */
4165 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
4166 SILC_PACKET_COMMAND, cmd->packet->flags,
4167 tmpbuf->data, tmpbuf->len, TRUE);
4169 /* Reprocess this packet after received reply */
4170 silc_server_command_pending(server, SILC_COMMAND_USERS,
4171 silc_command_get_ident(cmd->payload),
4172 silc_server_command_users,
4173 silc_server_command_dup(cmd));
4174 cmd->pending = TRUE;
4175 silc_command_set_ident(cmd->payload, ident);
4176 silc_buffer_free(tmpbuf);
4181 /* Check the global list as well. */
4183 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4185 channel = silc_idlist_find_channel_by_name(server->global_list,
4186 channel_name, NULL);
4188 /* Channel really does not exist */
4189 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4190 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4196 /* If the channel is private or secret do not send anything, unless the
4197 user requesting this command is on the channel or is server */
4198 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
4199 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
4200 && !silc_server_client_on_channel(cmd->sock->user_data, channel,
4202 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4203 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4209 /* Get the users list */
4210 if (!silc_server_get_users_on_channel(server, channel, &client_id_list,
4211 &client_mode_list, &list_count)) {
4213 client_id_list = NULL;
4214 client_mode_list = NULL;
4218 SILC_PUT32_MSB(list_count, lc);
4221 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
4222 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
4223 SILC_STATUS_OK, 0, ident, 4,
4224 2, idp->data, idp->len,
4227 client_id_list->data : NULL,
4229 client_id_list->len : 0,
4230 5, client_mode_list ?
4231 client_mode_list->data : NULL,
4233 client_mode_list->len : 0);
4234 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4235 packet->data, packet->len, FALSE);
4237 silc_buffer_free(idp);
4238 silc_buffer_free(packet);
4240 silc_buffer_free(client_id_list);
4241 if (client_mode_list)
4242 silc_buffer_free(client_mode_list);
4246 silc_server_command_free(cmd);
4249 /* Server side of command GETKEY. This fetches the client's public key
4250 from the server where to the client is connected. */
4252 SILC_SERVER_CMD_FUNC(getkey)
4254 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4255 SilcServer server = cmd->server;
4257 SilcClientEntry client;
4258 SilcServerEntry server_entry;
4259 SilcClientID *client_id = NULL;
4260 SilcServerID *server_id = NULL;
4261 SilcIDPayload idp = NULL;
4262 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4263 unsigned char *tmp, *pkdata;
4264 SilcUInt32 tmp_len, pklen;
4265 SilcBuffer pk = NULL;
4267 SilcPublicKey public_key;
4269 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4271 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4272 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4276 idp = silc_id_payload_parse(tmp, tmp_len);
4278 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4279 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4284 id_type = silc_id_payload_get_type(idp);
4285 if (id_type == SILC_ID_CLIENT) {
4286 client_id = silc_id_payload_get_id(idp);
4288 /* If the client is not found from local list there is no chance it
4289 would be locally connected client so send the command further. */
4290 client = silc_idlist_find_client_by_id(server->local_list,
4291 client_id, TRUE, NULL);
4293 client = silc_idlist_find_client_by_id(server->global_list,
4294 client_id, TRUE, NULL);
4296 if ((!client && !cmd->pending && !server->standalone) ||
4297 (client && !client->connection && !cmd->pending &&
4298 !(client->mode & SILC_UMODE_DETACHED)) ||
4299 (client && !client->data.public_key && !cmd->pending)) {
4301 SilcUInt16 old_ident;
4302 SilcSocketConnection dest_sock;
4304 dest_sock = silc_server_get_client_route(server, NULL, 0,
4305 client_id, NULL, NULL);
4309 old_ident = silc_command_get_ident(cmd->payload);
4310 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4311 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4313 silc_server_packet_send(server, dest_sock,
4314 SILC_PACKET_COMMAND, cmd->packet->flags,
4315 tmpbuf->data, tmpbuf->len, TRUE);
4317 /* Reprocess this packet after received reply from router */
4318 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
4319 silc_command_get_ident(cmd->payload),
4320 silc_server_command_getkey,
4321 silc_server_command_dup(cmd));
4322 cmd->pending = TRUE;
4323 silc_command_set_ident(cmd->payload, old_ident);
4324 silc_buffer_free(tmpbuf);
4329 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4330 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
4335 /* The client is locally connected, just get the public key and
4336 send it back. If they key does not exist then do not send it,
4337 send just OK reply */
4338 public_key = client->data.public_key;
4343 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
4344 pk = silc_buffer_alloc(4 + tmp_len);
4345 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
4346 silc_buffer_format(pk,
4347 SILC_STR_UI_SHORT(tmp_len),
4348 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
4349 SILC_STR_UI_XNSTRING(tmp, tmp_len),
4355 } else if (id_type == SILC_ID_SERVER) {
4356 server_id = silc_id_payload_get_id(idp);
4358 /* If the server is not found from local list there is no chance it
4359 would be locally connected server so send the command further. */
4360 server_entry = silc_idlist_find_server_by_id(server->local_list,
4361 server_id, TRUE, NULL);
4363 server_entry = silc_idlist_find_server_by_id(server->global_list,
4364 server_id, TRUE, NULL);
4366 if (server_entry != server->id_entry &&
4367 ((!server_entry && !cmd->pending && !server->standalone) ||
4368 (server_entry && !server_entry->connection && !cmd->pending &&
4369 !server->standalone) ||
4370 (server_entry && !server_entry->data.public_key && !cmd->pending &&
4371 !server->standalone))) {
4373 SilcUInt16 old_ident;
4375 old_ident = silc_command_get_ident(cmd->payload);
4376 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4377 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4379 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
4380 SILC_PACKET_COMMAND, cmd->packet->flags,
4381 tmpbuf->data, tmpbuf->len, TRUE);
4383 /* Reprocess this packet after received reply from router */
4384 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
4385 silc_command_get_ident(cmd->payload),
4386 silc_server_command_getkey,
4387 silc_server_command_dup(cmd));
4388 cmd->pending = TRUE;
4389 silc_command_set_ident(cmd->payload, old_ident);
4390 silc_buffer_free(tmpbuf);
4394 if (!server_entry) {
4395 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4396 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
4401 /* If they key does not exist then do not send it, send just OK reply */
4402 public_key = (!server_entry->data.public_key ?
4403 (server_entry == server->id_entry ? server->public_key :
4404 NULL) : server_entry->data.public_key);
4409 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
4410 pk = silc_buffer_alloc(4 + tmp_len);
4411 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
4412 silc_buffer_format(pk,
4413 SILC_STR_UI_SHORT(tmp_len),
4414 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
4415 SILC_STR_UI_XNSTRING(tmp, tmp_len),
4425 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4426 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
4427 SILC_STATUS_OK, 0, ident,
4431 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4432 packet->data, packet->len, FALSE);
4433 silc_buffer_free(packet);
4436 silc_buffer_free(pk);
4440 silc_id_payload_free(idp);
4441 silc_free(client_id);
4442 silc_free(server_id);
4443 silc_server_command_free(cmd);
4447 /* Private range commands, specific to this implementation */
4449 /* Server side command of CONNECT. Connects us to the specified remote
4450 server or router. */
4452 SILC_SERVER_CMD_FUNC(connect)
4454 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4455 SilcServer server = cmd->server;
4456 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4457 unsigned char *tmp, *host;
4459 SilcUInt32 port = SILC_PORT;
4461 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
4464 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
4466 /* Check whether client has the permissions. */
4467 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
4468 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
4469 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
4470 SILC_STATUS_ERR_NO_SERVER_PRIV, 0);
4474 if (server->server_type == SILC_ROUTER &&
4475 client->mode & SILC_UMODE_SERVER_OPERATOR) {
4476 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
4477 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
4481 /* Get the remote server */
4482 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4484 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
4485 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4491 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4493 SILC_GET32_MSB(port, tmp);
4495 /* Create the connection. It is done with timeout and is async. */
4496 silc_server_create_connection(server, host, port);
4498 /* Send reply to the sender */
4499 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
4503 silc_server_command_free(cmd);
4506 /* Server side command of CLOSE. Closes connection to a specified server. */
4508 SILC_SERVER_CMD_FUNC(close)
4510 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4511 SilcServer server = cmd->server;
4512 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4513 SilcServerEntry server_entry;
4514 SilcSocketConnection sock;
4517 unsigned char *name;
4518 SilcUInt32 port = SILC_PORT;
4520 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
4523 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
4525 /* Check whether client has the permissions. */
4526 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
4527 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
4528 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
4529 SILC_STATUS_ERR_NO_SERVER_PRIV,
4534 /* Get the remote server */
4535 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4537 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
4538 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4544 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4546 SILC_GET32_MSB(port, tmp);
4548 server_entry = silc_idlist_find_server_by_conn(server->local_list,
4549 name, port, FALSE, NULL);
4551 server_entry = silc_idlist_find_server_by_conn(server->global_list,
4552 name, port, FALSE, NULL);
4553 if (!server_entry) {
4554 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
4555 SILC_STATUS_ERR_NO_SERVER_ID, 0);
4559 if (server_entry == server->id_entry) {
4560 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
4561 SILC_STATUS_ERR_NO_SERVER_ID, 0);
4565 /* Send reply to the sender */
4566 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
4569 /* Close the connection to the server */
4570 sock = (SilcSocketConnection)server_entry->connection;
4572 /* If we shutdown primary router connection manually then don't trigger
4573 any reconnect or backup router connections, by setting the router
4575 if (server->router == server_entry) {
4576 server->id_entry->router = NULL;
4577 server->router = NULL;
4578 server->standalone = TRUE;
4580 silc_server_free_sock_user_data(server, sock, NULL);
4581 silc_server_close_connection(server, sock);
4584 silc_server_command_free(cmd);
4587 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4588 active connections. */
4590 SILC_SERVER_CMD_FUNC(shutdown)
4592 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4593 SilcServer server = cmd->server;
4594 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4596 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
4599 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
4601 /* Check whether client has the permission. */
4602 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
4603 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
4604 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
4605 SILC_STATUS_ERR_NO_SERVER_PRIV,
4610 /* Send reply to the sender */
4611 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
4614 /* Then, gracefully, or not, bring the server down. */
4615 silc_server_stop(server);
4619 silc_server_command_free(cmd);