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; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
22 #include "serverincludes.h"
23 #include "server_internal.h"
25 static int silc_server_is_registered(SilcServer server,
26 SilcSocketConnection sock,
27 SilcServerCommandContext cmd,
30 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
35 silc_server_command_send_status_data(SilcServerCommandContext cmd,
40 const unsigned char *arg,
43 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
44 SilcServerCommandReplyContext cmdr,
46 SILC_TASK_CALLBACK(silc_server_command_process_timeout);
48 /* Server command list. */
49 SilcServerCommand silc_command_list[] =
51 SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
52 SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
53 SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
54 SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
55 SILC_SERVER_CMD(list, LIST, SILC_CF_LAG_STRICT | SILC_CF_REG),
56 SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
57 SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
58 SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
59 SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG_STRICT | SILC_CF_REG | SILC_CF_OPER),
60 SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
61 SILC_SERVER_CMD(stats, STATS, SILC_CF_LAG | SILC_CF_REG),
62 SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
63 SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
64 SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG_STRICT | SILC_CF_REG),
65 SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
66 SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
67 SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG_STRICT | SILC_CF_REG),
68 SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
69 SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
70 SILC_SERVER_CMD(ban, BAN, SILC_CF_LAG_STRICT | SILC_CF_REG),
71 SILC_SERVER_CMD(detach, DETACH, SILC_CF_LAG_STRICT | SILC_CF_REG),
72 SILC_SERVER_CMD(watch, WATCH, SILC_CF_LAG | SILC_CF_REG),
73 SILC_SERVER_CMD(silcoper, SILCOPER,
74 SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
75 SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
76 SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
77 SILC_SERVER_CMD(getkey, GETKEY, SILC_CF_LAG | SILC_CF_REG),
79 SILC_SERVER_CMD(connect, PRIV_CONNECT,
80 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
81 SILC_SERVER_CMD(close, PRIV_CLOSE,
82 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
83 SILC_SERVER_CMD(shutdown, PRIV_SHUTDOWN, SILC_CF_LAG | SILC_CF_REG |
89 /* Performs several checks to the command. It first checks whether this
90 command was called as pending command callback. If it was then it checks
91 whether error occurred in the command reply where the pending command
94 It also checks that the requested command includes correct amount
96 #define SILC_SERVER_COMMAND_CHECK(command, context, min, max) \
100 if (silc_server_command_pending_error_check(cmd, context2, command)) { \
101 SILC_LOG_DEBUG(("Error occurred in command reply, command not called")); \
102 silc_server_command_free(cmd); \
106 _argc = silc_argument_get_arg_num(cmd->args); \
108 SILC_LOG_DEBUG(("Not enough parameters in command")); \
109 silc_server_command_send_status_reply(cmd, command, \
110 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, \
112 silc_server_command_free(cmd); \
116 SILC_LOG_DEBUG(("Too many parameters in command")); \
117 silc_server_command_send_status_reply(cmd, command, \
118 SILC_STATUS_ERR_TOO_MANY_PARAMS, \
120 silc_server_command_free(cmd); \
125 /* Returns TRUE if the connection is registered. Unregistered connections
126 usually cannot send commands hence the check. */
128 static int silc_server_is_registered(SilcServer server,
129 SilcSocketConnection sock,
130 SilcServerCommandContext cmd,
133 SilcIDListData idata = (SilcIDListData)sock->user_data;
138 if (idata->status & SILC_IDLIST_STATUS_REGISTERED)
141 silc_server_command_send_status_reply(cmd, command,
142 SILC_STATUS_ERR_NOT_REGISTERED, 0);
146 /* Internal context to hold data when executed command with timeout. */
148 SilcServerCommandContext ctx;
149 SilcServerCommand *cmd;
150 } *SilcServerCommandTimeout;
152 /* Timeout callback to process commands with timeout for client. Client's
153 commands are always executed with timeout. */
155 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
157 SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
158 SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data;
161 SILC_LOG_DEBUG(("Client entry is invalid"));
162 silc_server_command_free(timeout->ctx);
166 /* Update access time */
167 client->last_command = time(NULL);
169 if (!(timeout->cmd->flags & SILC_CF_REG)) {
170 SILC_LOG_DEBUG(("Calling %s command",
171 silc_get_command_name(timeout->cmd->cmd)));
172 timeout->cmd->cb(timeout->ctx, NULL);
173 } else if (silc_server_is_registered(timeout->ctx->server,
176 timeout->cmd->cmd)) {
177 SILC_LOG_DEBUG(("Calling %s command",
178 silc_get_command_name(timeout->cmd->cmd)));
179 timeout->cmd->cb(timeout->ctx, NULL);
181 SILC_LOG_DEBUG(("Client is not registered"));
182 silc_server_command_free(timeout->ctx);
188 /* Processes received command packet. */
190 void silc_server_command_process(SilcServer server,
191 SilcSocketConnection sock,
192 SilcPacketContext *packet)
194 SilcServerCommandContext ctx;
195 SilcServerCommand *cmd;
198 /* Allocate command context. This must be free'd by the
199 command routine receiving it. */
200 ctx = silc_server_command_alloc();
201 ctx->server = server;
202 ctx->sock = silc_socket_dup(sock);
203 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
205 /* Parse the command payload in the packet */
206 ctx->payload = silc_command_payload_parse(packet->buffer->data,
207 packet->buffer->len);
209 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
210 silc_packet_context_free(packet);
211 silc_socket_free(ctx->sock);
215 ctx->args = silc_command_get_args(ctx->payload);
217 /* Get the command */
218 command = silc_command_get(ctx->payload);
219 for (cmd = silc_command_list; cmd->cb; cmd++)
220 if (cmd->cmd == command)
223 if (!cmd || !cmd->cb) {
224 SILC_LOG_DEBUG(("Unknown command %d", command));
225 silc_server_command_send_status_reply(ctx, command,
226 SILC_STATUS_ERR_UNKNOWN_COMMAND, 0);
227 silc_server_command_free(ctx);
231 /* Execute client's commands always with timeout. Normally they are
232 executed with zero (0) timeout but if client is sending command more
233 frequently than once in 2 seconds, then the timeout may be 0 to 2
235 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
236 SilcClientEntry client = (SilcClientEntry)sock->user_data;
237 SilcServerCommandTimeout timeout;
241 SILC_LOG_DEBUG(("Client entry is invalid"));
242 silc_server_command_free(ctx);
245 timeout = silc_calloc(1, sizeof(*timeout));
249 if (client->last_command && (time(NULL) - client->last_command) < 2) {
250 client->fast_command++;
253 if (client->fast_command - 2 <= 0)
254 client->fast_command = 0;
256 client->fast_command -= 2;
260 if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
261 (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
262 silc_schedule_task_add(server->schedule, sock->sock,
263 silc_server_command_process_timeout, timeout,
264 (client->fast_command < 3 ? 0 :
265 2 - (time(NULL) - client->last_command)),
266 (client->fast_command < 3 ? 200000 : 0),
267 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
269 silc_schedule_task_add(server->schedule, sock->sock,
270 silc_server_command_process_timeout, timeout,
271 0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
275 /* Execute for server */
277 if (!(cmd->flags & SILC_CF_REG)) {
278 SILC_LOG_DEBUG(("Calling %s command", silc_get_command_name(cmd->cmd)));
280 } else if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) {
281 SILC_LOG_DEBUG(("Calling %s command", silc_get_command_name(cmd->cmd)));
284 SILC_LOG_DEBUG(("Server is not registered"));
285 silc_server_command_free(ctx);
289 /* Allocate Command Context */
291 SilcServerCommandContext silc_server_command_alloc()
293 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
298 /* Free's the command context allocated before executing the command */
300 void silc_server_command_free(SilcServerCommandContext ctx)
303 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
305 if (ctx->users < 1) {
307 silc_command_payload_free(ctx->payload);
309 silc_packet_context_free(ctx->packet);
311 silc_socket_free(ctx->sock); /* Decrease reference counter */
316 /* Duplicate Command Context by adding reference counter. The context won't
317 be free'd untill it hits zero. */
319 SilcServerCommandContext
320 silc_server_command_dup(SilcServerCommandContext ctx)
323 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
328 /* Timeout for pending command. If reply to pending command never arrives
329 this is called to free resources. */
331 SILC_TASK_CALLBACK(silc_server_command_pending_timeout)
333 SilcServer server = app_context;
334 SilcServerCommandPending *reply = context;
335 SilcServerCommandReplyContext cmdr;
339 SILC_LOG_DEBUG(("Timeout pending command"));
341 /* Allocate temporary and bogus command reply context */
342 cmdr = silc_calloc(1, sizeof(*cmdr));
343 cmdr->server = server;
344 cmdr->ident = reply->ident;
346 /* Check for pending commands and mark to be exeucted */
348 silc_server_command_pending_check(server, reply->reply_cmd,
349 reply->ident, &cmdr->callbacks_count);
351 /* Create bogus command reply with an error inside */
353 silc_command_reply_payload_encode_va(reply->reply_cmd,
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 /******************************************************************************
557 ******************************************************************************/
566 #define ADD_ERROR(errptr, errptr_count, _id, _id_type, _index, _status) \
568 errptr = silc_realloc(errptr, sizeof(*errptr) * (errptr_count + 1)); \
571 errptr[errptr_count].id = _id; \
572 errptr[errptr_count].id_type = _id_type; \
573 errptr[errptr_count].index = _index; \
574 errptr[errptr_count].error = _status; \
579 silc_server_command_whois_parse(SilcServerCommandContext cmd,
580 SilcClientID ***client_id,
581 SilcUInt32 *client_id_count,
585 ResolveError *error_client,
586 SilcUInt32 *error_client_count,
591 SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
595 /* If client ID is in the command it must be used instead of nickname */
596 tmp = silc_argument_get_arg_type(cmd->args, 4, &len);
598 /* No ID, get the nickname@server string and parse it. */
599 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
601 silc_parse_userfqdn(tmp, nickname, server_name);
603 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
604 SILC_STATUS_ERR_BAD_NICKNAME, 0);
608 /* Command includes ID, we must use that. Take all ID's from the
610 for (k = 0, i = 0; i < argc; i++) {
611 tmp = silc_argument_get_arg_type(cmd->args, i + 4, &len);
614 id = silc_id_payload_parse_id(tmp, len, NULL);
616 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
617 (*client_id_count + 1));
618 (*client_id)[k] = id;
619 (*client_id_count)++;
622 ADD_ERROR((*error_client), (*error_client_count), NULL, 0, i + 4,
623 SILC_STATUS_ERR_BAD_CLIENT_ID);
628 /* Get the max count of reply messages allowed */
629 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
631 SILC_GET32_MSB(*count, tmp);
635 /* Get requested attributes if set */
636 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
638 *attrs = silc_attribute_payload_parse_list(tmp, len);
643 /* Resolve context used by both WHOIS and IDENTIFY commands */
645 SilcSocketConnection sock;
647 unsigned char **res_argv;
648 SilcUInt32 *res_argv_lens;
649 SilcUInt32 *res_argv_types;
651 SilcUInt32 res_timeout;
652 } *SilcServerResolveContext;
655 silc_server_command_whois_check(SilcServerCommandContext cmd,
656 SilcClientEntry *clients,
657 SilcUInt32 clients_count,
660 SilcServer server = cmd->server;
661 SilcClientEntry entry;
662 SilcServerResolveContext resolve = NULL, r = NULL;
663 SilcUInt32 resolve_count = 0;
667 SILC_LOG_DEBUG(("Start"));
669 for (i = 0; i < clients_count; i++) {
674 /* If requested attributes is set then we always resolve the client
675 information, if not then check whether the entry is complete or not
676 and decide whether we need to resolve or not. Usually attributes
677 are not present so the this test is performed all the time. */
679 if ((entry->nickname && entry->username && entry->userinfo) ||
680 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
684 /* If we are normal server, and we've not resolved this client from
685 router and it is global client, we'll check whether it is on some
686 channel. If not then we cannot be sure about its validity, and
687 we'll resolve it from router. */
688 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
689 entry->connection || silc_hash_table_count(entry->channels))
694 /* When requested attributes is present and local client is detached
695 we cannot send the command to the client, we'll reply on behalf of
696 the client instead. */
697 if (attrs && SILC_IS_LOCAL(entry) && entry->mode & SILC_UMODE_DETACHED)
700 /* We need to resolve this entry since it is not complete */
702 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
703 /* The entry is being resolved (and we are not the resolver) so attach
704 to the command reply and we're done with this one. */
705 silc_server_command_pending(server, SILC_COMMAND_NONE,
706 entry->resolve_cmd_ident,
707 silc_server_command_whois,
708 silc_server_command_dup(cmd));
712 SilcSocketConnection sock;
714 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
715 /* We've resolved this and it still is not ready. We'll return
716 and are that this will be handled again after it is resolved. */
717 for (i = 0; i < resolve_count; i++) {
718 for (k = 0; k < r->res_argc; k++)
719 silc_free(r->res_argv[k]);
720 silc_free(r->res_argv);
721 silc_free(r->res_argv_lens);
722 silc_free(r->res_argv_types);
728 /* We'll resolve this client now */
730 sock = (SILC_IS_LOCAL(entry) ? entry->connection :
731 entry->router->connection);
736 for (k = 0; k < resolve_count; k++) {
737 if (resolve[k].sock == sock) {
744 resolve = silc_realloc(resolve, sizeof(*resolve) *
745 (resolve_count + 1));
746 r = &resolve[resolve_count];
747 memset(r, 0, sizeof(*r));
749 r->ident = ++server->cmd_ident;
750 if (SILC_IS_LOCAL(entry))
757 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
759 r->res_argv_lens = silc_realloc(r->res_argv_lens,
760 sizeof(*r->res_argv_lens) *
762 r->res_argv_types = silc_realloc(r->res_argv_types,
763 sizeof(*r->res_argv_types) *
765 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
766 r->res_argv[r->res_argc] = silc_calloc(idp->len,
767 sizeof(**r->res_argv));
768 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
769 r->res_argv_lens[r->res_argc] = idp->len;
770 r->res_argv_types[r->res_argc] = r->res_argc + 4;
772 silc_buffer_free(idp);
774 entry->resolve_cmd_ident = r->ident;
775 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
776 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
780 /* Do the resolving */
781 for (i = 0; i < resolve_count; i++) {
783 unsigned char *attrs_buf;
784 SilcUInt32 attrs_buf_len;
788 /* If attributes were present put them to this resolving as well */
790 attrs_buf = silc_argument_get_arg_type(cmd->args, 3, &attrs_buf_len);
792 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
794 r->res_argv_lens = silc_realloc(r->res_argv_lens,
795 sizeof(*r->res_argv_lens) *
797 r->res_argv_types = silc_realloc(r->res_argv_types,
798 sizeof(*r->res_argv_types) *
800 r->res_argv[r->res_argc] = silc_memdup(attrs_buf, attrs_buf_len);
801 r->res_argv_lens[r->res_argc] = attrs_buf_len;
802 r->res_argv_types[r->res_argc] = 3;
807 /* Send WHOIS command */
808 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
809 r->res_argc, r->res_argv,
813 silc_server_packet_send(server, r->sock, SILC_PACKET_COMMAND,
814 cmd->packet->flags, res_cmd->data,
815 res_cmd->len, FALSE);
817 /* Reprocess this packet after received reply */
818 silc_server_command_pending_timed(server, SILC_COMMAND_WHOIS, r->ident,
819 silc_server_command_whois,
820 silc_server_command_dup(cmd),
824 silc_buffer_free(res_cmd);
825 for (k = 0; k < r->res_argc; k++)
826 silc_free(r->res_argv[k]);
827 silc_free(r->res_argv);
828 silc_free(r->res_argv_lens);
829 silc_free(r->res_argv_types);
838 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
839 SilcClientEntry *clients,
840 SilcUInt32 clients_count,
842 SilcUInt32 errors_count,
843 int count, const char *nickname,
844 SilcClientID **client_ids)
846 SilcServer server = cmd->server;
848 int i, k, valid_count = clients_count;
850 SilcBuffer packet, idp, channels, umode_list = NULL;
851 SilcClientEntry entry;
853 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
854 char nh[256], uh[256];
855 unsigned char idle[4], mode[4];
856 unsigned char *fingerprint, fempty[20];
857 SilcSocketConnection hsock;
860 /* Process only valid clients and ignore those that are not registered.
861 This is checked with nickname only because when resolved client IDs
862 we check that they are registered earlier. */
864 for (i = 0; i < clients_count; i++)
865 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
871 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
872 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
873 3, nickname, strlen(nickname));
878 memset(fempty, 0, sizeof(fempty));
880 /* Start processing found clients. */
881 status = SILC_STATUS_OK;
883 status = SILC_STATUS_LIST_START;
885 for (i = 0, k = 0; i < clients_count; i++) {
891 status = SILC_STATUS_LIST_ITEM;
892 if (valid_count > 1 && k == valid_count - 1 && !errors_count)
893 status = SILC_STATUS_LIST_END;
894 if (count && k - 1 == count)
895 status = SILC_STATUS_LIST_END;
897 /* Send WHOIS reply */
898 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
899 tmp = silc_argument_get_first_arg(cmd->args, NULL);
901 memset(uh, 0, sizeof(uh));
902 memset(nh, 0, sizeof(nh));
903 memset(idle, 0, sizeof(idle));
905 strncat(nh, entry->nickname, strlen(entry->nickname));
906 if (!strchr(entry->nickname, '@')) {
908 if (entry->servername) {
909 strncat(nh, entry->servername, strlen(entry->servername));
911 len = entry->router ? strlen(entry->router->server_name) :
912 strlen(server->server_name);
913 strncat(nh, entry->router ? entry->router->server_name :
914 server->server_name, len);
918 strncat(uh, entry->username, strlen(entry->username));
919 if (!strchr(entry->username, '@') && entry->connection) {
921 hsock = (SilcSocketConnection)entry->connection;
922 len = strlen(hsock->hostname);
923 strncat(uh, hsock->hostname, len);
926 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
927 channels = silc_server_get_client_channel_list(server, entry, FALSE,
930 channels = silc_server_get_client_channel_list(server, entry, TRUE,
933 if (memcmp(entry->data.fingerprint, fempty, sizeof(fempty)))
934 fingerprint = entry->data.fingerprint;
938 SILC_PUT32_MSB(entry->mode, mode);
939 if (entry->connection)
940 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
943 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
945 2, idp->data, idp->len,
949 strlen(entry->userinfo),
950 6, channels ? channels->data : NULL,
951 channels ? channels->len : 0,
955 fingerprint ? 20 : 0,
956 10, umode_list ? umode_list->data :
957 NULL, umode_list ? umode_list->len :
960 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
961 0, packet->data, packet->len, FALSE);
963 silc_buffer_free(packet);
964 silc_buffer_free(idp);
966 silc_buffer_free(channels);
968 silc_buffer_free(umode_list);
972 if (status == SILC_STATUS_LIST_END)
977 /* Send error replies */
978 if (status == SILC_STATUS_OK && errors_count > 1)
979 status = SILC_STATUS_LIST_START;
982 for (i = 0, k = 0; i < errors_count; i++) {
984 idp = silc_id_payload_encode(errors[i].id, SILC_ID_CLIENT);
988 tmp = silc_argument_get_arg_type(cmd->args, errors[i].index, &len);
992 status = SILC_STATUS_LIST_ITEM;
993 if (errors_count > 1 && k == errors_count - 1)
994 status = SILC_STATUS_LIST_END;
995 if (count && k - 1 == count)
996 status = SILC_STATUS_LIST_END;
999 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
1000 (status == SILC_STATUS_OK ?
1001 errors[i].error : status),
1002 (status == SILC_STATUS_OK ?
1003 0 : errors[i].error),
1005 silc_buffer_free(idp);
1008 if (status == SILC_STATUS_LIST_END)
1015 silc_server_command_whois_send_router(SilcServerCommandContext cmd)
1017 SilcServer server = cmd->server;
1019 SilcUInt16 old_ident;
1021 old_ident = silc_command_get_ident(cmd->payload);
1022 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1023 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1025 /* Send WHOIS command to our router */
1026 silc_server_packet_send(server, (SilcSocketConnection)
1027 SILC_PRIMARY_ROUTE(server),
1028 SILC_PACKET_COMMAND, cmd->packet->flags,
1029 tmpbuf->data, tmpbuf->len, TRUE);
1031 /* Reprocess this packet after received reply from router */
1032 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1033 silc_command_get_ident(cmd->payload),
1034 silc_server_command_whois,
1035 silc_server_command_dup(cmd));
1036 cmd->pending = TRUE;
1037 silc_command_set_ident(cmd->payload, old_ident);
1038 silc_buffer_free(tmpbuf);
1042 silc_server_command_whois_process(SilcServerCommandContext cmd)
1044 SilcServer server = cmd->server;
1045 char *nick = NULL, *server_name = NULL;
1047 SilcClientEntry *clients = NULL, entry;
1048 SilcClientID **client_id = NULL;
1049 SilcUInt32 client_id_count = 0, clients_count = 0, error_client_count = 0;
1050 ResolveError error_client = NULL;
1051 SilcDList attrs = NULL;
1053 bool check_global = FALSE;
1055 /* Parse the whois request */
1056 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1057 &nick, &server_name, &count,
1058 &error_client, &error_client_count,
1062 /* Send the WHOIS request to the router only if it included nickname.
1063 Since nicknames can be expanded into many clients we need to send it
1064 to router. If the WHOIS included only client ID's we will check them
1065 first locally since we just might have them. */
1066 if (nick && !client_id_count && cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1067 server->server_type == SILC_SERVER && !cmd->pending &&
1068 !server->standalone) {
1069 silc_server_command_whois_send_router(cmd);
1074 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1075 check_global = TRUE;
1076 else if (server->server_type != SILC_SERVER)
1077 check_global = TRUE;
1079 /* Get all clients matching that ID or nickname from local list */
1080 if (client_id_count) {
1081 /* Check all Client ID's received in the command packet */
1082 for (i = 0; i < client_id_count; i++) {
1083 entry = silc_idlist_find_client_by_id(server->local_list,
1084 client_id[i], TRUE, NULL);
1085 if (!entry && check_global)
1086 entry = silc_idlist_find_client_by_id(server->global_list,
1087 client_id[i], TRUE, NULL);
1089 clients = silc_realloc(clients, sizeof(*clients) *
1090 (clients_count + 1));
1091 clients[clients_count++] = entry;
1093 /* If we are normal server and did not send the request first to router
1094 do it now, since we do not have the Client ID information. */
1095 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1096 server->server_type == SILC_SERVER && !cmd->pending &&
1097 !server->standalone) {
1098 silc_server_command_whois_send_router(cmd);
1103 ADD_ERROR(error_client, error_client_count, client_id[i],
1104 SILC_ID_CLIENT, 0, SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
1108 /* Find by nickname */
1109 if (!silc_idlist_get_clients_by_hash(server->local_list,
1110 nick, server->md5hash,
1111 &clients, &clients_count))
1112 silc_idlist_get_clients_by_nickname(server->local_list,
1114 &clients, &clients_count);
1116 if (!silc_idlist_get_clients_by_hash(server->global_list,
1117 nick, server->md5hash,
1118 &clients, &clients_count))
1119 silc_idlist_get_clients_by_nickname(server->global_list,
1121 &clients, &clients_count);
1125 if (!clients && (client_id_count || nick)) {
1126 /* If we are normal server and did not send the request first to router
1127 do it now, since we do not have the information. */
1128 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1129 server->server_type == SILC_SERVER && !cmd->pending &&
1130 !server->standalone) {
1131 silc_server_command_whois_send_router(cmd);
1136 /* Such client(s) really does not exist in the SILC network. */
1137 if (!client_id_count)
1138 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
1139 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1140 3, nick, strlen(nick));
1142 silc_server_command_whois_send_reply(cmd, NULL, 0,
1143 error_client, error_client_count,
1148 /* Router always finds the client entry if it exists in the SILC network.
1149 However, it might be incomplete entry and does not include all the
1150 mandatory fields that WHOIS command reply requires. Check for these and
1151 make query from the server who owns the client if some fields are
1153 if (!silc_server_command_whois_check(cmd, clients, clients_count, attrs)) {
1158 /* Send the command reply */
1159 silc_server_command_whois_send_reply(cmd, clients, clients_count,
1160 error_client, error_client_count,
1161 count, nick, client_id);
1164 if (client_id_count) {
1165 for (i = 0; i < client_id_count; i++)
1166 silc_free(client_id[i]);
1167 silc_free(client_id);
1170 silc_free(error_client);
1172 silc_free(server_name);
1174 silc_attribute_payload_list_free(attrs);
1179 /* Server side of command WHOIS. Processes user's query and sends found
1180 results as command replies back to the client. */
1182 SILC_SERVER_CMD_FUNC(whois)
1184 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1187 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 3328);
1189 ret = silc_server_command_whois_process(cmd);
1190 silc_server_command_free(cmd);
1193 /******************************************************************************
1197 ******************************************************************************/
1200 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
1208 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1210 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
1211 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1216 /* Get the nickname@server string and parse it. */
1217 silc_parse_userfqdn(tmp, nickname, server_name);
1219 /* Get the max count of reply messages allowed */
1220 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1222 SILC_GET32_MSB(*count, tmp);
1230 silc_server_command_whowas_check(SilcServerCommandContext cmd,
1231 SilcClientEntry *clients,
1232 SilcUInt32 clients_count)
1234 SilcServer server = cmd->server;
1236 SilcClientEntry entry;
1238 for (i = 0; i < clients_count; i++) {
1241 if (!entry->nickname || !entry->username) {
1243 SilcUInt16 old_ident;
1248 old_ident = silc_command_get_ident(cmd->payload);
1249 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1250 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1252 /* Send WHOWAS command */
1253 silc_server_packet_send(server, entry->router->connection,
1254 SILC_PACKET_COMMAND, cmd->packet->flags,
1255 tmpbuf->data, tmpbuf->len, TRUE);
1257 /* Reprocess this packet after received reply */
1258 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1259 silc_command_get_ident(cmd->payload),
1260 silc_server_command_whowas,
1261 silc_server_command_dup(cmd));
1262 cmd->pending = TRUE;
1263 silc_command_set_ident(cmd->payload, old_ident);
1265 silc_buffer_free(tmpbuf);
1274 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1275 SilcClientEntry *clients,
1276 SilcUInt32 clients_count)
1278 SilcServer server = cmd->server;
1280 int i, k, count = 0, len;
1281 SilcBuffer packet, idp;
1282 SilcClientEntry entry = NULL;
1284 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1285 char nh[256], uh[256];
1288 status = SILC_STATUS_OK;
1290 /* Process only entries that are not registered anymore. */
1292 for (i = 0; i < clients_count; i++) {
1293 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1300 /* No valid entries found at all, just send error */
1301 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1302 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1303 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1304 3, tmp, tmp ? strlen(tmp) : 0);
1308 if (valid_count > 1)
1309 status = SILC_STATUS_LIST_START;
1311 for (i = 0, k = 0; i < clients_count; i++) {
1317 status = SILC_STATUS_LIST_ITEM;
1318 if (valid_count > 1 && k == valid_count - 1)
1319 status = SILC_STATUS_LIST_END;
1320 if (count && k - 1 == count)
1321 status = SILC_STATUS_LIST_END;
1323 /* Send WHOWAS reply */
1324 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1325 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1326 memset(uh, 0, sizeof(uh));
1327 memset(nh, 0, sizeof(nh));
1329 strncat(nh, entry->nickname, strlen(entry->nickname));
1330 if (!strchr(entry->nickname, '@')) {
1331 strncat(nh, "@", 1);
1332 if (entry->servername) {
1333 strncat(nh, entry->servername, strlen(entry->servername));
1335 len = entry->router ? strlen(entry->router->server_name) :
1336 strlen(server->server_name);
1337 strncat(nh, entry->router ? entry->router->server_name :
1338 server->server_name, len);
1342 strncat(uh, entry->username, strlen(entry->username));
1343 if (!strchr(entry->username, '@')) {
1344 strncat(uh, "@", 1);
1345 strcat(uh, "*private*");
1349 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1350 status, 0, ident, 4,
1351 2, idp->data, idp->len,
1356 strlen(entry->userinfo) : 0);
1357 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1358 0, packet->data, packet->len, FALSE);
1360 silc_buffer_free(packet);
1361 silc_buffer_free(idp);
1363 if (status == SILC_STATUS_LIST_END)
1370 silc_server_command_whowas_process(SilcServerCommandContext cmd)
1372 SilcServer server = cmd->server;
1373 char *nick = NULL, *server_name = NULL;
1375 SilcClientEntry *clients = NULL;
1376 SilcUInt32 clients_count = 0;
1378 bool check_global = FALSE;
1380 /* Protocol dictates that we must always send the received WHOWAS request
1381 to our router if we are normal server, so let's do it now unless we
1382 are standalone. We will not send any replies to the client until we
1383 have received reply from the router. */
1384 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1385 server->server_type == SILC_SERVER && !cmd->pending &&
1386 !server->standalone) {
1388 SilcUInt16 old_ident;
1390 old_ident = silc_command_get_ident(cmd->payload);
1391 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1392 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1394 /* Send WHOWAS command to our router */
1395 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
1396 SILC_PACKET_COMMAND, cmd->packet->flags,
1397 tmpbuf->data, tmpbuf->len, TRUE);
1399 /* Reprocess this packet after received reply from router */
1400 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1401 silc_command_get_ident(cmd->payload),
1402 silc_server_command_whowas,
1403 silc_server_command_dup(cmd));
1404 cmd->pending = TRUE;
1405 silc_command_set_ident(cmd->payload, old_ident);
1407 silc_buffer_free(tmpbuf);
1412 /* We are ready to process the command request. Let's search for the
1413 requested client and send reply to the requesting client. */
1415 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1416 check_global = TRUE;
1417 else if (server->server_type != SILC_SERVER)
1418 check_global = TRUE;
1420 /* Parse the whowas request */
1421 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1424 /* Get all clients matching that nickname from local list */
1425 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1427 &clients, &clients_count))
1428 silc_idlist_get_clients_by_hash(server->local_list,
1429 nick, server->md5hash,
1430 &clients, &clients_count);
1432 /* Check global list as well */
1434 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1436 &clients, &clients_count))
1437 silc_idlist_get_clients_by_hash(server->global_list,
1438 nick, server->md5hash,
1439 &clients, &clients_count);
1443 /* Such a client really does not exist in the SILC network. */
1444 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1445 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1446 3, nick, strlen(nick));
1450 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1455 /* Send the command reply to the client */
1456 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1461 silc_free(server_name);
1465 /* Server side of command WHOWAS. */
1467 SILC_SERVER_CMD_FUNC(whowas)
1469 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1472 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1474 ret = silc_server_command_whowas_process(cmd);
1475 silc_server_command_free(cmd);
1478 /******************************************************************************
1482 ******************************************************************************/
1485 silc_server_command_identify_send_router(SilcServerCommandContext cmd)
1487 SilcServer server = cmd->server;
1489 SilcUInt16 old_ident;
1491 old_ident = silc_command_get_ident(cmd->payload);
1492 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1493 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1495 /* Send IDENTIFY command to our router */
1496 silc_server_packet_send(server, (SilcSocketConnection)
1497 SILC_PRIMARY_ROUTE(server),
1498 SILC_PACKET_COMMAND, cmd->packet->flags,
1499 tmpbuf->data, tmpbuf->len, TRUE);
1501 /* Reprocess this packet after received reply from router */
1502 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1503 silc_command_get_ident(cmd->payload),
1504 silc_server_command_identify,
1505 silc_server_command_dup(cmd));
1506 cmd->pending = TRUE;
1507 silc_command_set_ident(cmd->payload, old_ident);
1508 silc_buffer_free(tmpbuf);
1512 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1513 SilcClientEntry **clients,
1514 SilcUInt32 *clients_count,
1515 SilcServerEntry **servers,
1516 SilcUInt32 *servers_count,
1517 SilcChannelEntry **channels,
1518 SilcUInt32 *channels_count,
1520 ResolveError *error_id,
1521 SilcUInt32 *error_id_count)
1523 SilcServer server = cmd->server;
1526 SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
1528 bool check_global = FALSE;
1532 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1533 check_global = TRUE;
1534 else if (server->server_type != SILC_SERVER)
1535 check_global = TRUE;
1537 /* If ID Payload is in the command it must be used instead of names */
1538 tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1540 /* No ID, get the names. */
1542 /* If we are normal server and have not resolved information from
1543 router yet, do so now. */
1544 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1545 server->server_type == SILC_SERVER && !cmd->pending &&
1546 !server->standalone) {
1547 silc_server_command_identify_send_router(cmd);
1551 /* Try to get nickname@server. */
1552 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1555 char *nick_server = NULL;
1557 silc_parse_userfqdn(tmp, &nick, &nick_server);
1559 if (!silc_idlist_get_clients_by_hash(server->local_list,
1560 nick, server->md5hash,
1561 clients, clients_count))
1562 silc_idlist_get_clients_by_nickname(server->local_list,
1564 clients, clients_count);
1566 if (!silc_idlist_get_clients_by_hash(server->global_list,
1567 nick, server->md5hash,
1568 clients, clients_count))
1569 silc_idlist_get_clients_by_nickname(server->global_list,
1571 clients, clients_count);
1575 silc_free(nick_server);
1578 /* the nickname does not exist, send error reply */
1579 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1580 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1581 3, tmp, strlen(tmp));
1586 /* Try to get server name */
1587 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1589 entry = silc_idlist_find_server_by_name(server->local_list,
1591 if (!entry && check_global)
1592 entry = silc_idlist_find_server_by_name(server->global_list,
1595 *servers = silc_realloc(*servers, sizeof(**servers) *
1596 (*servers_count + 1));
1597 (*servers)[(*servers_count)++] = entry;
1601 /* the server does not exist, send error reply */
1602 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1603 SILC_STATUS_ERR_NO_SUCH_SERVER,
1604 0, 3, tmp, strlen(tmp));
1609 /* Try to get channel name */
1610 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1612 entry = silc_idlist_find_channel_by_name(server->local_list,
1614 if (!entry && check_global)
1615 entry = silc_idlist_find_channel_by_name(server->global_list,
1618 *channels = silc_realloc(*channels, sizeof(**channels) *
1619 (*channels_count + 1));
1620 (*channels)[(*channels_count)++] = entry;
1624 /* The channel does not exist, send error reply */
1625 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1626 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1627 0, 3, tmp, strlen(tmp));
1632 if (!(*clients) && !(*servers) && !(*channels)) {
1633 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1634 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1639 /* Command includes ID, we must use that. Also check whether the command
1640 has more than one ID set - take them all. */
1642 /* Take all ID's from the command packet */
1643 for (i = 0; i < argc; i++) {
1646 tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
1650 idp = silc_id_payload_parse(tmp, len);
1652 ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1653 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1655 id = silc_id_payload_get_id(idp);
1656 switch (silc_id_payload_get_type(idp)) {
1658 case SILC_ID_CLIENT:
1659 entry = silc_idlist_find_client_by_id(server->local_list,
1661 if (!entry && check_global)
1662 entry = silc_idlist_find_client_by_id(server->global_list,
1665 *clients = silc_realloc(*clients, sizeof(**clients) *
1666 (*clients_count + 1));
1667 (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
1669 /* If we are normal server and have not resolved information from
1670 router yet, do so now. */
1671 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1672 server->server_type == SILC_SERVER && !cmd->pending &&
1673 !server->standalone) {
1674 silc_server_command_identify_send_router(cmd);
1675 silc_free(*clients);
1676 silc_free(*servers);
1677 silc_free(*channels);
1678 silc_free(*error_id);
1682 ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1683 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
1688 case SILC_ID_SERVER:
1689 entry = silc_idlist_find_server_by_id(server->local_list,
1691 if (!entry && check_global)
1692 entry = silc_idlist_find_server_by_id(server->global_list,
1695 *servers = silc_realloc(*servers, sizeof(**servers) *
1696 (*servers_count + 1));
1697 (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
1699 /* If we are normal server and have not resolved information from
1700 router yet, do so now. */
1701 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1702 server->server_type == SILC_SERVER && !cmd->pending &&
1703 !server->standalone) {
1704 silc_server_command_identify_send_router(cmd);
1705 silc_free(*clients);
1706 silc_free(*servers);
1707 silc_free(*channels);
1708 silc_free(*error_id);
1712 ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1713 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
1717 case SILC_ID_CHANNEL:
1718 entry = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
1719 if (!entry && check_global)
1720 entry = silc_idlist_find_channel_by_id(server->global_list, id,
1723 *channels = silc_realloc(*channels, sizeof(**channels) *
1724 (*channels_count + 1));
1725 (*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
1727 /* If we are normal server and have not resolved information from
1728 router yet, do so now. */
1729 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1730 server->server_type == SILC_SERVER && !cmd->pending &&
1731 !server->standalone) {
1732 silc_server_command_identify_send_router(cmd);
1733 silc_free(*clients);
1734 silc_free(*servers);
1735 silc_free(*channels);
1736 silc_free(*error_id);
1740 ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1741 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID);
1746 silc_id_payload_free(idp);
1751 /* Get the max count of reply messages allowed */
1752 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1754 SILC_GET32_MSB(*count, tmp);
1761 /* Checks that all mandatory fields in client entry are present. If not
1762 then send WHOIS request to the server who owns the client. We use
1763 WHOIS because we want to get as much information as possible at once. */
1766 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1767 SilcClientEntry *clients,
1768 SilcUInt32 clients_count)
1770 SilcServer server = cmd->server;
1771 SilcClientEntry entry;
1772 SilcServerResolveContext resolve = NULL, r = NULL;
1773 SilcUInt32 resolve_count = 0;
1777 for (i = 0; i < clients_count; i++) {
1782 if (entry->nickname ||
1783 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1787 /* If we are normal server, and we've not resolved this client from
1788 router and it is global client, we'll check whether it is on some
1789 channel. If not then we cannot be sure about its validity, and
1790 we'll resolve it from router. */
1791 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
1792 entry->connection || silc_hash_table_count(entry->channels))
1796 /* We need to resolve this entry since it is not complete */
1798 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1799 /* The entry is being resolved (and we are not the resolver) so attach
1800 to the command reply and we're done with this one. */
1801 silc_server_command_pending(server, SILC_COMMAND_NONE,
1802 entry->resolve_cmd_ident,
1803 silc_server_command_identify,
1804 silc_server_command_dup(cmd));
1807 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1808 /* We've resolved this and it still is not ready. We'll return
1809 and are that this will be handled again after it is resolved. */
1810 for (i = 0; i < resolve_count; i++) {
1811 for (k = 0; k < r->res_argc; k++)
1812 silc_free(r->res_argv[k]);
1813 silc_free(r->res_argv);
1814 silc_free(r->res_argv_lens);
1815 silc_free(r->res_argv_types);
1820 /* We'll resolve this client */
1824 for (k = 0; k < resolve_count; k++) {
1825 if (resolve[k].sock == entry->router->connection) {
1832 resolve = silc_realloc(resolve, sizeof(*resolve) *
1833 (resolve_count + 1));
1834 r = &resolve[resolve_count];
1835 memset(r, 0, sizeof(*r));
1836 r->sock = entry->router->connection;
1837 r->ident = ++server->cmd_ident;
1841 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1843 r->res_argv_lens = silc_realloc(r->res_argv_lens,
1844 sizeof(*r->res_argv_lens) *
1846 r->res_argv_types = silc_realloc(r->res_argv_types,
1847 sizeof(*r->res_argv_types) *
1849 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1850 r->res_argv[r->res_argc] = silc_calloc(idp->len,
1851 sizeof(**r->res_argv));
1852 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1853 r->res_argv_lens[r->res_argc] = idp->len;
1854 r->res_argv_types[r->res_argc] = r->res_argc + 4;
1856 silc_buffer_free(idp);
1858 entry->resolve_cmd_ident = r->ident;
1859 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1860 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1865 /* Do the resolving */
1866 for (i = 0; i < resolve_count; i++) {
1871 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1872 now anyway so make it a good one. */
1873 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1874 r->res_argc, r->res_argv,
1878 silc_server_packet_send(server, r->sock, SILC_PACKET_COMMAND,
1879 cmd->packet->flags, res_cmd->data,
1880 res_cmd->len, FALSE);
1882 /* Reprocess this packet after received reply */
1883 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1885 silc_server_command_identify,
1886 silc_server_command_dup(cmd));
1887 cmd->pending = TRUE;
1889 silc_buffer_free(res_cmd);
1890 for (k = 0; k < r->res_argc; k++)
1891 silc_free(r->res_argv[k]);
1892 silc_free(r->res_argv);
1893 silc_free(r->res_argv_lens);
1894 silc_free(r->res_argv_types);
1903 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1904 SilcClientEntry *clients,
1905 SilcUInt32 clients_count,
1906 SilcServerEntry *servers,
1907 SilcUInt32 servers_count,
1908 SilcChannelEntry *channels,
1909 SilcUInt32 channels_count,
1910 ResolveError errors,
1911 SilcUInt32 errors_count,
1914 SilcServer server = cmd->server;
1915 int i, k, valid_count;
1917 SilcBuffer packet, idp;
1919 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1920 char nh[256], uh[256];
1921 SilcSocketConnection hsock;
1924 status = SILC_STATUS_OK;
1927 SilcClientEntry entry;
1928 valid_count = clients_count;
1930 if (silc_argument_get_arg_type(cmd->args, 1, NULL)) {
1931 /* Process only valid clients and ignore those that are not registered.
1932 This is checked with nickname only because when resolved client IDs
1933 we check that they are registered earlier. */
1935 for (i = 0; i < clients_count; i++) {
1936 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1943 /* No valid entries found at all, just send error */
1944 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1945 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1946 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1947 3, tmp, tmp ? strlen(tmp) : 0);
1952 /* Process all valid client entries and send command replies */
1954 if (valid_count > 1)
1955 status = SILC_STATUS_LIST_START;
1957 for (i = 0, k = 0; i < clients_count; i++) {
1963 status = SILC_STATUS_LIST_ITEM;
1964 if (valid_count > 1 && k == valid_count - 1
1965 && !servers_count && !channels_count && !errors_count)
1966 status = SILC_STATUS_LIST_END;
1967 if (count && k - 1 == count)
1968 status = SILC_STATUS_LIST_END;
1970 /* Send IDENTIFY reply */
1972 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1973 memset(uh, 0, sizeof(uh));
1974 memset(nh, 0, sizeof(nh));
1975 strncat(nh, entry->nickname, strlen(entry->nickname));
1976 if (!strchr(entry->nickname, '@')) {
1977 strncat(nh, "@", 1);
1978 if (entry->servername) {
1979 strncat(nh, entry->servername, strlen(entry->servername));
1981 len = entry->router ? strlen(entry->router->server_name) :
1982 strlen(server->server_name);
1983 strncat(nh, entry->router ? entry->router->server_name :
1984 server->server_name, len);
1988 if (!entry->username) {
1989 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1990 status, 0, ident, 2,
1991 2, idp->data, idp->len,
1994 strncat(uh, entry->username, strlen(entry->username));
1995 if (!strchr(entry->username, '@') && entry->connection) {
1996 strncat(uh, "@", 1);
1997 hsock = (SilcSocketConnection)entry->connection;
1998 len = strlen(hsock->hostname);
1999 strncat(uh, hsock->hostname, len);
2002 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
2003 status, 0, ident, 3,
2004 2, idp->data, idp->len,
2009 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2010 0, packet->data, packet->len, FALSE);
2012 silc_buffer_free(packet);
2013 silc_buffer_free(idp);
2015 if (status == SILC_STATUS_LIST_END)
2022 SilcServerEntry entry;
2024 if (status == SILC_STATUS_OK && servers_count > 1)
2025 status = SILC_STATUS_LIST_START;
2027 for (i = 0, k = 0; i < servers_count; i++) {
2031 status = SILC_STATUS_LIST_ITEM;
2032 if (servers_count > 1 && k == servers_count - 1 && !channels_count &&
2034 status = SILC_STATUS_LIST_END;
2035 if (count && k - 1 == count)
2036 status = SILC_STATUS_LIST_END;
2038 /* Send IDENTIFY reply */
2039 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2041 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
2042 status, 0, ident, 2,
2043 2, idp->data, idp->len,
2044 3, entry->server_name,
2045 entry->server_name ?
2046 strlen(entry->server_name) : 0);
2047 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2048 0, packet->data, packet->len, FALSE);
2050 silc_buffer_free(packet);
2051 silc_buffer_free(idp);
2053 if (status == SILC_STATUS_LIST_END)
2060 SilcChannelEntry entry;
2062 if (status == SILC_STATUS_OK && channels_count > 1)
2063 status = SILC_STATUS_LIST_START;
2065 for (i = 0, k = 0; i < channels_count; i++) {
2066 entry = channels[i];
2069 status = SILC_STATUS_LIST_ITEM;
2070 if (channels_count > 1 && k == channels_count - 1 && !errors_count)
2071 status = SILC_STATUS_LIST_END;
2072 if (count && k - 1 == count)
2073 status = SILC_STATUS_LIST_END;
2075 /* Send IDENTIFY reply */
2076 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2078 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
2079 status, 0, ident, 2,
2080 2, idp->data, idp->len,
2081 3, entry->channel_name,
2082 entry->channel_name ?
2083 strlen(entry->channel_name): 0);
2084 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2085 0, packet->data, packet->len, FALSE);
2087 silc_buffer_free(packet);
2088 silc_buffer_free(idp);
2090 if (status == SILC_STATUS_LIST_END)
2096 /* Send error replies */
2098 if (status == SILC_STATUS_OK && errors_count > 1)
2099 status = SILC_STATUS_LIST_START;
2102 for (i = 0, k = 0; i < errors_count; i++) {
2104 idp = silc_id_payload_encode(errors[i].id, SILC_ID_CLIENT);
2108 tmp = silc_argument_get_arg_type(cmd->args, errors[i].index, &len);
2112 status = SILC_STATUS_LIST_ITEM;
2113 if (errors_count > 1 && k == errors_count - 1)
2114 status = SILC_STATUS_LIST_END;
2115 if (count && k - 1 == count)
2116 status = SILC_STATUS_LIST_END;
2119 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
2120 (status == SILC_STATUS_OK ?
2121 errors[i].error : status),
2122 (status == SILC_STATUS_OK ?
2123 0 : errors[i].error),
2125 silc_buffer_free(idp);
2128 if (status == SILC_STATUS_LIST_END)
2136 silc_server_command_identify_process(SilcServerCommandContext cmd)
2138 SilcUInt32 count = 0;
2140 SilcClientEntry *clients = NULL;
2141 SilcServerEntry *servers = NULL;
2142 SilcChannelEntry *channels = NULL;
2143 SilcUInt32 clients_count = 0, servers_count = 0, channels_count = 0;
2144 SilcUInt32 errors_count = 0;
2145 ResolveError errors = NULL;
2147 /* Parse the IDENTIFY request */
2148 ret = silc_server_command_identify_parse(cmd,
2149 &clients, &clients_count,
2150 &servers, &servers_count,
2151 &channels, &channels_count,
2152 &count, &errors, &errors_count);
2157 /* Check that all mandatory fields are present and request those data
2158 from the server who owns the client if necessary. */
2159 if (!silc_server_command_identify_check_client(cmd, clients,
2165 /* Send the command reply to the client */
2166 silc_server_command_identify_send_reply(cmd,
2167 clients, clients_count,
2168 servers, servers_count,
2169 channels, channels_count,
2170 errors, errors_count,
2176 silc_free(channels);
2181 SILC_SERVER_CMD_FUNC(identify)
2183 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2186 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
2188 ret = silc_server_command_identify_process(cmd);
2189 silc_server_command_free(cmd);
2192 /* Server side of command NICK. Sets nickname for user. Setting
2193 nickname causes generation of a new client ID for the client. The
2194 new client ID is sent to the client after changing the nickname. */
2196 SILC_SERVER_CMD_FUNC(nick)
2198 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2199 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2200 SilcServer server = cmd->server;
2201 SilcBuffer packet, nidp, oidp = NULL;
2202 SilcClientID *new_id;
2203 SilcUInt32 nick_len;
2205 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2208 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
2211 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
2213 /* Check nickname */
2214 nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
2217 if (silc_server_name_bad_chars(nick, nick_len) == TRUE) {
2218 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2219 SILC_STATUS_ERR_BAD_NICKNAME, 0);
2223 /* Check for same nickname */
2224 if (!strcmp(client->nickname, nick)) {
2225 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2229 /* Create new Client ID */
2230 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
2232 cmd->server->md5hash, nick,
2236 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2237 SILC_STATUS_ERR_BAD_NICKNAME, 0);
2240 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2243 /* Send notify about nickname change to our router. We send the new
2244 ID and ask to replace it with the old one. If we are router the
2245 packet is broadcasted. Send NICK_CHANGE notify. */
2246 silc_server_send_notify_nick_change(server, SILC_PRIMARY_ROUTE(server),
2247 SILC_BROADCAST(server), client->id,
2250 /* Check if anyone is watching the old nickname */
2251 if (server->server_type == SILC_ROUTER)
2252 silc_server_check_watcher_list(server, client, nick,
2253 SILC_NOTIFY_TYPE_NICK_CHANGE);
2255 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2257 /* Remove old cache entry */
2258 silc_idcache_del_by_context(server->local_list->clients, client);
2260 silc_free(client->id);
2261 client->id = new_id;
2263 silc_free(client->nickname);
2264 client->nickname = strdup(nick);
2266 /* Update client cache */
2267 silc_idcache_add(server->local_list->clients, client->nickname,
2268 client->id, (void *)client, 0, NULL);
2270 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2272 /* Send NICK_CHANGE notify to the client's channels */
2273 silc_server_send_notify_on_channels(server, NULL, client,
2274 SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
2275 oidp->data, oidp->len,
2276 nidp->data, nidp->len,
2278 strlen(client->nickname));
2280 /* Check if anyone is watching the new nickname */
2281 if (server->server_type == SILC_ROUTER)
2282 silc_server_check_watcher_list(server, client, NULL,
2283 SILC_NOTIFY_TYPE_NICK_CHANGE);
2286 /* Send the new Client ID as reply command back to client */
2287 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
2288 SILC_STATUS_OK, 0, ident, 2,
2289 2, nidp->data, nidp->len,
2290 3, nick, strlen(nick));
2291 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2292 0, packet->data, packet->len, FALSE);
2294 silc_buffer_free(packet);
2295 silc_buffer_free(nidp);
2297 silc_buffer_free(oidp);
2300 silc_server_command_free(cmd);
2303 /* Sends the LIST command reply */
2306 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2307 SilcChannelEntry *lch,
2308 SilcUInt32 lch_count,
2309 SilcChannelEntry *gch,
2310 SilcUInt32 gch_count)
2313 SilcBuffer packet, idp;
2314 SilcChannelEntry entry;
2316 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2318 unsigned char usercount[4];
2320 int valid_lcount = 0, valid_rcount = 0;
2322 for (i = 0; i < lch_count; i++) {
2323 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2328 for (i = 0; i < gch_count; i++) {
2329 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2335 status = SILC_STATUS_OK;
2336 if ((lch_count + gch_count) > 1)
2337 status = SILC_STATUS_LIST_START;
2340 for (i = 0, k = 0; i < lch_count; i++) {
2346 status = SILC_STATUS_LIST_ITEM;
2347 if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
2348 status = SILC_STATUS_LIST_END;
2350 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2352 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2353 topic = "*private*";
2354 memset(usercount, 0, sizeof(usercount));
2356 topic = entry->topic;
2357 users = silc_hash_table_count(entry->user_list);
2358 SILC_PUT32_MSB(users, usercount);
2361 /* Send the reply */
2363 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2364 status, 0, ident, 4,
2365 2, idp->data, idp->len,
2366 3, entry->channel_name,
2367 strlen(entry->channel_name),
2368 4, topic, topic ? strlen(topic) : 0,
2370 silc_server_packet_send(cmd->server, cmd->sock,
2371 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2372 packet->len, FALSE);
2373 silc_buffer_free(packet);
2374 silc_buffer_free(idp);
2379 for (i = 0, k = 0; i < gch_count; i++) {
2385 status = SILC_STATUS_LIST_ITEM;
2386 if (valid_rcount > 1 && k == valid_rcount - 1)
2387 status = SILC_STATUS_LIST_END;
2389 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2391 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2392 topic = "*private*";
2393 memset(usercount, 0, sizeof(usercount));
2395 topic = entry->topic;
2396 users = entry->user_count;
2397 SILC_PUT32_MSB(users, usercount);
2400 /* Send the reply */
2402 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2403 status, 0, ident, 4,
2404 2, idp->data, idp->len,
2405 3, entry->channel_name,
2406 strlen(entry->channel_name),
2407 4, topic, topic ? strlen(topic) : 0,
2409 silc_server_packet_send(cmd->server, cmd->sock,
2410 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2411 packet->len, FALSE);
2412 silc_buffer_free(packet);
2413 silc_buffer_free(idp);
2418 /* Server side of LIST command. This lists the channel of the requested
2419 server. Secret channels are not listed. */
2421 SILC_SERVER_CMD_FUNC(list)
2423 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2424 SilcServer server = cmd->server;
2425 SilcChannelID *channel_id = NULL;
2428 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2429 SilcUInt32 lch_count = 0, gch_count = 0;
2431 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2433 /* If we are normal server, send the command to router, since we
2434 want to know all channels in the network. */
2435 if (!cmd->pending && server->server_type == SILC_SERVER &&
2436 !server->standalone) {
2438 SilcUInt16 old_ident;
2440 old_ident = silc_command_get_ident(cmd->payload);
2441 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2442 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2443 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
2444 SILC_PACKET_COMMAND, cmd->packet->flags,
2445 tmpbuf->data, tmpbuf->len, TRUE);
2447 /* Reprocess this packet after received reply from router */
2448 silc_server_command_pending(server, SILC_COMMAND_LIST,
2449 silc_command_get_ident(cmd->payload),
2450 silc_server_command_list,
2451 silc_server_command_dup(cmd));
2452 cmd->pending = TRUE;
2453 silc_command_set_ident(cmd->payload, old_ident);
2454 silc_buffer_free(tmpbuf);
2458 /* Get Channel ID */
2459 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2461 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2463 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2464 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2469 /* Get the channels from local list */
2470 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2473 /* Get the channels from global list */
2474 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2477 /* Send the reply */
2478 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2479 gchannels, gch_count);
2481 silc_free(lchannels);
2482 silc_free(gchannels);
2485 silc_server_command_free(cmd);
2488 /* Server side of TOPIC command. Sets topic for channel and/or returns
2489 current topic to client. */
2491 SILC_SERVER_CMD_FUNC(topic)
2493 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2494 SilcServer server = cmd->server;
2495 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2496 SilcChannelID *channel_id;
2497 SilcChannelEntry channel;
2498 SilcChannelClientEntry chl;
2499 SilcBuffer packet, idp;
2501 SilcUInt32 argc, tmp_len;
2502 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2504 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
2507 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2509 argc = silc_argument_get_arg_num(cmd->args);
2511 /* Get Channel ID */
2512 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2514 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2515 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2518 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2520 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2521 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2525 /* Check whether the channel exists */
2526 channel = silc_idlist_find_channel_by_id(server->local_list,
2529 channel = silc_idlist_find_channel_by_id(server->global_list,
2532 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2533 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
2541 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2543 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2544 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2549 if (strlen(tmp) > 256) {
2550 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2551 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2556 /* See whether the client is on channel and has rights to change topic */
2557 if (!silc_server_client_on_channel(client, channel, &chl)) {
2558 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2559 SILC_STATUS_ERR_NOT_ON_CHANNEL,
2564 if (channel->mode & SILC_CHANNEL_MODE_TOPIC &&
2565 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
2566 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
2567 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2568 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
2573 if (!channel->topic || strcmp(channel->topic, tmp)) {
2574 /* Set the topic for channel */
2575 silc_free(channel->topic);
2576 channel->topic = strdup(tmp);
2578 /* Send TOPIC_SET notify type to the network */
2579 silc_server_send_notify_topic_set(server, SILC_PRIMARY_ROUTE(server),
2580 SILC_BROADCAST(server), channel,
2581 client->id, SILC_ID_CLIENT,
2584 /* Send notify about topic change to all clients on the channel */
2585 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2586 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2587 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2588 idp->data, idp->len,
2590 strlen(channel->topic));
2591 silc_buffer_free(idp);
2595 /* Send the topic to client as reply packet */
2596 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2597 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2598 SILC_STATUS_OK, 0, ident, 2,
2599 2, idp->data, idp->len,
2602 strlen(channel->topic) : 0);
2603 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2604 0, packet->data, packet->len, FALSE);
2606 silc_buffer_free(packet);
2607 silc_buffer_free(idp);
2608 silc_free(channel_id);
2611 silc_server_command_free(cmd);
2614 /* Server side of INVITE command. Invites some client to join some channel.
2615 This command is also used to manage the invite list of the channel. */
2617 SILC_SERVER_CMD_FUNC(invite)
2619 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2620 SilcServer server = cmd->server;
2621 SilcSocketConnection sock = cmd->sock, dest_sock;
2622 SilcChannelClientEntry chl;
2623 SilcClientEntry sender, dest;
2624 SilcClientID *dest_id = NULL;
2625 SilcChannelEntry channel;
2626 SilcChannelID *channel_id = NULL;
2627 SilcIDListData idata;
2628 SilcBuffer idp, idp2, packet;
2629 unsigned char *tmp, *add, *del;
2631 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2633 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2635 /* Get Channel ID */
2636 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2638 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2639 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2642 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
2644 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2645 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2649 /* Get the channel entry */
2650 channel = silc_idlist_find_channel_by_id(server->local_list,
2653 channel = silc_idlist_find_channel_by_id(server->global_list,
2656 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2657 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
2663 /* Check whether the sender of this command is on the channel. */
2664 sender = (SilcClientEntry)sock->user_data;
2665 if (!sender || !silc_server_client_on_channel(sender, channel, &chl)) {
2666 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2667 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
2671 /* Check whether the channel is invite-only channel. If yes then the
2672 sender of this command must be at least channel operator. */
2673 if (channel->mode & SILC_CHANNEL_MODE_INVITE &&
2674 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
2675 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
2676 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2677 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
2682 /* Get destination client ID */
2683 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2688 dest_id = silc_id_payload_parse_id(tmp, len, NULL);
2690 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2691 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
2695 /* Get the client entry */
2696 dest = silc_server_get_client_resolve(server, dest_id, FALSE, &resolve);
2698 if (server->server_type != SILC_SERVER || !resolve) {
2699 silc_server_command_send_status_reply(
2700 cmd, SILC_COMMAND_INVITE,
2701 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0);
2705 /* The client info is being resolved. Reprocess this packet after
2706 receiving the reply to the query. */
2707 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2709 silc_server_command_invite,
2710 silc_server_command_dup(cmd));
2711 cmd->pending = TRUE;
2712 silc_free(channel_id);
2717 /* Check whether the requested client is already on the channel. */
2718 if (silc_server_client_on_channel(dest, channel, NULL)) {
2719 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2720 SILC_STATUS_ERR_USER_ON_CHANNEL,
2725 /* Get route to the client */
2726 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id,
2729 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2730 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2735 memset(invite, 0, sizeof(invite));
2736 strncat(invite, dest->nickname, strlen(dest->nickname));
2737 strncat(invite, "!", 1);
2738 strncat(invite, dest->username, strlen(dest->username));
2739 if (!strchr(dest->username, '@')) {
2740 strncat(invite, "@", 1);
2741 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2744 len = strlen(invite);
2745 if (!channel->invite_list)
2746 channel->invite_list = silc_calloc(len + 2,
2747 sizeof(*channel->invite_list));
2749 channel->invite_list = silc_realloc(channel->invite_list,
2750 sizeof(*channel->invite_list) *
2752 strlen(channel->invite_list) + 2));
2753 strncat(channel->invite_list, invite, len);
2754 strncat(channel->invite_list, ",", 1);
2756 if (!(dest->mode & SILC_UMODE_BLOCK_INVITE)) {
2757 /* Send notify to the client that is invited to the channel */
2758 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2759 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2760 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2762 SILC_NOTIFY_TYPE_INVITE, 3,
2763 idp->data, idp->len,
2764 channel->channel_name,
2765 strlen(channel->channel_name),
2766 idp2->data, idp2->len);
2767 silc_buffer_free(idp);
2768 silc_buffer_free(idp2);
2772 /* Add the client to the invite list of the channel */
2773 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2775 if (!channel->invite_list)
2776 channel->invite_list = silc_calloc(len + 2,
2777 sizeof(*channel->invite_list));
2779 channel->invite_list = silc_realloc(channel->invite_list,
2780 sizeof(*channel->invite_list) *
2782 strlen(channel->invite_list) + 2));
2783 if (add[len - 1] == ',')
2784 add[len - 1] = '\0';
2786 strncat(channel->invite_list, add, len);
2787 strncat(channel->invite_list, ",", 1);
2790 /* Get the invite to be removed and remove it from the list */
2791 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2792 if (del && channel->invite_list) {
2793 char *start, *end, *n;
2795 if (!strncmp(channel->invite_list, del,
2796 strlen(channel->invite_list) - 1)) {
2797 silc_free(channel->invite_list);
2798 channel->invite_list = NULL;
2800 start = strstr(channel->invite_list, del);
2801 if (start && strlen(start) >= len) {
2803 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2804 strncat(n, channel->invite_list, start - channel->invite_list);
2805 strncat(n, end + 1, ((channel->invite_list +
2806 strlen(channel->invite_list)) - end) - 1);
2807 silc_free(channel->invite_list);
2808 channel->invite_list = n;
2813 /* Send notify to the primary router */
2814 silc_server_send_notify_invite(server, SILC_PRIMARY_ROUTE(server),
2815 SILC_BROADCAST(server), channel,
2816 sender->id, add, del);
2818 /* Send command reply */
2819 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2823 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2824 SILC_STATUS_OK, 0, ident, 2,
2826 3, channel->invite_list,
2827 channel->invite_list ?
2828 strlen(channel->invite_list) : 0);
2831 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2832 SILC_STATUS_OK, 0, ident, 1,
2834 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2835 packet->data, packet->len, FALSE);
2836 silc_buffer_free(packet);
2840 silc_free(channel_id);
2841 silc_server_command_free(cmd);
2845 SilcSocketConnection sock;
2849 /* Quits connection to client. This gets called if client won't
2850 close the connection even when it has issued QUIT command. */
2852 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2854 SilcServer server = app_context;
2855 QuitInternal q = (QuitInternal)context;
2857 /* Free all client specific data, such as client entry and entires
2858 on channels this client may be on. */
2859 silc_server_free_client_data(server, q->sock, q->sock->user_data,
2861 q->sock->user_data = NULL;
2863 /* Close the connection on our side */
2864 silc_server_close_connection(server, q->sock);
2866 silc_socket_free(q->sock);
2867 silc_free(q->signoff);
2871 /* Quits SILC session. This is the normal way to disconnect client. */
2873 SILC_SERVER_CMD_FUNC(quit)
2875 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2876 SilcServer server = cmd->server;
2877 SilcSocketConnection sock = cmd->sock;
2879 unsigned char *tmp = NULL;
2882 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2884 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2888 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2892 q = silc_calloc(1, sizeof(*q));
2893 q->sock = silc_socket_dup(sock);
2894 q->signoff = tmp ? strdup(tmp) : NULL;
2896 /* We quit the connection with little timeout */
2897 silc_schedule_task_add(server->schedule, sock->sock,
2898 silc_server_command_quit_cb, (void *)q,
2899 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2902 silc_server_command_free(cmd);
2905 /* Server side of command KILL. This command is used by router operator
2906 to remove an client from the SILC Network temporarily. */
2908 SILC_SERVER_CMD_FUNC(kill)
2910 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2911 SilcServer server = cmd->server;
2912 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2913 SilcClientEntry remote_client;
2914 SilcClientID *client_id;
2915 unsigned char *tmp, *comment;
2916 SilcUInt32 tmp_len, tmp_len2;
2919 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2921 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
2924 /* KILL command works only on router */
2925 if (server->server_type != SILC_ROUTER) {
2926 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2927 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
2931 /* Check whether client has the permissions. */
2932 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2933 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2934 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
2938 /* Get the client ID */
2939 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2941 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2942 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2946 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2948 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2949 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2954 /* Get the client entry */
2955 remote_client = silc_idlist_find_client_by_id(server->local_list,
2956 client_id, TRUE, NULL);
2958 if (!remote_client) {
2959 remote_client = silc_idlist_find_client_by_id(server->global_list,
2960 client_id, TRUE, NULL);
2962 if (!remote_client) {
2963 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2964 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2971 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2975 /* Send reply to the sender */
2976 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2979 /* Check if anyone is watching this nickname */
2980 if (server->server_type == SILC_ROUTER)
2981 silc_server_check_watcher_list(server, client, NULL,
2982 SILC_NOTIFY_TYPE_KILLED);
2984 /* Now do the killing */
2985 silc_server_kill_client(server, remote_client, comment, client->id,
2989 silc_server_command_free(cmd);
2992 /* Server side of command INFO. This sends information about us to
2993 the client. If client requested specific server we will send the
2994 command to that server. */
2996 SILC_SERVER_CMD_FUNC(info)
2998 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2999 SilcServer server = cmd->server;
3000 SilcBuffer packet, idp;
3003 char *dest_server, *server_info = NULL, *server_name;
3004 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3005 SilcServerEntry entry = NULL;
3006 SilcServerID *server_id = NULL;
3008 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
3010 /* Get server name */
3011 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3014 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3016 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3018 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3019 SILC_STATUS_ERR_NO_SERVER_ID, 0);
3025 /* Check whether we have this server cached */
3026 entry = silc_idlist_find_server_by_id(server->local_list,
3027 server_id, TRUE, NULL);
3029 entry = silc_idlist_find_server_by_id(server->global_list,
3030 server_id, TRUE, NULL);
3031 if (!entry && server->server_type != SILC_SERVER) {
3032 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3033 SILC_STATUS_ERR_NO_SUCH_SERVER,
3040 /* Some buggy servers has sent request to router about themselves. */
3041 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
3044 if ((!dest_server && !server_id && !entry) || (entry &&
3045 entry == server->id_entry) ||
3046 (dest_server && !cmd->pending &&
3047 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
3048 /* Send our reply */
3049 char info_string[256];
3051 memset(info_string, 0, sizeof(info_string));
3052 snprintf(info_string, sizeof(info_string),
3053 "location: %s server: %s admin: %s <%s>",
3054 server->config->server_info->location,
3055 server->config->server_info->server_type,
3056 server->config->server_info->admin,
3057 server->config->server_info->email);
3059 server_info = info_string;
3060 entry = server->id_entry;
3062 /* Check whether we have this server cached */
3063 if (!entry && dest_server) {
3064 entry = silc_idlist_find_server_by_name(server->global_list,
3065 dest_server, TRUE, NULL);
3067 entry = silc_idlist_find_server_by_name(server->local_list,
3068 dest_server, TRUE, NULL);
3072 if (!cmd->pending &&
3073 server->server_type != SILC_SERVER && entry && !entry->server_info) {
3074 /* Send to the server */
3076 SilcUInt16 old_ident;
3078 old_ident = silc_command_get_ident(cmd->payload);
3079 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3080 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3082 silc_server_packet_send(server, entry->connection,
3083 SILC_PACKET_COMMAND, cmd->packet->flags,
3084 tmpbuf->data, tmpbuf->len, TRUE);
3086 /* Reprocess this packet after received reply from router */
3087 silc_server_command_pending(server, SILC_COMMAND_INFO,
3088 silc_command_get_ident(cmd->payload),
3089 silc_server_command_info,
3090 silc_server_command_dup(cmd));
3091 cmd->pending = TRUE;
3092 silc_command_set_ident(cmd->payload, old_ident);
3093 silc_buffer_free(tmpbuf);
3097 if (!entry && !cmd->pending && !server->standalone) {
3098 /* Send to the primary router */
3100 SilcUInt16 old_ident;
3102 old_ident = silc_command_get_ident(cmd->payload);
3103 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3104 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3106 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
3107 SILC_PACKET_COMMAND, cmd->packet->flags,
3108 tmpbuf->data, tmpbuf->len, TRUE);
3110 /* Reprocess this packet after received reply from router */
3111 silc_server_command_pending(server, SILC_COMMAND_INFO,
3112 silc_command_get_ident(cmd->payload),
3113 silc_server_command_info,
3114 silc_server_command_dup(cmd));
3115 cmd->pending = TRUE;
3116 silc_command_set_ident(cmd->payload, old_ident);
3117 silc_buffer_free(tmpbuf);
3122 silc_free(server_id);
3125 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3126 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3130 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
3132 server_info = entry->server_info;
3133 server_name = entry->server_name;
3135 /* Send the reply */
3136 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
3137 SILC_STATUS_OK, 0, ident, 3,
3138 2, idp->data, idp->len,
3140 strlen(server_name),
3143 strlen(server_info) : 0);
3144 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3145 packet->data, packet->len, FALSE);
3147 silc_buffer_free(packet);
3148 silc_buffer_free(idp);
3151 silc_server_command_free(cmd);
3154 /* Server side of command PING. This just replies to the ping. */
3156 SILC_SERVER_CMD_FUNC(ping)
3158 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3159 SilcServer server = cmd->server;
3164 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
3167 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
3169 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3170 SILC_STATUS_ERR_NO_SERVER_ID, 0);
3173 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
3177 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
3178 /* Send our reply */
3179 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3182 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3183 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3190 silc_server_command_free(cmd);
3193 /* Server side of command STATS. */
3195 SILC_SERVER_CMD_FUNC(stats)
3197 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3198 SilcServer server = cmd->server;
3199 SilcServerID *server_id;
3202 SilcBuffer packet, stats;
3203 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3206 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1);
3209 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3211 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3212 SILC_STATUS_ERR_NO_SERVER_ID, 0);
3215 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3219 /* The ID must be ours */
3220 if (!SILC_ID_SERVER_COMPARE(server->id, server_id)) {
3221 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3222 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3223 silc_free(server_id);
3226 silc_free(server_id);
3228 /* If we are router then just send everything we got. If we are normal
3229 server then we'll send this to our router to get all the latest
3230 statistical information. */
3231 if (!cmd->pending && server->server_type != SILC_ROUTER &&
3232 !server->standalone) {
3233 /* Send request to our router */
3234 SilcBuffer idp = silc_id_payload_encode(server->router->id,
3236 packet = silc_command_payload_encode_va(SILC_COMMAND_STATS,
3237 ++server->cmd_ident, 1,
3238 1, idp->data, idp->len);
3239 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
3240 SILC_PACKET_COMMAND, 0, packet->data,
3241 packet->len, FALSE);
3243 /* Reprocess this packet after received reply from router */
3244 silc_server_command_pending(server, SILC_COMMAND_STATS,
3246 silc_server_command_stats,
3247 silc_server_command_dup(cmd));
3248 cmd->pending = TRUE;
3249 silc_buffer_free(packet);
3250 silc_buffer_free(idp);
3254 /* Send our reply to sender */
3255 uptime = time(NULL) - server->starttime;
3257 stats = silc_buffer_alloc_size(60);
3258 silc_buffer_format(stats,
3259 SILC_STR_UI_INT(server->starttime),
3260 SILC_STR_UI_INT(uptime),
3261 SILC_STR_UI_INT(server->stat.my_clients),
3262 SILC_STR_UI_INT(server->stat.my_channels),
3263 SILC_STR_UI_INT(server->stat.my_server_ops),
3264 SILC_STR_UI_INT(server->stat.my_router_ops),
3265 SILC_STR_UI_INT(server->stat.cell_clients),
3266 SILC_STR_UI_INT(server->stat.cell_channels),
3267 SILC_STR_UI_INT(server->stat.cell_servers),
3268 SILC_STR_UI_INT(server->stat.clients),
3269 SILC_STR_UI_INT(server->stat.channels),
3270 SILC_STR_UI_INT(server->stat.servers),
3271 SILC_STR_UI_INT(server->stat.routers),
3272 SILC_STR_UI_INT(server->stat.server_ops),
3273 SILC_STR_UI_INT(server->stat.router_ops),
3276 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_STATS,
3277 SILC_STATUS_OK, 0, ident, 2,
3279 3, stats->data, stats->len);
3280 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
3281 0, packet->data, packet->len, FALSE);
3282 silc_buffer_free(packet);
3283 silc_buffer_free(stats);
3286 silc_server_command_free(cmd);
3289 /* Internal routine to join channel. The channel sent to this function
3290 has been either created or resolved from ID lists. This joins the sent
3291 client to the channel. */
3293 static void silc_server_command_join_channel(SilcServer server,
3294 SilcServerCommandContext cmd,
3295 SilcChannelEntry channel,
3296 SilcClientID *client_id,
3300 const unsigned char *auth,
3301 SilcUInt32 auth_len)
3303 SilcSocketConnection sock = cmd->sock;
3305 SilcUInt32 tmp_len, user_count;
3306 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
3307 SilcClientEntry client;
3308 SilcChannelClientEntry chl;
3309 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
3310 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3311 char check[512], check2[512];
3312 bool founder = FALSE;
3314 unsigned char *fkey = NULL;
3315 SilcUInt32 fkey_len = 0;
3317 SILC_LOG_DEBUG(("Joining client to channel"));
3322 /* Get the client entry */
3323 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3324 client = (SilcClientEntry)sock->user_data;
3328 client = silc_server_get_client_resolve(server, client_id, FALSE,
3335 silc_server_command_send_status_reply(
3336 cmd, SILC_COMMAND_JOIN,
3337 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3341 /* The client info is being resolved. Reprocess this packet after
3342 receiving the reply to the query. */
3343 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
3345 silc_server_command_join,
3346 silc_server_command_dup(cmd));
3347 cmd->pending = TRUE;
3351 cmd->pending = FALSE;
3355 * Check founder auth payload if provided. If client can gain founder
3356 * privileges it can override various conditions on joining the channel,
3357 * and can have directly the founder mode set on the channel.
3359 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3360 SilcIDListData idata = (SilcIDListData)client;
3361 SilcChannelClientEntry chl2;
3362 SilcHashTableList htl;
3364 if (channel->founder_key && idata->public_key &&
3365 silc_pkcs_public_key_compare(channel->founder_key,
3366 idata->public_key)) {
3367 /* Check whether the client is to become founder */
3368 if (silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
3369 channel->founder_key, 0, server->sha1hash,
3370 client->id, SILC_ID_CLIENT)) {
3372 /* There cannot be anyone else as founder on the channel now. This
3373 client is definitely the founder due to this authentication */
3374 silc_hash_table_list(channel->user_list, &htl);
3375 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
3376 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
3377 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3378 silc_server_force_cumode_change(server, NULL, channel, chl2,
3382 silc_hash_table_list_reset(&htl);
3384 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3391 * Check channel modes
3395 memset(check, 0, sizeof(check));
3396 memset(check2, 0, sizeof(check2));
3397 strncat(check, client->nickname, strlen(client->nickname));
3398 strncat(check, "!", 1);
3399 strncat(check, client->username, strlen(client->username));
3400 if (!strchr(client->username, '@')) {
3401 strncat(check, "@", 1);
3402 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3405 strncat(check2, client->nickname, strlen(client->nickname));
3406 if (!strchr(client->nickname, '@')) {
3407 strncat(check2, "@", 1);
3408 strncat(check2, server->server_name, strlen(server->server_name));
3410 strncat(check2, "!", 1);
3411 strncat(check2, client->username, strlen(client->username));
3412 if (!strchr(client->username, '@')) {
3413 strncat(check2, "@", 1);
3414 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3417 /* Check invite list if channel is invite-only channel */
3418 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3419 if (!channel->invite_list ||
3420 (!silc_string_match(channel->invite_list, check) &&
3421 !silc_string_match(channel->invite_list, check2))) {
3422 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3423 SILC_STATUS_ERR_NOT_INVITED, 0);
3428 /* Check ban list if it exists. If the client's nickname, server,
3429 username and/or hostname is in the ban list the access to the
3430 channel is denied. */
3431 if (channel->ban_list) {
3432 if (silc_string_match(channel->ban_list, check) ||
3433 silc_string_match(channel->ban_list, check2)) {
3434 silc_server_command_send_status_reply(
3435 cmd, SILC_COMMAND_JOIN,
3436 SILC_STATUS_ERR_BANNED_FROM_CHANNEL, 0);
3441 /* Check user count limit if set. */
3442 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3443 if (silc_hash_table_count(channel->user_list) + 1 >
3444 channel->user_limit) {
3445 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3446 SILC_STATUS_ERR_CHANNEL_IS_FULL,
3453 /* Check the channel passphrase if set. */
3454 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3455 /* Get passphrase */
3456 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3458 passphrase = silc_memdup(tmp, tmp_len);
3460 if (!passphrase || !channel->passphrase ||
3461 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3462 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3463 SILC_STATUS_ERR_BAD_PASSWORD, 0);
3469 * Client is allowed to join to the channel. Make it happen.
3472 /* Check whether the client already is on the channel */
3473 if (silc_server_client_on_channel(client, channel, NULL)) {
3474 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3475 SILC_STATUS_ERR_USER_ON_CHANNEL, 0);
3479 /* Generate new channel key as protocol dictates */
3481 if (!silc_server_create_channel_key(server, channel, 0))
3484 /* Send the channel key. This is broadcasted to the channel but is not
3485 sent to the client who is joining to the channel. */
3486 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3487 silc_server_send_channel_key(server, NULL, channel,
3488 server->server_type == SILC_ROUTER ?
3489 FALSE : !server->standalone);
3492 /* Join the client to the channel by adding it to channel's user list.
3493 Add also the channel to client entry's channels list for fast cross-
3495 chl = silc_calloc(1, sizeof(*chl));
3497 chl->client = client;
3498 chl->channel = channel;
3499 silc_hash_table_add(channel->user_list, client, chl);
3500 silc_hash_table_add(client->channels, channel, chl);
3501 channel->user_count++;
3502 channel->disabled = FALSE;
3504 /* Get users on the channel */
3505 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3508 /* Encode Client ID Payload of the original client who wants to join */
3509 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3511 /* Encode command reply packet */
3512 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3513 SILC_PUT32_MSB(channel->mode, mode);
3514 SILC_PUT32_MSB(created, tmp2);
3515 SILC_PUT32_MSB(user_count, tmp3);
3517 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3518 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3519 keyp = silc_channel_key_payload_encode(silc_id_get_len(channel->id,
3522 strlen(channel->channel_key->
3524 channel->channel_key->cipher->name,
3525 channel->key_len / 8, channel->key);
3529 if (channel->founder_key)
3530 fkey = silc_pkcs_public_key_encode(channel->founder_key, &fkey_len);
3533 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3534 SILC_STATUS_OK, 0, ident, 14,
3535 2, channel->channel_name,
3536 strlen(channel->channel_name),
3537 3, chidp->data, chidp->len,
3538 4, clidp->data, clidp->len,
3541 7, keyp ? keyp->data : NULL,
3542 keyp ? keyp->len : 0,
3543 8, channel->ban_list,
3545 strlen(channel->ban_list) : 0,
3546 9, channel->invite_list,
3547 channel->invite_list ?
3548 strlen(channel->invite_list) : 0,
3551 strlen(channel->topic) : 0,
3552 11, silc_hmac_get_name(channel->hmac),
3553 strlen(silc_hmac_get_name(channel->
3556 13, user_list->data, user_list->len,
3557 14, mode_list->data,
3559 15, fkey, fkey_len);
3561 /* Send command reply */
3562 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3563 reply->data, reply->len, FALSE);
3565 /* Send JOIN notify to locally connected clients on the channel. If
3566 we are normal server then router will send or have sent JOIN notify
3567 already. However since we've added the client already to our channel
3568 we'll ignore it (in packet_receive.c) so we must send it here. If
3569 we are router then this will send it to local clients and local
3571 SILC_LOG_DEBUG(("Send JOIN notify to channel"));
3572 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3573 SILC_NOTIFY_TYPE_JOIN, 2,
3574 clidp->data, clidp->len,
3575 chidp->data, chidp->len);
3577 /* Update statistics */
3578 server->stat.my_chanclients++;
3579 if (server->server_type == SILC_ROUTER) {
3580 server->stat.cell_chanclients++;
3581 server->stat.chanclients++;
3584 if (!cmd->pending) {
3585 /* Send JOIN notify packet to our primary router */
3586 silc_server_send_notify_join(server, SILC_PRIMARY_ROUTE(server),
3587 SILC_BROADCAST(server), channel, client->id);
3590 /* Distribute the channel key to all backup routers. */
3591 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3592 keyp->data, keyp->len, FALSE, TRUE);
3594 /* If client became founder by providing correct founder auth data
3595 notify the mode change to the channel. */
3597 SILC_PUT32_MSB(chl->mode, mode);
3598 SILC_LOG_DEBUG(("Send CUMODE_CHANGE notify to channel"));
3599 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3600 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
3601 clidp->data, clidp->len,
3602 mode, 4, clidp->data, clidp->len,
3607 /* Set CUMODE notify type to network */
3609 silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
3610 SILC_BROADCAST(server), channel,
3611 chl->mode, client->id, SILC_ID_CLIENT,
3612 client->id, channel->founder_key);
3614 silc_buffer_free(reply);
3615 silc_buffer_free(clidp);
3616 silc_buffer_free(chidp);
3617 silc_buffer_free(keyp);
3618 silc_buffer_free(user_list);
3619 silc_buffer_free(mode_list);
3623 silc_free(passphrase);
3626 /* Server side of command JOIN. Joins client into requested channel. If
3627 the channel does not exist it will be created. */
3629 SILC_SERVER_CMD_FUNC(join)
3631 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3632 SilcServer server = cmd->server;
3633 unsigned char *auth;
3634 SilcUInt32 tmp_len, auth_len;
3635 char *tmp, *channel_name = NULL, *cipher, *hmac;
3636 SilcChannelEntry channel;
3637 SilcUInt32 umode = 0;
3638 bool created = FALSE, create_key = TRUE;
3639 SilcClientID *client_id;
3641 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3643 /* Get channel name */
3644 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3646 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3647 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3654 channel_name[255] = '\0';
3656 if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
3657 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3658 SILC_STATUS_ERR_BAD_CHANNEL, 0);
3662 /* Get Client ID of the client who is joining to the channel */
3663 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3665 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3666 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3670 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3672 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3673 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3678 /* Get cipher, hmac name and auth payload */
3679 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3680 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3681 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3683 /* See if the channel exists */
3684 channel = silc_idlist_find_channel_by_name(server->local_list,
3685 channel_name, NULL);
3687 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3688 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3690 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3691 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3696 silc_free(client_id);
3697 client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
3700 (channel->disabled && server->server_type != SILC_ROUTER)) {
3701 /* Channel not found or not valid */
3703 /* If we are standalone server we don't have a router, we just create
3704 the channel by ourselves (unless it existed). */
3705 if (server->standalone) {
3707 channel = silc_server_create_new_channel(server, server->id, cipher,
3708 hmac, channel_name, TRUE);
3710 silc_server_command_send_status_reply(
3711 cmd, SILC_COMMAND_JOIN,
3712 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
3714 silc_free(client_id);
3718 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3724 /* The channel does not exist on our server. If we are normal server
3725 we will send JOIN command to our router which will handle the
3726 joining procedure (either creates the channel if it doesn't exist
3727 or joins the client to it). */
3728 if (server->server_type != SILC_ROUTER) {
3730 SilcUInt16 old_ident;
3732 /* If this is pending command callback then we've resolved
3733 it and it didn't work, return since we've notified the
3734 client already in the command reply callback. */
3736 silc_free(client_id);
3740 old_ident = silc_command_get_ident(cmd->payload);
3741 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3742 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3744 /* Send JOIN command to our router */
3745 silc_server_packet_send(server, (SilcSocketConnection)
3746 SILC_PRIMARY_ROUTE(server),
3747 SILC_PACKET_COMMAND, cmd->packet->flags,
3748 tmpbuf->data, tmpbuf->len, TRUE);
3750 /* Reprocess this packet after received reply from router */
3751 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3752 silc_command_get_ident(cmd->payload),
3753 silc_server_command_join,
3754 silc_server_command_dup(cmd));
3755 cmd->pending = TRUE;
3756 silc_command_set_ident(cmd->payload, old_ident);
3757 silc_buffer_free(tmpbuf);
3758 silc_free(client_id);
3762 /* We are router and the channel does not seem exist so we will check
3763 our global list as well for the channel. */
3764 channel = silc_idlist_find_channel_by_name(server->global_list,
3765 channel_name, NULL);
3767 /* Channel really does not exist, create it */
3768 channel = silc_server_create_new_channel(server, server->id, cipher,
3769 hmac, channel_name, TRUE);
3771 silc_server_command_send_status_reply(
3772 cmd, SILC_COMMAND_JOIN,
3773 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
3774 silc_free(client_id);
3778 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3786 /* Channel not found */
3788 /* If the command came from router and we are normal server then
3789 something went wrong with the joining as the channel was not found.
3790 We can't do anything else but ignore this. */
3791 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3792 server->server_type != SILC_ROUTER) {
3793 silc_free(client_id);
3797 /* We are router and the channel does not seem exist so we will check
3798 our global list as well for the channel. */
3799 channel = silc_idlist_find_channel_by_name(server->global_list,
3800 channel_name, NULL);
3802 /* Channel really does not exist, create it */
3803 channel = silc_server_create_new_channel(server, server->id, cipher,
3804 hmac, channel_name, TRUE);
3806 silc_server_command_send_status_reply(
3807 cmd, SILC_COMMAND_JOIN,
3808 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
3809 silc_free(client_id);
3813 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3820 /* Check whether the channel was created by our router */
3821 if (cmd->pending && context2) {
3822 SilcServerCommandReplyContext reply = context2;
3824 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3825 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3826 SILC_GET32_MSB(created, tmp);
3827 if (silc_argument_get_arg_type(reply->args, 7, NULL))
3828 create_key = FALSE; /* Router returned the key already */
3830 if (silc_command_get_status(reply->payload, NULL, NULL) &&
3831 channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3832 /* Save channel passphrase, if user provided it successfully */
3835 pa = silc_argument_get_arg_type(cmd->args, 3, &pa_len);
3837 silc_free(channel->passphrase);
3838 channel->passphrase = silc_memdup(pa, pa_len);
3843 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
3844 !channel->disabled && !silc_hash_table_count(channel->user_list))
3848 /* If the channel does not have global users and is also empty the client
3849 will be the channel founder and operator. */
3850 if (!channel->disabled &&
3851 !channel->global_users && !silc_hash_table_count(channel->user_list))
3852 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3854 /* Join to the channel */
3855 silc_server_command_join_channel(server, cmd, channel, client_id,
3856 created, create_key, umode,
3859 silc_free(client_id);
3862 silc_server_command_free(cmd);
3865 /* Server side of command MOTD. Sends server's current "message of the
3866 day" to the client. */
3868 SILC_SERVER_CMD_FUNC(motd)
3870 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3871 SilcServer server = cmd->server;
3872 SilcBuffer packet, idp;
3873 char *motd, *dest_server;
3874 SilcUInt32 motd_len;
3875 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3877 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3879 /* Get server name */
3880 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3882 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3883 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3887 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3890 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3892 if (server->config && server->config->server_info &&
3893 server->config->server_info->motd_file) {
3895 motd = silc_file_readfile(server->config->server_info->motd_file,
3901 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3908 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3914 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3915 packet->data, packet->len, FALSE);
3916 silc_buffer_free(packet);
3917 silc_buffer_free(idp);
3919 SilcServerEntry entry;
3921 /* Check whether we have this server cached */
3922 entry = silc_idlist_find_server_by_name(server->global_list,
3923 dest_server, TRUE, NULL);
3925 entry = silc_idlist_find_server_by_name(server->local_list,
3926 dest_server, TRUE, NULL);
3929 if (server->server_type != SILC_SERVER && !cmd->pending &&
3930 entry && !entry->motd) {
3931 /* Send to the server */
3933 SilcUInt16 old_ident;
3935 old_ident = silc_command_get_ident(cmd->payload);
3936 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3937 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3939 silc_server_packet_send(server, entry->connection,
3940 SILC_PACKET_COMMAND, cmd->packet->flags,
3941 tmpbuf->data, tmpbuf->len, TRUE);
3943 /* Reprocess this packet after received reply from router */
3944 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3945 silc_command_get_ident(cmd->payload),
3946 silc_server_command_motd,
3947 silc_server_command_dup(cmd));
3948 cmd->pending = TRUE;
3949 silc_command_set_ident(cmd->payload, old_ident);
3950 silc_buffer_free(tmpbuf);
3954 if (!entry && !cmd->pending && !server->standalone) {
3955 /* Send to the primary router */
3957 SilcUInt16 old_ident;
3959 old_ident = silc_command_get_ident(cmd->payload);
3960 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3961 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3963 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
3964 SILC_PACKET_COMMAND, cmd->packet->flags,
3965 tmpbuf->data, tmpbuf->len, TRUE);
3967 /* Reprocess this packet after received reply from router */
3968 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3969 silc_command_get_ident(cmd->payload),
3970 silc_server_command_motd,
3971 silc_server_command_dup(cmd));
3972 cmd->pending = TRUE;
3973 silc_command_set_ident(cmd->payload, old_ident);
3974 silc_buffer_free(tmpbuf);
3979 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3980 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3984 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3985 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3986 SILC_STATUS_OK, 0, ident, 2,
3990 strlen(entry->motd) : 0);
3991 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3992 packet->data, packet->len, FALSE);
3993 silc_buffer_free(packet);
3994 silc_buffer_free(idp);
3998 silc_server_command_free(cmd);
4001 /* Server side of command UMODE. Client can use this command to set/unset
4002 user mode. Client actually cannot set itself to be as server/router
4003 operator so this can be used only to unset the modes. */
4005 SILC_SERVER_CMD_FUNC(umode)
4007 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4008 SilcServer server = cmd->server;
4009 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4011 unsigned char *tmp_mask, m[4];
4012 SilcUInt32 mask = 0;
4013 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4014 bool set_mask = FALSE;
4016 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
4019 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2);
4021 /* Get the client's mode mask */
4022 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4024 SILC_GET32_MSB(mask, tmp_mask);
4029 /* Check that mode changing is allowed. */
4030 if (!silc_server_check_umode_rights(server, client, mask)) {
4031 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
4032 SILC_STATUS_ERR_PERM_DENIED, 0);
4036 /* Anonymous mode cannot be set by client */
4037 if (mask & SILC_UMODE_ANONYMOUS) {
4038 if (!(client->mode & SILC_UMODE_ANONYMOUS)) {
4039 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
4040 SILC_STATUS_ERR_PERM_DENIED, 0);
4044 if (client->mode & SILC_UMODE_ANONYMOUS) {
4045 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
4046 SILC_STATUS_ERR_PERM_DENIED, 0);
4051 /* Update statistics */
4052 if (mask & SILC_UMODE_GONE) {
4053 if (!(client->mode & SILC_UMODE_GONE))
4054 server->stat.my_aways++;
4056 if (client->mode & SILC_UMODE_GONE)
4057 server->stat.my_aways--;
4060 /* Change the mode */
4061 client->mode = mask;
4063 /* Send UMODE change to primary router */
4064 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
4065 SILC_BROADCAST(server), client->id,
4068 /* Check if anyone is watching this nickname */
4069 if (server->server_type == SILC_ROUTER)
4070 silc_server_check_watcher_list(server, client, NULL,
4071 SILC_NOTIFY_TYPE_UMODE_CHANGE);
4074 /* Send command reply to sender */
4075 SILC_PUT32_MSB(client->mode, m);
4076 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
4077 SILC_STATUS_OK, 0, ident, 1,
4079 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4080 packet->data, packet->len, FALSE);
4081 silc_buffer_free(packet);
4084 silc_server_command_free(cmd);
4087 /* Server side command of CMODE. Changes channel mode */
4089 SILC_SERVER_CMD_FUNC(cmode)
4091 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4092 SilcServer server = cmd->server;
4093 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4094 SilcIDListData idata = (SilcIDListData)client;
4095 SilcChannelID *channel_id = NULL;
4096 SilcChannelEntry channel;
4097 SilcChannelClientEntry chl;
4098 SilcBuffer packet, cidp;
4099 unsigned char *tmp, *tmp_id, *tmp_mask;
4100 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
4101 SilcUInt32 mode_mask = 0, old_mask = 0, tmp_len, tmp_len2;
4102 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4103 bool set_mask = FALSE;
4104 SilcPublicKey founder_key = NULL;
4105 unsigned char *fkey = NULL;
4106 SilcUInt32 fkey_len = 0;
4109 silc_server_command_free(cmd);
4113 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 7);
4115 /* Get Channel ID */
4116 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
4118 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4119 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4120 silc_server_command_free(cmd);
4123 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
4125 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4126 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4127 silc_server_command_free(cmd);
4131 /* Get channel entry */
4132 channel = silc_idlist_find_channel_by_id(server->local_list,
4135 channel = silc_idlist_find_channel_by_id(server->global_list,
4138 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4139 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4141 silc_free(channel_id);
4142 silc_server_command_free(cmd);
4146 old_mask = channel->mode;
4148 /* Get the channel mode mask */
4149 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4151 SILC_GET32_MSB(mode_mask, tmp_mask);
4155 /* Check whether this client is on the channel */
4156 if (!silc_server_client_on_channel(client, channel, &chl)) {
4157 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4158 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4162 /* Check that client has rights to change any requested channel modes */
4163 if (set_mask && !silc_server_check_cmode_rights(server, channel, chl,
4165 SILC_LOG_DEBUG(("Client does not have rights to change mode"));
4166 silc_server_command_send_status_reply(
4167 cmd, SILC_COMMAND_CMODE,
4168 (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) ?
4169 SILC_STATUS_ERR_NO_CHANNEL_PRIV :
4170 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV), 0);
4174 /* If mode mask was not sent as argument then merely return the current
4175 mode mask to the sender. */
4178 SILC_PUT32_MSB(channel->mode, m);
4179 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4180 SILC_STATUS_OK, 0, ident, 2,
4181 2, tmp_id, tmp_len2,
4183 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4184 packet->data, packet->len, FALSE);
4185 silc_buffer_free(packet);
4190 * Check the modes. Modes that requires nothing special operation are
4194 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
4195 /* Channel uses private keys to protect traffic. Client(s) has set the
4196 key locally they want to use, server does not know that key. */
4197 /* Nothing interesting to do here */
4199 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
4200 /* The mode is removed and we need to generate and distribute
4201 new channel key. Clients are not using private channel keys
4202 anymore after this. */
4204 /* Re-generate channel key */
4205 if (!silc_server_create_channel_key(server, channel, 0))
4208 /* Send the channel key. This sends it to our local clients and if
4209 we are normal server to our router as well. */
4210 silc_server_send_channel_key(server, NULL, channel,
4211 server->server_type == SILC_ROUTER ?
4212 FALSE : !server->standalone);
4214 cipher = channel->channel_key->cipher->name;
4215 hmac = (char *)silc_hmac_get_name(channel->hmac);
4219 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
4220 /* User limit is set on channel */
4221 SilcUInt32 user_limit;
4223 /* Get user limit */
4224 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
4226 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
4227 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4228 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4232 SILC_GET32_MSB(user_limit, tmp);
4233 channel->user_limit = user_limit;
4236 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
4237 /* User limit mode is unset. Remove user limit */
4238 channel->user_limit = 0;
4241 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
4242 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
4243 /* Passphrase has been set to channel */
4245 /* Get the passphrase */
4246 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
4248 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4249 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4253 /* Save the passphrase */
4254 passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
4257 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
4258 /* Passphrase mode is unset. remove the passphrase */
4259 silc_free(channel->passphrase);
4260 channel->passphrase = NULL;
4264 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
4265 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
4266 /* Cipher to use protect the traffic */
4267 SilcCipher newkey, oldkey;
4270 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
4272 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4273 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4277 /* Delete old cipher and allocate the new one */
4278 if (!silc_cipher_alloc(cipher, &newkey)) {
4279 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4280 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4284 oldkey = channel->channel_key;
4285 channel->channel_key = newkey;
4287 /* Re-generate channel key */
4288 if (!silc_server_create_channel_key(server, channel, 0)) {
4289 /* We don't have new key, revert to old one */
4290 channel->channel_key = oldkey;
4294 /* Remove old channel key for good */
4295 silc_cipher_free(oldkey);
4297 /* Send the channel key. This sends it to our local clients and if
4298 we are normal server to our router as well. */
4299 silc_server_send_channel_key(server, NULL, channel,
4300 server->server_type == SILC_ROUTER ?
4301 FALSE : !server->standalone);
4304 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
4305 /* Cipher mode is unset. Remove the cipher and revert back to
4307 SilcCipher newkey, oldkey;
4308 cipher = channel->cipher;
4310 /* Delete old cipher and allocate default one */
4311 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
4312 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4313 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4317 oldkey = channel->channel_key;
4318 channel->channel_key = newkey;
4320 /* Re-generate channel key */
4321 if (!silc_server_create_channel_key(server, channel, 0)) {
4322 /* We don't have new key, revert to old one */
4323 channel->channel_key = oldkey;
4327 /* Remove old channel key for good */
4328 silc_cipher_free(oldkey);
4330 /* Send the channel key. This sends it to our local clients and if
4331 we are normal server to our router as well. */
4332 silc_server_send_channel_key(server, NULL, channel,
4333 server->server_type == SILC_ROUTER ?
4334 FALSE : !server->standalone);
4338 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
4339 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
4340 /* HMAC to use protect the traffic */
4341 unsigned char hash[32];
4345 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4347 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4348 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4352 /* Delete old hmac and allocate the new one */
4353 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4354 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4355 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4359 silc_hmac_free(channel->hmac);
4360 channel->hmac = newhmac;
4362 /* Set the HMAC key out of current channel key. The client must do
4364 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4365 channel->key_len / 8, hash);
4366 silc_hmac_set_key(channel->hmac, hash,
4367 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4368 memset(hash, 0, sizeof(hash));
4371 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4372 /* Hmac mode is unset. Remove the hmac and revert back to
4375 unsigned char hash[32];
4376 hmac = channel->hmac_name;
4378 /* Delete old hmac and allocate default one */
4379 silc_hmac_free(channel->hmac);
4380 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4381 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4382 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4386 silc_hmac_free(channel->hmac);
4387 channel->hmac = newhmac;
4389 /* Set the HMAC key out of current channel key. The client must do
4391 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4392 channel->key_len / 8,
4394 silc_hmac_set_key(channel->hmac, hash,
4395 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4396 memset(hash, 0, sizeof(hash));
4400 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4401 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4402 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4403 /* Set the founder authentication */
4404 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4406 silc_server_command_send_status_reply(
4407 cmd, SILC_COMMAND_CMODE,
4408 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4412 /* Verify the payload before setting the mode */
4413 if (!silc_auth_verify_data(tmp, tmp_len, SILC_AUTH_PUBLIC_KEY,
4414 idata->public_key, 0, server->sha1hash,
4415 client->id, SILC_ID_CLIENT)) {
4416 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4417 SILC_STATUS_ERR_AUTH_FAILED,
4422 /* Save the public key */
4423 channel->founder_key = silc_pkcs_public_key_copy(idata->public_key);
4424 if (!channel->founder_key) {
4425 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4426 SILC_STATUS_ERR_AUTH_FAILED,
4431 founder_key = channel->founder_key;
4432 fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
4434 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4435 SILC_STATUS_ERR_AUTH_FAILED,
4437 silc_pkcs_public_key_free(channel->founder_key);
4438 channel->founder_key = NULL;
4444 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4445 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4446 if (channel->founder_key)
4447 silc_pkcs_public_key_free(channel->founder_key);
4448 channel->founder_key = NULL;
4453 /* Finally, set the mode */
4454 old_mask = channel->mode = mode_mask;
4456 /* Send CMODE_CHANGE notify. */
4457 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4458 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4459 SILC_NOTIFY_TYPE_CMODE_CHANGE, 6,
4460 cidp->data, cidp->len,
4462 cipher, cipher ? strlen(cipher) : 0,
4463 hmac, hmac ? strlen(hmac) : 0,
4464 passphrase, passphrase ?
4465 strlen(passphrase) : 0,
4468 /* Set CMODE notify type to network */
4469 silc_server_send_notify_cmode(server, SILC_PRIMARY_ROUTE(server),
4470 SILC_BROADCAST(server), channel,
4471 mode_mask, client->id, SILC_ID_CLIENT,
4472 cipher, hmac, passphrase, founder_key);
4474 /* Send command reply to sender */
4475 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4476 SILC_STATUS_OK, 0, ident, 2,
4477 2, tmp_id, tmp_len2,
4479 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4480 packet->data, packet->len, FALSE);
4482 silc_buffer_free(packet);
4483 silc_buffer_free(cidp);
4486 channel->mode = old_mask;
4488 silc_free(channel_id);
4489 silc_server_command_free(cmd);
4492 /* Server side of CUMODE command. Changes client's mode on a channel. */
4494 SILC_SERVER_CMD_FUNC(cumode)
4496 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4497 SilcServer server = cmd->server;
4498 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4499 SilcIDListData idata = (SilcIDListData)client;
4500 SilcChannelID *channel_id;
4501 SilcClientID *client_id;
4502 SilcChannelEntry channel;
4503 SilcClientEntry target_client;
4504 SilcChannelClientEntry chl;
4505 SilcBuffer packet, idp;
4506 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4507 SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4509 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4510 SilcPublicKey founder_key = NULL;
4511 unsigned char *fkey = NULL;
4512 SilcUInt32 fkey_len = 0;
4517 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4519 /* Get Channel ID */
4520 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4522 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4523 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4526 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
4528 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4529 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4533 /* Get channel entry */
4534 channel = silc_idlist_find_channel_by_id(server->local_list,
4537 channel = silc_idlist_find_channel_by_id(server->global_list,
4540 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4541 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4547 /* Check whether sender is on the channel */
4548 if (!silc_server_client_on_channel(client, channel, &chl)) {
4549 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4550 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4553 sender_mask = chl->mode;
4555 /* Get the target client's channel mode mask */
4556 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4558 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4559 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4563 SILC_GET32_MSB(target_mask, tmp_mask);
4565 /* Get target Client ID */
4566 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4568 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4569 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4572 client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
4574 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4575 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4579 /* Get target client's entry */
4580 target_client = silc_idlist_find_client_by_id(server->local_list,
4581 client_id, TRUE, NULL);
4582 if (!target_client) {
4583 target_client = silc_idlist_find_client_by_id(server->global_list,
4584 client_id, TRUE, NULL);
4587 if (target_client != client &&
4588 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4589 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4590 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4591 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
4595 /* Check whether target client is on the channel */
4596 if (target_client != client) {
4597 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4598 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4599 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL, 0);
4608 /* If the target client is founder, no one else can change their mode
4610 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4611 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4612 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
4617 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4618 if (target_client != client) {
4619 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4620 SILC_STATUS_ERR_NOT_YOU, 0);
4624 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4625 /* The client tries to claim the founder rights. */
4626 unsigned char *tmp_auth;
4627 SilcUInt32 tmp_auth_len;
4628 SilcChannelClientEntry chl2;
4629 SilcHashTableList htl;
4631 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4632 !channel->founder_key || !idata->public_key ||
4633 !silc_pkcs_public_key_compare(channel->founder_key,
4634 idata->public_key)) {
4635 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4636 SILC_STATUS_ERR_AUTH_FAILED, 0);
4640 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4642 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4643 SILC_STATUS_ERR_AUTH_FAILED, 0);
4647 /* Verify the authentication payload */
4648 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len, SILC_AUTH_PUBLIC_KEY,
4649 channel->founder_key, 0, server->sha1hash,
4650 client->id, SILC_ID_CLIENT)) {
4651 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4652 SILC_STATUS_ERR_AUTH_FAILED, 0);
4657 founder_key = channel->founder_key;
4658 fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
4660 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4661 SILC_STATUS_ERR_AUTH_FAILED, 0);
4665 /* There cannot be anyone else as founder on the channel now. This
4666 client is definitely the founder due to this authentication */
4667 silc_hash_table_list(channel->user_list, &htl);
4668 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
4669 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
4670 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4671 silc_server_force_cumode_change(server, NULL, channel, chl2,
4675 silc_hash_table_list_reset(&htl);
4677 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4680 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4681 if (target_client == client) {
4682 /* Remove channel founder rights from itself */
4683 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4686 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4687 SILC_STATUS_ERR_NOT_YOU, 0);
4693 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4694 /* Promote to operator */
4695 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4696 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4697 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4698 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4699 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
4704 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4708 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4709 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4710 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4711 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4712 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
4717 /* Demote to normal user */
4718 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4723 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4724 if (target_client != client) {
4725 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4726 SILC_STATUS_ERR_NOT_YOU, 0);
4730 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
4731 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4735 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4736 if (target_client != client) {
4737 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4738 SILC_STATUS_ERR_NOT_YOU, 0);
4742 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4747 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4748 if (target_client != client) {
4749 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4750 SILC_STATUS_ERR_NOT_YOU, 0);
4754 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)) {
4755 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4759 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4760 if (target_client != client) {
4761 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4762 SILC_STATUS_ERR_NOT_YOU, 0);
4766 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4771 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4772 if (target_client != client) {
4773 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4774 SILC_STATUS_ERR_NOT_YOU, 0);
4778 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)) {
4779 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4783 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4784 if (target_client != client) {
4785 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4786 SILC_STATUS_ERR_NOT_YOU, 0);
4790 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4795 if (target_mask & SILC_CHANNEL_UMODE_QUIET) {
4796 if (!(chl->mode & SILC_CHANNEL_UMODE_QUIET)) {
4797 if (client == target_client) {
4798 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4799 SILC_STATUS_ERR_PERM_DENIED, 0);
4802 chl->mode |= SILC_CHANNEL_UMODE_QUIET;
4806 if (chl->mode & SILC_CHANNEL_UMODE_QUIET) {
4807 if (client == target_client) {
4808 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4809 SILC_STATUS_ERR_PERM_DENIED, 0);
4812 chl->mode &= ~SILC_CHANNEL_UMODE_QUIET;
4817 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4818 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4820 /* Send notify to channel, notify only if mode was actually changed. */
4822 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4823 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
4824 idp->data, idp->len,
4829 /* Set CUMODE notify type to network */
4830 silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
4831 SILC_BROADCAST(server), channel,
4832 target_mask, client->id, SILC_ID_CLIENT,
4833 target_client->id, founder_key);
4836 /* Send command reply to sender */
4837 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4838 SILC_STATUS_OK, 0, ident, 3,
4840 3, tmp_ch_id, tmp_ch_len,
4841 4, tmp_id, tmp_len);
4842 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4843 packet->data, packet->len, FALSE);
4845 silc_buffer_free(packet);
4846 silc_free(channel_id);
4847 silc_free(client_id);
4848 silc_buffer_free(idp);
4852 silc_server_command_free(cmd);
4855 /* Server side of KICK command. Kicks client out of channel. */
4857 SILC_SERVER_CMD_FUNC(kick)
4859 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4860 SilcServer server = cmd->server;
4861 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4862 SilcClientEntry target_client;
4863 SilcChannelID *channel_id;
4864 SilcClientID *client_id;
4865 SilcChannelEntry channel;
4866 SilcChannelClientEntry chl;
4868 SilcUInt32 tmp_len, target_idp_len;
4869 unsigned char *tmp, *comment, *target_idp;
4874 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4876 /* Get Channel ID */
4877 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4879 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4880 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4883 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4885 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4886 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4890 /* Get channel entry */
4891 channel = silc_idlist_find_channel_by_id(server->local_list,
4894 channel = silc_idlist_find_channel_by_id(server->local_list,
4897 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4898 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4904 /* Check whether sender is on the channel */
4905 if (!silc_server_client_on_channel(client, channel, &chl)) {
4906 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4907 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4911 /* Check that the kicker is channel operator or channel founder */
4912 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
4913 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4914 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4915 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
4919 /* Get target Client ID */
4920 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4922 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4923 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4926 client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
4928 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4929 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4933 /* Get target client's entry */
4934 target_client = silc_idlist_find_client_by_id(server->local_list,
4935 client_id, TRUE, NULL);
4936 if (!target_client) {
4937 target_client = silc_idlist_find_client_by_id(server->global_list,
4938 client_id, TRUE, NULL);
4941 /* Check whether target client is on the channel */
4942 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4943 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4944 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL,
4949 /* Check that the target client is not channel founder. Channel founder
4950 cannot be kicked from the channel. */
4951 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4952 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4953 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
4960 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4964 /* Send command reply to sender */
4965 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4968 /* Send KICKED notify to local clients on the channel */
4969 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4970 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4971 SILC_NOTIFY_TYPE_KICKED, 3,
4972 target_idp, target_idp_len,
4973 comment, comment ? strlen(comment) : 0,
4974 idp->data, idp->len);
4975 silc_buffer_free(idp);
4977 /* Send KICKED notify to primary route */
4978 silc_server_send_notify_kicked(server, SILC_PRIMARY_ROUTE(server),
4979 SILC_BROADCAST(server), channel,
4980 target_client->id, client->id, comment);
4982 /* Remove the client from the channel. If the channel does not exist
4983 after removing the client then the client kicked itself off the channel
4984 and we don't have to send anything after that. */
4985 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4986 target_client, FALSE))
4989 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4990 /* Re-generate channel key */
4991 if (!silc_server_create_channel_key(server, channel, 0))
4994 /* Send the channel key to the channel. The key of course is not sent
4995 to the client who was kicked off the channel. */
4996 silc_server_send_channel_key(server, target_client->connection, channel,
4997 server->server_type == SILC_ROUTER ?
4998 FALSE : !server->standalone);
5002 silc_server_command_free(cmd);
5005 /* Server side of OPER command. Client uses this comand to obtain server
5006 operator privileges to this server/router. */
5008 SILC_SERVER_CMD_FUNC(oper)
5010 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5011 SilcServer server = cmd->server;
5012 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5013 unsigned char *username, *auth;
5015 SilcServerConfigAdmin *admin;
5016 SilcIDListData idata = (SilcIDListData)client;
5017 bool result = FALSE;
5018 SilcPublicKey cached_key;
5020 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
5023 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
5025 /* Get the username */
5026 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5028 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
5029 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5034 /* Get the admin configuration */
5035 admin = silc_server_config_find_admin(server, cmd->sock->ip,
5036 username, client->nickname);
5038 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
5039 username, client->nickname);
5041 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
5042 SILC_STATUS_ERR_AUTH_FAILED,
5048 /* Get the authentication payload */
5049 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5051 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
5052 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5057 /* Verify the authentication data. If both passphrase and public key
5058 is set then try both of them. */
5059 if (admin->passphrase)
5060 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
5061 admin->passphrase, admin->passphrase_len,
5062 idata->hash, client->id, SILC_ID_CLIENT);
5063 if (!result && admin->publickeys) {
5064 cached_key = silc_server_get_public_key(server, admin->publickeys);
5067 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
5068 cached_key, 0, idata->hash,
5069 client->id, SILC_ID_CLIENT);
5072 /* Authentication failed */
5073 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
5074 SILC_STATUS_ERR_AUTH_FAILED,
5079 /* Client is now server operator */
5080 client->mode |= SILC_UMODE_SERVER_OPERATOR;
5082 /* Update statistics */
5083 if (SILC_IS_LOCAL(client))
5084 server->stat.my_server_ops++;
5085 if (server->server_type == SILC_ROUTER)
5086 server->stat.server_ops++;
5088 /* Send UMODE change to primary router */
5089 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
5090 SILC_BROADCAST(server), client->id,
5093 /* Check if anyone is watching this nickname */
5094 if (server->server_type == SILC_ROUTER)
5095 silc_server_check_watcher_list(server, client, NULL,
5096 SILC_NOTIFY_TYPE_UMODE_CHANGE);
5098 /* Send reply to the sender */
5099 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
5103 silc_server_command_free(cmd);
5106 SILC_TASK_CALLBACK(silc_server_command_detach_cb)
5108 SilcServer server = app_context;
5109 QuitInternal q = (QuitInternal)context;
5110 SilcClientID *client_id = (SilcClientID *)q->sock;
5111 SilcClientEntry client;
5112 SilcSocketConnection sock;
5114 client = silc_idlist_find_client_by_id(server->local_list, client_id,
5116 if (client && client->connection) {
5117 sock = client->connection;
5119 /* If there is pending outgoing data for the client then purge it
5120 to the network before closing connection. */
5121 silc_server_packet_queue_purge(server, sock);
5123 /* Close the connection on our side */
5124 client->router = NULL;
5125 client->connection = NULL;
5126 sock->user_data = NULL;
5127 silc_server_close_connection(server, sock);
5130 silc_free(client_id);
5134 SILC_TASK_CALLBACK(silc_server_command_detach_timeout)
5136 SilcServer server = app_context;
5137 QuitInternal q = (QuitInternal)context;
5138 SilcClientID *client_id = (SilcClientID *)q->sock;
5139 SilcClientEntry client;
5141 client = silc_idlist_find_client_by_id(server->local_list, client_id,
5143 if (client && client->mode & SILC_UMODE_DETACHED) {
5144 SILC_LOG_DEBUG(("Detach timeout"));
5145 silc_server_free_client_data(server, NULL, client, TRUE,
5149 silc_free(client_id);
5153 /* Server side of DETACH command. Detached the client from the network
5154 by closing the connection but preserving the session. */
5156 SILC_SERVER_CMD_FUNC(detach)
5158 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5159 SilcServer server = cmd->server;
5160 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5163 if (server->config->detach_disabled) {
5164 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
5165 SILC_STATUS_ERR_UNKNOWN_COMMAND, 0);
5169 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
5172 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
5174 /* Remove operator privileges, since the client may resume in some
5175 other server which to it does not have operator privileges. */
5176 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
5177 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
5179 /* Send the user mode notify to notify that client is detached */
5180 client->mode |= SILC_UMODE_DETACHED;
5181 client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
5182 client->last_command = 0;
5183 client->fast_command = 0;
5184 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
5185 SILC_BROADCAST(server), client->id,
5187 server->stat.my_detached++;
5189 /* Check if anyone is watching this nickname */
5190 if (server->server_type == SILC_ROUTER)
5191 silc_server_check_watcher_list(server, client, NULL,
5192 SILC_NOTIFY_TYPE_UMODE_CHANGE);
5194 q = silc_calloc(1, sizeof(*q));
5195 q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
5196 silc_schedule_task_add(server->schedule, 0, silc_server_command_detach_cb,
5197 q, 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
5199 if (server->config->detach_timeout) {
5200 q = silc_calloc(1, sizeof(*q));
5201 q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
5202 silc_schedule_task_add(server->schedule, 0,
5203 silc_server_command_detach_timeout,
5204 q, server->config->detach_timeout * 60,
5205 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
5208 /* Send reply to the sender */
5209 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
5213 silc_server_command_free(cmd);
5216 /* Server side of WATCH command. */
5218 SILC_SERVER_CMD_FUNC(watch)
5220 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5221 SilcServer server = cmd->server;
5222 char *add_nick, *del_nick;
5223 SilcUInt32 add_nick_len, del_nick_len, tmp_len;
5225 unsigned char hash[16], *tmp;
5226 SilcClientEntry client;
5227 SilcClientID *client_id = NULL;
5229 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WATCH, cmd, 1, 3);
5231 if (server->server_type == SILC_SERVER && !server->standalone) {
5232 if (!cmd->pending) {
5233 /* Send the command to router */
5235 SilcUInt16 old_ident;
5237 old_ident = silc_command_get_ident(cmd->payload);
5238 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5239 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5241 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5242 SILC_PACKET_COMMAND, cmd->packet->flags,
5243 tmpbuf->data, tmpbuf->len, TRUE);
5245 /* Reprocess this packet after received reply from router */
5246 silc_server_command_pending(server, SILC_COMMAND_WATCH,
5247 silc_command_get_ident(cmd->payload),
5248 silc_server_command_watch,
5249 silc_server_command_dup(cmd));
5250 cmd->pending = TRUE;
5251 silc_command_set_ident(cmd->payload, old_ident);
5252 silc_buffer_free(tmpbuf);
5253 } else if (context2) {
5254 /* Received reply from router, just send same data to the client. */
5255 SilcServerCommandReplyContext reply = context2;
5257 silc_command_get_status(reply->payload, &status, NULL);
5258 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, status,
5265 /* We are router and keep the watch list for local cell */
5267 /* Get the client ID */
5268 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5270 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5271 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5275 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
5277 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5278 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5283 /* Get the client entry which must be in local list */
5284 client = silc_idlist_find_client_by_id(server->local_list,
5285 client_id, TRUE, NULL);
5287 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5288 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5294 add_nick = silc_argument_get_arg_type(cmd->args, 2, &add_nick_len);
5295 del_nick = silc_argument_get_arg_type(cmd->args, 3, &del_nick_len);
5296 if (!add_nick && !del_nick) {
5297 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5298 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5303 if (add_nick && add_nick_len > 128)
5304 add_nick[128] = '\0';
5305 if (del_nick && del_nick_len > 128)
5306 del_nick[128] = '\0';
5308 memset(nick, 0, sizeof(nick));
5310 /* Add new nickname to be watched in our cell */
5312 if (silc_server_name_bad_chars(add_nick, strlen(add_nick)) == TRUE) {
5313 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5314 SILC_STATUS_ERR_BAD_NICKNAME, 0);
5318 /* Hash the nick, we have the hash saved, not nicks because we can
5319 do one to one mapping to the nick from Client ID hash this way. */
5320 silc_to_lower(add_nick, nick, sizeof(nick) - 1);
5321 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
5323 /* Check whether this client is already watching this nickname */
5324 if (silc_hash_table_find_by_context(server->watcher_list, hash,
5326 /* Nickname is alredy being watched for this client */
5327 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5328 SILC_STATUS_ERR_NICKNAME_IN_USE,
5333 /* Get the nickname from the watcher list and use the same key in
5334 new entries as well. If key doesn't exist then create it. */
5335 if (!silc_hash_table_find(server->watcher_list, hash, (void **)&tmp, NULL))
5336 tmp = silc_memdup(hash, CLIENTID_HASH_LEN);
5338 /* Add the client to the watcher list with the specified nickname hash. */
5339 silc_hash_table_add(server->watcher_list, tmp, client);
5342 /* Delete nickname from watch list */
5344 if (silc_server_name_bad_chars(del_nick, strlen(del_nick)) == TRUE) {
5345 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5346 SILC_STATUS_ERR_BAD_NICKNAME, 0);
5350 /* Hash the nick, we have the hash saved, not nicks because we can
5351 do one to one mapping to the nick from Client ID hash this way. */
5352 silc_to_lower(del_nick, nick, sizeof(nick) - 1);
5353 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
5355 /* Check that this client is watching for this nickname */
5356 if (!silc_hash_table_find_by_context(server->watcher_list, hash,
5357 client, (void **)&tmp)) {
5358 /* Nickname is alredy being watched for this client */
5359 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5360 SILC_STATUS_ERR_NO_SUCH_NICK, 0);
5364 /* Delete the nickname from the watcher list. */
5365 silc_hash_table_del_by_context(server->watcher_list, hash, client);
5367 /* Now check whether there still exists entries with this key, if not
5368 then free the key to not leak memory. */
5369 if (!silc_hash_table_find(server->watcher_list, hash, NULL, NULL))
5373 /* Distribute the watch list to backup routers too */
5374 if (server->backup) {
5376 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5377 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5378 silc_server_backup_send(server, NULL, SILC_PACKET_COMMAND,
5379 cmd->packet->flags, tmpbuf->data, tmpbuf->len,
5381 silc_buffer_free(tmpbuf);
5384 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5388 silc_free(client_id);
5389 silc_server_command_free(cmd);
5392 /* Server side of SILCOPER command. Client uses this comand to obtain router
5393 operator privileges to this router. */
5395 SILC_SERVER_CMD_FUNC(silcoper)
5397 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5398 SilcServer server = cmd->server;
5399 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5400 unsigned char *username, *auth;
5402 SilcServerConfigAdmin *admin;
5403 SilcIDListData idata = (SilcIDListData)client;
5404 bool result = FALSE;
5405 SilcPublicKey cached_key;
5407 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
5410 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
5412 if (server->server_type != SILC_ROUTER) {
5413 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5414 SILC_STATUS_ERR_AUTH_FAILED, 0);
5418 /* Get the username */
5419 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5421 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5422 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5427 /* Get the admin configuration */
5428 admin = silc_server_config_find_admin(server, cmd->sock->ip,
5429 username, client->nickname);
5431 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
5432 username, client->nickname);
5434 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5435 SILC_STATUS_ERR_AUTH_FAILED, 0);
5440 /* Get the authentication payload */
5441 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5443 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5444 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5449 /* Verify the authentication data. If both passphrase and public key
5450 is set then try both of them. */
5451 if (admin->passphrase)
5452 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
5453 admin->passphrase, admin->passphrase_len,
5454 idata->hash, client->id, SILC_ID_CLIENT);
5455 if (!result && admin->publickeys) {
5456 cached_key = silc_server_get_public_key(server, admin->publickeys);
5459 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
5460 cached_key, 0, idata->hash,
5461 client->id, SILC_ID_CLIENT);
5464 /* Authentication failed */
5465 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
5466 SILC_STATUS_ERR_AUTH_FAILED, 0);
5470 /* Client is now router operator */
5471 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
5473 /* Update statistics */
5474 if (SILC_IS_LOCAL(client))
5475 server->stat.my_router_ops++;
5476 if (server->server_type == SILC_ROUTER)
5477 server->stat.router_ops++;
5479 /* Send UMODE change to primary router */
5480 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
5481 SILC_BROADCAST(server), client->id,
5484 /* Check if anyone is watching this nickname */
5485 if (server->server_type == SILC_ROUTER)
5486 silc_server_check_watcher_list(server, client, NULL,
5487 SILC_NOTIFY_TYPE_UMODE_CHANGE);
5489 /* Send reply to the sender */
5490 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5494 silc_server_command_free(cmd);
5497 /* Server side of command BAN. This is used to manage the ban list of the
5498 channel. To add clients and remove clients from the ban list. */
5500 SILC_SERVER_CMD_FUNC(ban)
5502 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5503 SilcServer server = cmd->server;
5504 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5506 SilcChannelEntry channel;
5507 SilcChannelClientEntry chl;
5508 SilcChannelID *channel_id = NULL;
5509 unsigned char *id, *add, *del;
5510 SilcUInt32 id_len, tmp_len;
5511 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5513 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
5516 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
5518 /* Get Channel ID */
5519 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
5521 channel_id = silc_id_payload_parse_id(id, id_len, NULL);
5523 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5524 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5529 /* Get channel entry. The server must know about the channel since the
5530 client is expected to be on the channel. */
5531 channel = silc_idlist_find_channel_by_id(server->local_list,
5534 channel = silc_idlist_find_channel_by_id(server->global_list,
5537 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5538 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5544 /* Check whether this client is on the channel */
5545 if (!silc_server_client_on_channel(client, channel, &chl)) {
5546 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5547 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5551 /* The client must be at least channel operator. */
5552 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
5553 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5554 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
5558 /* Get the new ban and add it to the ban list */
5559 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5561 if (!channel->ban_list)
5562 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
5564 channel->ban_list = silc_realloc(channel->ban_list,
5565 sizeof(*channel->ban_list) *
5567 strlen(channel->ban_list) + 2));
5568 if (add[tmp_len - 1] == ',')
5569 add[tmp_len - 1] = '\0';
5571 strncat(channel->ban_list, add, tmp_len);
5572 strncat(channel->ban_list, ",", 1);
5575 /* Get the ban to be removed and remove it from the list */
5576 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
5577 if (del && channel->ban_list) {
5578 char *start, *end, *n;
5580 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
5581 silc_free(channel->ban_list);
5582 channel->ban_list = NULL;
5584 start = strstr(channel->ban_list, del);
5585 if (start && strlen(start) >= tmp_len) {
5586 end = start + tmp_len;
5587 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
5588 strncat(n, channel->ban_list, start - channel->ban_list);
5589 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
5591 silc_free(channel->ban_list);
5592 channel->ban_list = n;
5597 /* Send the BAN notify type to our primary router. */
5599 silc_server_send_notify_ban(server, SILC_PRIMARY_ROUTE(server),
5600 SILC_BROADCAST(server), channel, add, del);
5602 /* Send the reply back to the client */
5604 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
5605 SILC_STATUS_OK, 0, ident, 2,
5607 3, channel->ban_list,
5609 strlen(channel->ban_list) -1 : 0);
5610 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5611 packet->data, packet->len, FALSE);
5613 silc_buffer_free(packet);
5616 silc_free(channel_id);
5617 silc_server_command_free(cmd);
5620 /* Server side command of LEAVE. Removes client from a channel. */
5622 SILC_SERVER_CMD_FUNC(leave)
5624 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5625 SilcServer server = cmd->server;
5626 SilcSocketConnection sock = cmd->sock;
5627 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
5628 SilcChannelID *id = NULL;
5629 SilcChannelEntry channel;
5633 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !id_entry)
5636 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
5638 /* Get Channel ID */
5639 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
5641 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5642 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5645 id = silc_id_payload_parse_id(tmp, len, NULL);
5647 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5648 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5652 /* Get channel entry */
5653 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5655 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5657 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5658 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5664 /* Check whether this client is on the channel */
5665 if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
5666 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5667 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5671 /* Notify routers that they should remove this client from their list
5672 of clients on the channel. Send LEAVE notify type. */
5673 silc_server_send_notify_leave(server, SILC_PRIMARY_ROUTE(server),
5674 SILC_BROADCAST(server), channel, id_entry->id);
5676 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
5677 SILC_STATUS_OK, 0, 2, tmp, len);
5679 /* Remove client from channel */
5680 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5682 /* If the channel does not exist anymore we won't send anything */
5685 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5686 /* Re-generate channel key */
5687 if (!silc_server_create_channel_key(server, channel, 0))
5690 /* Send the channel key */
5691 silc_server_send_channel_key(server, NULL, channel,
5692 server->server_type == SILC_ROUTER ?
5693 FALSE : !server->standalone);
5698 silc_server_command_free(cmd);
5701 /* Server side of command USERS. Resolves clients and their USERS currently
5702 joined on the requested channel. The list of Client ID's and their modes
5703 on the channel is sent back. */
5705 SILC_SERVER_CMD_FUNC(users)
5707 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5708 SilcServer server = cmd->server;
5709 SilcChannelEntry channel;
5710 SilcChannelID *id = NULL;
5711 SilcBuffer packet, idp;
5712 unsigned char *channel_id;
5713 SilcUInt32 channel_id_len;
5714 SilcBuffer client_id_list;
5715 SilcBuffer client_mode_list;
5716 unsigned char lc[4];
5717 SilcUInt32 list_count = 0;
5718 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5721 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5723 /* Get Channel ID */
5724 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5726 /* Get channel name */
5727 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5729 if (!channel_id && !channel_name) {
5730 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5731 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5736 id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
5738 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5739 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5744 /* If we are server and we don't know about this channel we will send
5745 the command to our router. If we know about the channel then we also
5746 have the list of users already. */
5748 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5750 channel = silc_idlist_find_channel_by_name(server->local_list,
5751 channel_name, NULL);
5753 if (!channel || (!server->standalone && (channel->disabled ||
5754 !channel->users_resolved))) {
5755 if (server->server_type != SILC_ROUTER && !server->standalone &&
5759 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5760 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5762 /* Send USERS command */
5763 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5764 SILC_PACKET_COMMAND, cmd->packet->flags,
5765 tmpbuf->data, tmpbuf->len, TRUE);
5767 /* Reprocess this packet after received reply */
5768 silc_server_command_pending(server, SILC_COMMAND_USERS,
5769 silc_command_get_ident(cmd->payload),
5770 silc_server_command_users,
5771 silc_server_command_dup(cmd));
5772 cmd->pending = TRUE;
5773 silc_command_set_ident(cmd->payload, ident);
5774 silc_buffer_free(tmpbuf);
5779 /* Check the global list as well. */
5781 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5783 channel = silc_idlist_find_channel_by_name(server->global_list,
5784 channel_name, NULL);
5786 /* Channel really does not exist */
5787 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5788 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5794 /* If the channel is private or secret do not send anything, unless the
5795 user requesting this command is on the channel or is server */
5796 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5797 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5798 && !silc_server_client_on_channel(cmd->sock->user_data, channel,
5800 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5801 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5807 /* Get the users list */
5808 if (!silc_server_get_users_on_channel(server, channel, &client_id_list,
5809 &client_mode_list, &list_count)) {
5811 client_id_list = NULL;
5812 client_mode_list = NULL;
5816 SILC_PUT32_MSB(list_count, lc);
5819 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5820 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5821 SILC_STATUS_OK, 0, ident, 4,
5822 2, idp->data, idp->len,
5825 client_id_list->data : NULL,
5827 client_id_list->len : 0,
5828 5, client_mode_list ?
5829 client_mode_list->data : NULL,
5831 client_mode_list->len : 0);
5832 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5833 packet->data, packet->len, FALSE);
5835 silc_buffer_free(idp);
5836 silc_buffer_free(packet);
5838 silc_buffer_free(client_id_list);
5839 if (client_mode_list)
5840 silc_buffer_free(client_mode_list);
5844 silc_server_command_free(cmd);
5847 /* Server side of command GETKEY. This fetches the client's public key
5848 from the server where to the client is connected. */
5850 SILC_SERVER_CMD_FUNC(getkey)
5852 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5853 SilcServer server = cmd->server;
5855 SilcClientEntry client;
5856 SilcServerEntry server_entry;
5857 SilcClientID *client_id = NULL;
5858 SilcServerID *server_id = NULL;
5859 SilcIDPayload idp = NULL;
5860 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5861 unsigned char *tmp, *pkdata;
5862 SilcUInt32 tmp_len, pklen;
5863 SilcBuffer pk = NULL;
5865 SilcPublicKey public_key;
5867 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5869 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5870 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5874 idp = silc_id_payload_parse(tmp, tmp_len);
5876 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5877 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5882 id_type = silc_id_payload_get_type(idp);
5883 if (id_type == SILC_ID_CLIENT) {
5884 client_id = silc_id_payload_get_id(idp);
5886 /* If the client is not found from local list there is no chance it
5887 would be locally connected client so send the command further. */
5888 client = silc_idlist_find_client_by_id(server->local_list,
5889 client_id, TRUE, NULL);
5891 client = silc_idlist_find_client_by_id(server->global_list,
5892 client_id, TRUE, NULL);
5894 if ((!client && !cmd->pending && !server->standalone) ||
5895 (client && !client->connection && !cmd->pending &&
5896 !(client->mode & SILC_UMODE_DETACHED)) ||
5897 (client && !client->data.public_key && !cmd->pending)) {
5899 SilcUInt16 old_ident;
5900 SilcSocketConnection dest_sock;
5902 dest_sock = silc_server_get_client_route(server, NULL, 0,
5903 client_id, NULL, NULL);
5907 old_ident = silc_command_get_ident(cmd->payload);
5908 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5909 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5911 silc_server_packet_send(server, dest_sock,
5912 SILC_PACKET_COMMAND, cmd->packet->flags,
5913 tmpbuf->data, tmpbuf->len, TRUE);
5915 /* Reprocess this packet after received reply from router */
5916 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5917 silc_command_get_ident(cmd->payload),
5918 silc_server_command_getkey,
5919 silc_server_command_dup(cmd));
5920 cmd->pending = TRUE;
5921 silc_command_set_ident(cmd->payload, old_ident);
5922 silc_buffer_free(tmpbuf);
5927 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5928 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5933 /* The client is locally connected, just get the public key and
5934 send it back. If they key does not exist then do not send it,
5935 send just OK reply */
5936 public_key = client->data.public_key;
5941 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5942 pk = silc_buffer_alloc(4 + tmp_len);
5943 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5944 silc_buffer_format(pk,
5945 SILC_STR_UI_SHORT(tmp_len),
5946 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5947 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5953 } else if (id_type == SILC_ID_SERVER) {
5954 server_id = silc_id_payload_get_id(idp);
5956 /* If the server is not found from local list there is no chance it
5957 would be locally connected server so send the command further. */
5958 server_entry = silc_idlist_find_server_by_id(server->local_list,
5959 server_id, TRUE, NULL);
5961 server_entry = silc_idlist_find_server_by_id(server->global_list,
5962 server_id, TRUE, NULL);
5964 if (server_entry != server->id_entry &&
5965 ((!server_entry && !cmd->pending && !server->standalone) ||
5966 (server_entry && !server_entry->connection && !cmd->pending &&
5967 !server->standalone) ||
5968 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5969 !server->standalone))) {
5971 SilcUInt16 old_ident;
5973 old_ident = silc_command_get_ident(cmd->payload);
5974 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5975 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5977 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5978 SILC_PACKET_COMMAND, cmd->packet->flags,
5979 tmpbuf->data, tmpbuf->len, TRUE);
5981 /* Reprocess this packet after received reply from router */
5982 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5983 silc_command_get_ident(cmd->payload),
5984 silc_server_command_getkey,
5985 silc_server_command_dup(cmd));
5986 cmd->pending = TRUE;
5987 silc_command_set_ident(cmd->payload, old_ident);
5988 silc_buffer_free(tmpbuf);
5992 if (!server_entry) {
5993 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5994 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
5999 /* If they key does not exist then do not send it, send just OK reply */
6000 public_key = (!server_entry->data.public_key ?
6001 (server_entry == server->id_entry ? server->public_key :
6002 NULL) : server_entry->data.public_key);
6007 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
6008 pk = silc_buffer_alloc(4 + tmp_len);
6009 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
6010 silc_buffer_format(pk,
6011 SILC_STR_UI_SHORT(tmp_len),
6012 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
6013 SILC_STR_UI_XNSTRING(tmp, tmp_len),
6023 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
6024 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
6025 SILC_STATUS_OK, 0, ident,
6029 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
6030 packet->data, packet->len, FALSE);
6031 silc_buffer_free(packet);
6034 silc_buffer_free(pk);
6038 silc_id_payload_free(idp);
6039 silc_free(client_id);
6040 silc_free(server_id);
6041 silc_server_command_free(cmd);
6045 /* Private range commands, specific to this implementation */
6047 /* Server side command of CONNECT. Connects us to the specified remote
6048 server or router. */
6050 SILC_SERVER_CMD_FUNC(connect)
6052 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
6053 SilcServer server = cmd->server;
6054 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
6055 unsigned char *tmp, *host;
6057 SilcUInt32 port = SILC_PORT;
6059 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
6062 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
6064 /* Check whether client has the permissions. */
6065 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
6066 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
6067 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
6068 SILC_STATUS_ERR_NO_SERVER_PRIV, 0);
6072 if (server->server_type == SILC_ROUTER &&
6073 client->mode & SILC_UMODE_SERVER_OPERATOR) {
6074 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
6075 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
6079 /* Get the remote server */
6080 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
6082 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
6083 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
6089 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
6091 SILC_GET32_MSB(port, tmp);
6093 /* Create the connection. It is done with timeout and is async. */
6094 silc_server_create_connection(server, host, port);
6096 /* Send reply to the sender */
6097 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
6101 silc_server_command_free(cmd);
6104 /* Server side command of CLOSE. Closes connection to a specified server. */
6106 SILC_SERVER_CMD_FUNC(close)
6108 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
6109 SilcServer server = cmd->server;
6110 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
6111 SilcServerEntry server_entry;
6112 SilcSocketConnection sock;
6115 unsigned char *name;
6116 SilcUInt32 port = SILC_PORT;
6118 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
6121 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
6123 /* Check whether client has the permissions. */
6124 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
6125 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
6126 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
6127 SILC_STATUS_ERR_NO_SERVER_PRIV,
6132 /* Get the remote server */
6133 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
6135 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
6136 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
6142 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
6144 SILC_GET32_MSB(port, tmp);
6146 server_entry = silc_idlist_find_server_by_conn(server->local_list,
6147 name, port, FALSE, NULL);
6149 server_entry = silc_idlist_find_server_by_conn(server->global_list,
6150 name, port, FALSE, NULL);
6151 if (!server_entry) {
6152 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
6153 SILC_STATUS_ERR_NO_SERVER_ID, 0);
6157 if (server_entry == server->id_entry) {
6158 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
6159 SILC_STATUS_ERR_NO_SERVER_ID, 0);
6163 /* Send reply to the sender */
6164 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
6167 /* Close the connection to the server */
6168 sock = (SilcSocketConnection)server_entry->connection;
6170 /* If we shutdown primary router connection manually then don't trigger
6171 any reconnect or backup router connections, by setting the router
6173 if (server->router == server_entry) {
6174 server->id_entry->router = NULL;
6175 server->router = NULL;
6176 server->standalone = TRUE;
6178 silc_server_free_sock_user_data(server, sock, NULL);
6179 silc_server_close_connection(server, sock);
6182 silc_server_command_free(cmd);
6185 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
6186 active connections. */
6188 SILC_SERVER_CMD_FUNC(shutdown)
6190 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
6191 SilcServer server = cmd->server;
6192 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
6194 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
6197 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
6199 /* Check whether client has the permission. */
6200 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
6201 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
6202 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
6203 SILC_STATUS_ERR_NO_SERVER_PRIV,
6208 /* Send reply to the sender */
6209 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
6212 /* Then, gracefully, or not, bring the server down. */
6213 silc_server_stop(server);
6217 silc_server_command_free(cmd);