5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2002 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
21 #include "serverincludes.h"
22 #include "server_internal.h"
24 static int silc_server_is_registered(SilcServer server,
25 SilcSocketConnection sock,
26 SilcServerCommandContext cmd,
29 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
34 silc_server_command_send_status_data(SilcServerCommandContext cmd,
39 const unsigned char *arg,
42 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
43 SilcServerCommandReplyContext cmdr,
45 SILC_TASK_CALLBACK(silc_server_command_process_timeout);
47 /* Server command list. */
48 SilcServerCommand silc_command_list[] =
50 SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
51 SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
52 SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
53 SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
54 SILC_SERVER_CMD(list, LIST, SILC_CF_LAG_STRICT | SILC_CF_REG),
55 SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
56 SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
57 SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
58 SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG_STRICT | SILC_CF_REG | SILC_CF_OPER),
59 SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
60 SILC_SERVER_CMD(stats, STATS, SILC_CF_LAG | SILC_CF_REG),
61 SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
62 SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
63 SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG_STRICT | SILC_CF_REG),
64 SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
65 SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
66 SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG_STRICT | SILC_CF_REG),
67 SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
68 SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
69 SILC_SERVER_CMD(ban, BAN, SILC_CF_LAG_STRICT | SILC_CF_REG),
70 SILC_SERVER_CMD(detach, DETACH, SILC_CF_LAG_STRICT | SILC_CF_REG),
71 SILC_SERVER_CMD(watch, WATCH, SILC_CF_LAG | SILC_CF_REG),
72 SILC_SERVER_CMD(silcoper, SILCOPER,
73 SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
74 SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
75 SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
76 SILC_SERVER_CMD(getkey, GETKEY, SILC_CF_LAG | SILC_CF_REG),
78 SILC_SERVER_CMD(connect, PRIV_CONNECT,
79 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
80 SILC_SERVER_CMD(close, PRIV_CLOSE,
81 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
82 SILC_SERVER_CMD(shutdown, PRIV_SHUTDOWN, SILC_CF_LAG | SILC_CF_REG |
88 /* Performs several checks to the command. It first checks whether this
89 command was called as pending command callback. If it was then it checks
90 whether error occurred in the command reply where the pending command
93 It also checks that the requested command includes correct amount
95 #define SILC_SERVER_COMMAND_CHECK(command, context, min, max) \
99 if (silc_server_command_pending_error_check(cmd, context2, command)) { \
100 SILC_LOG_DEBUG(("Error occurred in command reply, command not called")); \
101 silc_server_command_free(cmd); \
105 _argc = silc_argument_get_arg_num(cmd->args); \
107 SILC_LOG_DEBUG(("Not enough parameters in command")); \
108 silc_server_command_send_status_reply(cmd, command, \
109 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, \
111 silc_server_command_free(cmd); \
115 SILC_LOG_DEBUG(("Too many parameters in command")); \
116 silc_server_command_send_status_reply(cmd, command, \
117 SILC_STATUS_ERR_TOO_MANY_PARAMS, \
119 silc_server_command_free(cmd); \
124 /* Returns TRUE if the connection is registered. Unregistered connections
125 usually cannot send commands hence the check. */
127 static int silc_server_is_registered(SilcServer server,
128 SilcSocketConnection sock,
129 SilcServerCommandContext cmd,
132 SilcIDListData idata = (SilcIDListData)sock->user_data;
137 if (idata->status & SILC_IDLIST_STATUS_REGISTERED)
140 silc_server_command_send_status_reply(cmd, command,
141 SILC_STATUS_ERR_NOT_REGISTERED, 0);
145 /* Internal context to hold data when executed command with timeout. */
147 SilcServerCommandContext ctx;
148 SilcServerCommand *cmd;
149 } *SilcServerCommandTimeout;
151 /* Timeout callback to process commands with timeout for client. Client's
152 commands are always executed with timeout. */
154 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
156 SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
157 SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data;
160 SILC_LOG_DEBUG(("Client entry is invalid"));
161 silc_server_command_free(timeout->ctx);
165 /* Update access time */
166 client->last_command = time(NULL);
168 if (!(timeout->cmd->flags & SILC_CF_REG)) {
169 SILC_LOG_DEBUG(("Calling %s command",
170 silc_get_command_name(timeout->cmd->cmd)));
171 timeout->cmd->cb(timeout->ctx, NULL);
172 } else if (silc_server_is_registered(timeout->ctx->server,
175 timeout->cmd->cmd)) {
176 SILC_LOG_DEBUG(("Calling %s command",
177 silc_get_command_name(timeout->cmd->cmd)));
178 timeout->cmd->cb(timeout->ctx, NULL);
180 SILC_LOG_DEBUG(("Client is not registered"));
181 silc_server_command_free(timeout->ctx);
187 /* Processes received command packet. */
189 void silc_server_command_process(SilcServer server,
190 SilcSocketConnection sock,
191 SilcPacketContext *packet)
193 SilcServerCommandContext ctx;
194 SilcServerCommand *cmd;
197 /* Allocate command context. This must be free'd by the
198 command routine receiving it. */
199 ctx = silc_server_command_alloc();
200 ctx->server = server;
201 ctx->sock = silc_socket_dup(sock);
202 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
204 /* Parse the command payload in the packet */
205 ctx->payload = silc_command_payload_parse(packet->buffer->data,
206 packet->buffer->len);
208 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
209 silc_packet_context_free(packet);
210 silc_socket_free(ctx->sock);
214 ctx->args = silc_command_get_args(ctx->payload);
216 /* Get the command */
217 command = silc_command_get(ctx->payload);
218 for (cmd = silc_command_list; cmd->cb; cmd++)
219 if (cmd->cmd == command)
222 if (!cmd || !cmd->cb) {
223 SILC_LOG_DEBUG(("Unknown command %d", command));
224 silc_server_command_send_status_reply(ctx, command,
225 SILC_STATUS_ERR_UNKNOWN_COMMAND, 0);
226 silc_server_command_free(ctx);
230 /* Execute client's commands always with timeout. Normally they are
231 executed with zero (0) timeout but if client is sending command more
232 frequently than once in 2 seconds, then the timeout may be 0 to 2
234 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
235 SilcClientEntry client = (SilcClientEntry)sock->user_data;
236 SilcServerCommandTimeout timeout;
240 SILC_LOG_DEBUG(("Client entry is invalid"));
241 silc_server_command_free(ctx);
244 timeout = silc_calloc(1, sizeof(*timeout));
248 if (client->last_command && (time(NULL) - client->last_command) < 2) {
249 client->fast_command++;
252 if (client->fast_command - 2 <= 0)
253 client->fast_command = 0;
255 client->fast_command -= 2;
259 if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
260 (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
261 silc_schedule_task_add(server->schedule, sock->sock,
262 silc_server_command_process_timeout, timeout,
263 (client->fast_command < 3 ? 0 :
264 2 - (time(NULL) - client->last_command)),
265 (client->fast_command < 3 ? 200000 : 0),
266 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
268 silc_schedule_task_add(server->schedule, sock->sock,
269 silc_server_command_process_timeout, timeout,
270 0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
274 /* Execute for server */
276 if (!(cmd->flags & SILC_CF_REG)) {
277 SILC_LOG_DEBUG(("Calling %s command", silc_get_command_name(cmd->cmd)));
279 } else if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) {
280 SILC_LOG_DEBUG(("Calling %s command", silc_get_command_name(cmd->cmd)));
283 SILC_LOG_DEBUG(("Server is not registered"));
284 silc_server_command_free(ctx);
288 /* Allocate Command Context */
290 SilcServerCommandContext silc_server_command_alloc()
292 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
297 /* Free's the command context allocated before executing the command */
299 void silc_server_command_free(SilcServerCommandContext ctx)
302 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
304 if (ctx->users < 1) {
306 silc_command_payload_free(ctx->payload);
308 silc_packet_context_free(ctx->packet);
310 silc_socket_free(ctx->sock); /* Decrease reference counter */
315 /* Duplicate Command Context by adding reference counter. The context won't
316 be free'd untill it hits zero. */
318 SilcServerCommandContext
319 silc_server_command_dup(SilcServerCommandContext ctx)
322 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
327 /* Timeout for pending command. If reply to pending command never arrives
328 this is called to free resources. */
330 SILC_TASK_CALLBACK(silc_server_command_pending_timeout)
332 SilcServer server = app_context;
333 SilcServerCommandPending *reply = context;
334 SilcServerCommandReplyContext cmdr;
338 SILC_LOG_DEBUG(("Timeout pending command"));
340 /* Allocate temporary and bogus command reply context */
341 cmdr = silc_calloc(1, sizeof(*cmdr));
342 cmdr->server = server;
343 cmdr->ident = reply->ident;
345 /* Check for pending commands and mark to be exeucted */
347 silc_server_command_pending_check(server, reply->reply_cmd,
348 reply->ident, &cmdr->callbacks_count);
350 /* Create bogus command reply with an error inside */
352 silc_command_reply_payload_encode_va(reply->reply_cmd,
353 SILC_STATUS_ERR_TIMEDOUT, 0,
355 cmdr->payload = silc_command_payload_parse(tmpreply->data, tmpreply->len);
356 silc_buffer_free(tmpreply);
358 /* Call all callbacks. Same as SILC_SERVER_PENDING_EXEC macro. */
359 for (i = 0; i < cmdr->callbacks_count; i++)
360 if (cmdr->callbacks[i].callback)
361 (*cmdr->callbacks[i].callback)(cmdr->callbacks[i].context, cmdr);
363 silc_server_command_pending_del(server, reply->reply_cmd, reply->ident);
364 silc_server_command_reply_free(cmdr);
367 /* Add new pending command to be executed when reply to a command has been
368 received. The `reply_cmd' is the command that will call the `callback'
369 with `context' when reply has been received. It can be SILC_COMMAND_NONE
370 to match any command with the `ident'. If `ident' is non-zero
371 the `callback' will be executed when received reply with command
372 identifier `ident'. If there already exists pending command for the
373 specified command, ident, callback and context this function has no
376 bool silc_server_command_pending(SilcServer server,
377 SilcCommand reply_cmd,
379 SilcCommandCb callback,
382 return silc_server_command_pending_timed(server, reply_cmd, ident, callback,
386 /* Same as silc_server_command_pending with specific timeout for pending
387 commands. If the `timeout' is zero default timeout is used. */
389 bool silc_server_command_pending_timed(SilcServer server,
390 SilcCommand reply_cmd,
392 SilcCommandCb callback,
396 SilcServerCommandPending *reply;
398 /* Check whether identical pending already exists for same command,
399 ident, callback and callback context. If it does then it would be
400 error to register it again. */
401 silc_dlist_start(server->pending_commands);
402 while ((reply = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
403 if (reply->reply_cmd == reply_cmd && reply->ident == ident &&
404 reply->callback == callback && reply->context == context)
408 reply = silc_calloc(1, sizeof(*reply));
409 reply->reply_cmd = reply_cmd;
410 reply->ident = ident;
411 reply->context = context;
412 reply->callback = callback;
414 silc_schedule_task_add(server->schedule, 0,
415 silc_server_command_pending_timeout, reply,
416 timeout ? timeout : 10, 0,
417 SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
418 silc_dlist_add(server->pending_commands, reply);
423 /* Deletes pending command by reply command type. */
425 void silc_server_command_pending_del(SilcServer server,
426 SilcCommand reply_cmd,
429 SilcServerCommandPending *r;
431 silc_dlist_start(server->pending_commands);
432 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
433 if ((r->reply_cmd == reply_cmd || (r->reply_cmd == SILC_COMMAND_NONE &&
435 && r->ident == ident) {
436 silc_dlist_del(server->pending_commands, r);
438 silc_schedule_task_del(server->schedule, r->timeout);
444 /* Checks for pending commands and marks callbacks to be called from
445 the command reply function. Returns TRUE if there were pending command. */
447 SilcServerCommandPendingCallbacks
448 silc_server_command_pending_check(SilcServer server,
451 SilcUInt32 *callbacks_count)
453 SilcServerCommandPending *r;
454 SilcServerCommandPendingCallbacks callbacks = NULL;
457 silc_dlist_start(server->pending_commands);
458 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
459 if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE)
460 && r->ident == ident) {
461 callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
462 callbacks[i].context = r->context;
463 callbacks[i].callback = r->callback;
464 r->reply_check = TRUE;
469 *callbacks_count = i;
473 /* Sends simple status message as command reply packet */
476 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
483 SILC_LOG_DEBUG(("Sending command status %d", status));
486 silc_command_reply_payload_encode_va(command, status, error,
487 silc_command_get_ident(cmd->payload),
489 silc_server_packet_send(cmd->server, cmd->sock,
490 SILC_PACKET_COMMAND_REPLY, 0,
491 buffer->data, buffer->len, FALSE);
492 silc_buffer_free(buffer);
495 /* Sends command status reply with one extra argument. The argument
496 type must be sent as argument. */
499 silc_server_command_send_status_data(SilcServerCommandContext cmd,
504 const unsigned char *arg,
509 SILC_LOG_DEBUG(("Sending command status %d", status));
512 silc_command_reply_payload_encode_va(command, status, 0,
513 silc_command_get_ident(cmd->payload),
514 1, arg_type, arg, arg_len);
515 silc_server_packet_send(cmd->server, cmd->sock,
516 SILC_PACKET_COMMAND_REPLY, 0,
517 buffer->data, buffer->len, FALSE);
518 silc_buffer_free(buffer);
521 /* This function can be called to check whether in the command reply
522 an error occurred. This function has no effect if this is called
523 when the command function was not called as pending command callback.
524 This returns TRUE if error had occurred. */
527 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
528 SilcServerCommandReplyContext cmdr,
531 if (!cmd->pending || !cmdr)
534 if (!silc_command_get_status(cmdr->payload, NULL, NULL)) {
537 /* Send the same command reply payload */
538 silc_command_set_command(cmdr->payload, silc_command_get(cmd->payload));
539 silc_command_set_ident(cmdr->payload,
540 silc_command_get_ident(cmd->payload));
541 buffer = silc_command_payload_encode_payload(cmdr->payload);
542 silc_server_packet_send(cmd->server, cmd->sock,
543 SILC_PACKET_COMMAND_REPLY, 0,
544 buffer->data, buffer->len, FALSE);
545 silc_buffer_free(buffer);
552 /******************************************************************************
556 ******************************************************************************/
565 #define ADD_ERROR(errptr, errptr_count, _id, _id_type, _index, _status) \
567 errptr = silc_realloc(errptr, sizeof(*errptr) * (errptr_count + 1)); \
570 errptr[errptr_count].id = _id; \
571 errptr[errptr_count].id_type = _id_type; \
572 errptr[errptr_count].index = _index; \
573 errptr[errptr_count].error = _status; \
578 silc_server_command_whois_parse(SilcServerCommandContext cmd,
579 SilcClientID ***client_id,
580 SilcUInt32 *client_id_count,
584 ResolveError *error_client,
585 SilcUInt32 *error_client_count,
590 SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
594 /* If client ID is in the command it must be used instead of nickname */
595 tmp = silc_argument_get_arg_type(cmd->args, 4, &len);
597 /* No ID, get the nickname@server string and parse it. */
598 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
600 silc_parse_userfqdn(tmp, nickname, server_name);
602 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
603 SILC_STATUS_ERR_BAD_NICKNAME, 0);
607 /* Command includes ID, we must use that. Take all ID's from the
609 for (k = 0, i = 0; i < argc; i++) {
610 tmp = silc_argument_get_arg_type(cmd->args, i + 4, &len);
613 id = silc_id_payload_parse_id(tmp, len, NULL);
615 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
616 (*client_id_count + 1));
617 (*client_id)[k] = id;
618 (*client_id_count)++;
621 ADD_ERROR((*error_client), (*error_client_count), NULL, 0, i + 4,
622 SILC_STATUS_ERR_BAD_CLIENT_ID);
627 /* Get the max count of reply messages allowed */
628 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
630 SILC_GET32_MSB(*count, tmp);
634 /* Get requested attributes if set */
635 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
637 *attrs = silc_attribute_payload_parse_list(tmp, len);
642 /* Resolve context used by both WHOIS and IDENTIFY commands */
644 SilcSocketConnection sock;
646 unsigned char **res_argv;
647 SilcUInt32 *res_argv_lens;
648 SilcUInt32 *res_argv_types;
650 SilcUInt32 res_timeout;
651 } *SilcServerResolveContext;
654 silc_server_command_whois_check(SilcServerCommandContext cmd,
655 SilcClientEntry *clients,
656 SilcUInt32 clients_count,
659 SilcServer server = cmd->server;
660 SilcClientEntry entry;
661 SilcServerResolveContext resolve = NULL, r = NULL;
662 SilcUInt32 resolve_count = 0;
666 SILC_LOG_DEBUG(("Start"));
668 for (i = 0; i < clients_count; i++) {
673 /* If requested attributes is set then we always resolve the client
674 information, if not then check whether the entry is complete or not
675 and decide whether we need to resolve or not. Usually attributes
676 are not present so the this test is performed all the time. */
678 if ((entry->nickname && entry->username && entry->userinfo) ||
679 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
683 /* If we are normal server, and we've not resolved this client from
684 router and it is global client, we'll check whether it is on some
685 channel. If not then we cannot be sure about its validity, and
686 we'll resolve it from router. */
687 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
688 entry->connection || silc_hash_table_count(entry->channels))
693 /* When requested attributes is present and local client is detached
694 we cannot send the command to the client, we'll reply on behalf of
695 the client instead. */
696 if (attrs && SILC_IS_LOCAL(entry) && entry->mode & SILC_UMODE_DETACHED)
699 /* We need to resolve this entry since it is not complete */
701 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
702 /* The entry is being resolved (and we are not the resolver) so attach
703 to the command reply and we're done with this one. */
704 silc_server_command_pending(server, SILC_COMMAND_NONE,
705 entry->resolve_cmd_ident,
706 silc_server_command_whois,
707 silc_server_command_dup(cmd));
711 SilcSocketConnection sock;
713 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
714 /* We've resolved this and it still is not ready. We'll return
715 and are that this will be handled again after it is resolved. */
716 for (i = 0; i < resolve_count; i++) {
717 for (k = 0; k < r->res_argc; k++)
718 silc_free(r->res_argv[k]);
719 silc_free(r->res_argv);
720 silc_free(r->res_argv_lens);
721 silc_free(r->res_argv_types);
727 /* We'll resolve this client now */
729 sock = (SILC_IS_LOCAL(entry) ? entry->connection :
730 entry->router->connection);
735 for (k = 0; k < resolve_count; k++) {
736 if (resolve[k].sock == sock) {
743 resolve = silc_realloc(resolve, sizeof(*resolve) *
744 (resolve_count + 1));
745 r = &resolve[resolve_count];
746 memset(r, 0, sizeof(*r));
748 r->ident = ++server->cmd_ident;
749 if (SILC_IS_LOCAL(entry))
756 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
758 r->res_argv_lens = silc_realloc(r->res_argv_lens,
759 sizeof(*r->res_argv_lens) *
761 r->res_argv_types = silc_realloc(r->res_argv_types,
762 sizeof(*r->res_argv_types) *
764 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
765 r->res_argv[r->res_argc] = silc_calloc(idp->len,
766 sizeof(**r->res_argv));
767 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
768 r->res_argv_lens[r->res_argc] = idp->len;
769 r->res_argv_types[r->res_argc] = r->res_argc + 4;
771 silc_buffer_free(idp);
773 entry->resolve_cmd_ident = r->ident;
774 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
775 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
779 /* Do the resolving */
780 for (i = 0; i < resolve_count; i++) {
782 unsigned char *attrs_buf;
783 SilcUInt32 attrs_buf_len;
787 /* If attributes were present put them to this resolving as well */
789 attrs_buf = silc_argument_get_arg_type(cmd->args, 3, &attrs_buf_len);
791 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
793 r->res_argv_lens = silc_realloc(r->res_argv_lens,
794 sizeof(*r->res_argv_lens) *
796 r->res_argv_types = silc_realloc(r->res_argv_types,
797 sizeof(*r->res_argv_types) *
799 r->res_argv[r->res_argc] = silc_memdup(attrs_buf, attrs_buf_len);
800 r->res_argv_lens[r->res_argc] = attrs_buf_len;
801 r->res_argv_types[r->res_argc] = 3;
806 /* Send WHOIS command */
807 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
808 r->res_argc, r->res_argv,
812 silc_server_packet_send(server, r->sock, SILC_PACKET_COMMAND,
813 cmd->packet->flags, res_cmd->data,
814 res_cmd->len, FALSE);
816 /* Reprocess this packet after received reply */
817 silc_server_command_pending_timed(server, SILC_COMMAND_WHOIS, r->ident,
818 silc_server_command_whois,
819 silc_server_command_dup(cmd),
823 silc_buffer_free(res_cmd);
824 for (k = 0; k < r->res_argc; k++)
825 silc_free(r->res_argv[k]);
826 silc_free(r->res_argv);
827 silc_free(r->res_argv_lens);
828 silc_free(r->res_argv_types);
837 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
838 SilcClientEntry *clients,
839 SilcUInt32 clients_count,
841 SilcUInt32 errors_count,
842 int count, const char *nickname,
843 SilcClientID **client_ids)
845 SilcServer server = cmd->server;
847 int i, k, valid_count = clients_count;
849 SilcBuffer packet, idp, channels, umode_list = NULL;
850 SilcClientEntry entry;
852 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
853 char nh[256], uh[256];
854 unsigned char idle[4], mode[4];
855 unsigned char *fingerprint, fempty[20];
856 SilcSocketConnection hsock;
859 /* Process only valid clients and ignore those that are not registered.
860 This is checked with nickname only because when resolved client IDs
861 we check that they are registered earlier. */
863 for (i = 0; i < clients_count; i++)
864 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
870 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
871 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
872 3, nickname, strlen(nickname));
877 memset(fempty, 0, sizeof(fempty));
879 /* Start processing found clients. */
880 status = SILC_STATUS_OK;
882 status = SILC_STATUS_LIST_START;
884 for (i = 0, k = 0; i < clients_count; i++) {
890 status = SILC_STATUS_LIST_ITEM;
891 if (valid_count > 1 && k == valid_count - 1 && !errors_count)
892 status = SILC_STATUS_LIST_END;
893 if (count && k - 1 == count)
894 status = SILC_STATUS_LIST_END;
896 /* Send WHOIS reply */
897 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
898 tmp = silc_argument_get_first_arg(cmd->args, NULL);
900 memset(uh, 0, sizeof(uh));
901 memset(nh, 0, sizeof(nh));
902 memset(idle, 0, sizeof(idle));
904 strncat(nh, entry->nickname, strlen(entry->nickname));
905 if (!strchr(entry->nickname, '@')) {
907 if (entry->servername) {
908 strncat(nh, entry->servername, strlen(entry->servername));
910 len = entry->router ? strlen(entry->router->server_name) :
911 strlen(server->server_name);
912 strncat(nh, entry->router ? entry->router->server_name :
913 server->server_name, len);
917 strncat(uh, entry->username, strlen(entry->username));
918 if (!strchr(entry->username, '@') && entry->connection) {
920 hsock = (SilcSocketConnection)entry->connection;
921 len = strlen(hsock->hostname);
922 strncat(uh, hsock->hostname, len);
925 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
926 channels = silc_server_get_client_channel_list(server, entry, FALSE,
929 channels = silc_server_get_client_channel_list(server, entry, TRUE,
932 if (memcmp(entry->data.fingerprint, fempty, sizeof(fempty)))
933 fingerprint = entry->data.fingerprint;
937 SILC_PUT32_MSB(entry->mode, mode);
938 if (entry->connection)
939 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
942 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
944 2, idp->data, idp->len,
948 strlen(entry->userinfo),
949 6, channels ? channels->data : NULL,
950 channels ? channels->len : 0,
954 fingerprint ? 20 : 0,
955 10, umode_list ? umode_list->data :
956 NULL, umode_list ? umode_list->len :
959 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
960 0, packet->data, packet->len, FALSE);
962 silc_buffer_free(packet);
963 silc_buffer_free(idp);
965 silc_buffer_free(channels);
967 silc_buffer_free(umode_list);
971 if (status == SILC_STATUS_LIST_END)
976 /* Send error replies */
977 if (status == SILC_STATUS_OK && errors_count > 1)
978 status = SILC_STATUS_LIST_START;
981 for (i = 0, k = 0; i < errors_count; i++) {
983 idp = silc_id_payload_encode(errors[i].id, SILC_ID_CLIENT);
987 tmp = silc_argument_get_arg_type(cmd->args, errors[i].index, &len);
991 status = SILC_STATUS_LIST_ITEM;
992 if (errors_count > 1 && k == errors_count - 1)
993 status = SILC_STATUS_LIST_END;
994 if (count && k - 1 == count)
995 status = SILC_STATUS_LIST_END;
998 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
999 (status == SILC_STATUS_OK ?
1000 errors[i].error : status),
1001 (status == SILC_STATUS_OK ?
1002 0 : errors[i].error),
1004 silc_buffer_free(idp);
1007 if (status == SILC_STATUS_LIST_END)
1014 silc_server_command_whois_send_router(SilcServerCommandContext cmd)
1016 SilcServer server = cmd->server;
1018 SilcUInt16 old_ident;
1020 old_ident = silc_command_get_ident(cmd->payload);
1021 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1022 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1024 /* Send WHOIS command to our router */
1025 silc_server_packet_send(server, (SilcSocketConnection)
1026 SILC_PRIMARY_ROUTE(server),
1027 SILC_PACKET_COMMAND, cmd->packet->flags,
1028 tmpbuf->data, tmpbuf->len, TRUE);
1030 /* Reprocess this packet after received reply from router */
1031 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1032 silc_command_get_ident(cmd->payload),
1033 silc_server_command_whois,
1034 silc_server_command_dup(cmd));
1035 cmd->pending = TRUE;
1036 silc_command_set_ident(cmd->payload, old_ident);
1037 silc_buffer_free(tmpbuf);
1041 silc_server_command_whois_process(SilcServerCommandContext cmd)
1043 SilcServer server = cmd->server;
1044 char *nick = NULL, *server_name = NULL;
1046 SilcClientEntry *clients = NULL, entry;
1047 SilcClientID **client_id = NULL;
1048 SilcUInt32 client_id_count = 0, clients_count = 0, error_client_count = 0;
1049 ResolveError error_client = NULL;
1050 SilcDList attrs = NULL;
1052 bool check_global = FALSE;
1054 /* Parse the whois request */
1055 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1056 &nick, &server_name, &count,
1057 &error_client, &error_client_count,
1061 /* Send the WHOIS request to the router only if it included nickname.
1062 Since nicknames can be expanded into many clients we need to send it
1063 to router. If the WHOIS included only client ID's we will check them
1064 first locally since we just might have them. */
1065 if (nick && !client_id_count && cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1066 server->server_type == SILC_SERVER && !cmd->pending &&
1067 !server->standalone) {
1068 silc_server_command_whois_send_router(cmd);
1073 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1074 check_global = TRUE;
1075 else if (server->server_type != SILC_SERVER)
1076 check_global = TRUE;
1078 /* Get all clients matching that ID or nickname from local list */
1079 if (client_id_count) {
1080 /* Check all Client ID's received in the command packet */
1081 for (i = 0; i < client_id_count; i++) {
1082 entry = silc_idlist_find_client_by_id(server->local_list,
1083 client_id[i], TRUE, NULL);
1084 if (!entry && check_global)
1085 entry = silc_idlist_find_client_by_id(server->global_list,
1086 client_id[i], TRUE, NULL);
1088 clients = silc_realloc(clients, sizeof(*clients) *
1089 (clients_count + 1));
1090 clients[clients_count++] = entry;
1092 /* If we are normal server and did not send the request first to router
1093 do it now, since we do not have the Client ID information. */
1094 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1095 server->server_type == SILC_SERVER && !cmd->pending &&
1096 !server->standalone) {
1097 silc_server_command_whois_send_router(cmd);
1102 ADD_ERROR(error_client, error_client_count, client_id[i],
1103 SILC_ID_CLIENT, 0, SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
1107 /* Find by nickname */
1108 if (!silc_idlist_get_clients_by_hash(server->local_list,
1109 nick, server->md5hash,
1110 &clients, &clients_count))
1111 silc_idlist_get_clients_by_nickname(server->local_list,
1113 &clients, &clients_count);
1115 if (!silc_idlist_get_clients_by_hash(server->global_list,
1116 nick, server->md5hash,
1117 &clients, &clients_count))
1118 silc_idlist_get_clients_by_nickname(server->global_list,
1120 &clients, &clients_count);
1124 if (!clients && (client_id_count || nick)) {
1125 /* If we are normal server and did not send the request first to router
1126 do it now, since we do not have the information. */
1127 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1128 server->server_type == SILC_SERVER && !cmd->pending &&
1129 !server->standalone) {
1130 silc_server_command_whois_send_router(cmd);
1135 /* Such client(s) really does not exist in the SILC network. */
1136 if (!client_id_count)
1137 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
1138 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1139 3, nick, strlen(nick));
1141 silc_server_command_whois_send_reply(cmd, NULL, 0,
1142 error_client, error_client_count,
1147 /* Router always finds the client entry if it exists in the SILC network.
1148 However, it might be incomplete entry and does not include all the
1149 mandatory fields that WHOIS command reply requires. Check for these and
1150 make query from the server who owns the client if some fields are
1152 if (!silc_server_command_whois_check(cmd, clients, clients_count, attrs)) {
1157 /* Send the command reply */
1158 silc_server_command_whois_send_reply(cmd, clients, clients_count,
1159 error_client, error_client_count,
1160 count, nick, client_id);
1163 if (client_id_count) {
1164 for (i = 0; i < client_id_count; i++)
1165 silc_free(client_id[i]);
1166 silc_free(client_id);
1169 silc_free(error_client);
1171 silc_free(server_name);
1173 silc_attribute_payload_list_free(attrs);
1178 /* Server side of command WHOIS. Processes user's query and sends found
1179 results as command replies back to the client. */
1181 SILC_SERVER_CMD_FUNC(whois)
1183 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1185 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 256);
1187 silc_server_command_whois_process(cmd);
1188 silc_server_command_free(cmd);
1191 /******************************************************************************
1195 ******************************************************************************/
1198 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
1206 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1208 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
1209 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1214 /* Get the nickname@server string and parse it. */
1215 silc_parse_userfqdn(tmp, nickname, server_name);
1217 /* Get the max count of reply messages allowed */
1218 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1220 SILC_GET32_MSB(*count, tmp);
1228 silc_server_command_whowas_check(SilcServerCommandContext cmd,
1229 SilcClientEntry *clients,
1230 SilcUInt32 clients_count)
1232 SilcServer server = cmd->server;
1234 SilcClientEntry entry;
1236 for (i = 0; i < clients_count; i++) {
1239 if (!entry->nickname || !entry->username) {
1241 SilcUInt16 old_ident;
1246 old_ident = silc_command_get_ident(cmd->payload);
1247 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1248 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1250 /* Send WHOWAS command */
1251 silc_server_packet_send(server, entry->router->connection,
1252 SILC_PACKET_COMMAND, cmd->packet->flags,
1253 tmpbuf->data, tmpbuf->len, TRUE);
1255 /* Reprocess this packet after received reply */
1256 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1257 silc_command_get_ident(cmd->payload),
1258 silc_server_command_whowas,
1259 silc_server_command_dup(cmd));
1260 cmd->pending = TRUE;
1261 silc_command_set_ident(cmd->payload, old_ident);
1263 silc_buffer_free(tmpbuf);
1272 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1273 SilcClientEntry *clients,
1274 SilcUInt32 clients_count)
1276 SilcServer server = cmd->server;
1278 int i, k, count = 0, len;
1279 SilcBuffer packet, idp;
1280 SilcClientEntry entry = NULL;
1282 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1283 char nh[256], uh[256];
1286 status = SILC_STATUS_OK;
1288 /* Process only entries that are not registered anymore. */
1290 for (i = 0; i < clients_count; i++) {
1291 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1298 /* No valid entries found at all, just send error */
1299 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1300 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1301 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1302 3, tmp, tmp ? strlen(tmp) : 0);
1306 if (valid_count > 1)
1307 status = SILC_STATUS_LIST_START;
1309 for (i = 0, k = 0; i < clients_count; i++) {
1315 status = SILC_STATUS_LIST_ITEM;
1316 if (valid_count > 1 && k == valid_count - 1)
1317 status = SILC_STATUS_LIST_END;
1318 if (count && k - 1 == count)
1319 status = SILC_STATUS_LIST_END;
1321 /* Send WHOWAS reply */
1322 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1323 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1324 memset(uh, 0, sizeof(uh));
1325 memset(nh, 0, sizeof(nh));
1327 strncat(nh, entry->nickname, strlen(entry->nickname));
1328 if (!strchr(entry->nickname, '@')) {
1329 strncat(nh, "@", 1);
1330 if (entry->servername) {
1331 strncat(nh, entry->servername, strlen(entry->servername));
1333 len = entry->router ? strlen(entry->router->server_name) :
1334 strlen(server->server_name);
1335 strncat(nh, entry->router ? entry->router->server_name :
1336 server->server_name, len);
1340 strncat(uh, entry->username, strlen(entry->username));
1341 if (!strchr(entry->username, '@')) {
1342 strncat(uh, "@", 1);
1343 strcat(uh, "*private*");
1347 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1348 status, 0, ident, 4,
1349 2, idp->data, idp->len,
1354 strlen(entry->userinfo) : 0);
1355 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1356 0, packet->data, packet->len, FALSE);
1358 silc_buffer_free(packet);
1359 silc_buffer_free(idp);
1361 if (status == SILC_STATUS_LIST_END)
1368 silc_server_command_whowas_process(SilcServerCommandContext cmd)
1370 SilcServer server = cmd->server;
1371 char *nick = NULL, *server_name = NULL;
1373 SilcClientEntry *clients = NULL;
1374 SilcUInt32 clients_count = 0;
1376 bool check_global = FALSE;
1378 /* Protocol dictates that we must always send the received WHOWAS request
1379 to our router if we are normal server, so let's do it now unless we
1380 are standalone. We will not send any replies to the client until we
1381 have received reply from the router. */
1382 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1383 server->server_type == SILC_SERVER && !cmd->pending &&
1384 !server->standalone) {
1386 SilcUInt16 old_ident;
1388 old_ident = silc_command_get_ident(cmd->payload);
1389 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1390 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1392 /* Send WHOWAS command to our router */
1393 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
1394 SILC_PACKET_COMMAND, cmd->packet->flags,
1395 tmpbuf->data, tmpbuf->len, TRUE);
1397 /* Reprocess this packet after received reply from router */
1398 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1399 silc_command_get_ident(cmd->payload),
1400 silc_server_command_whowas,
1401 silc_server_command_dup(cmd));
1402 cmd->pending = TRUE;
1403 silc_command_set_ident(cmd->payload, old_ident);
1405 silc_buffer_free(tmpbuf);
1410 /* We are ready to process the command request. Let's search for the
1411 requested client and send reply to the requesting client. */
1413 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1414 check_global = TRUE;
1415 else if (server->server_type != SILC_SERVER)
1416 check_global = TRUE;
1418 /* Parse the whowas request */
1419 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1422 /* Get all clients matching that nickname from local list */
1423 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1425 &clients, &clients_count))
1426 silc_idlist_get_clients_by_hash(server->local_list,
1427 nick, server->md5hash,
1428 &clients, &clients_count);
1430 /* Check global list as well */
1432 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1434 &clients, &clients_count))
1435 silc_idlist_get_clients_by_hash(server->global_list,
1436 nick, server->md5hash,
1437 &clients, &clients_count);
1441 /* Such a client really does not exist in the SILC network. */
1442 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1443 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1444 3, nick, strlen(nick));
1448 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1453 /* Send the command reply to the client */
1454 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1459 silc_free(server_name);
1463 /* Server side of command WHOWAS. */
1465 SILC_SERVER_CMD_FUNC(whowas)
1467 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1470 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1472 ret = silc_server_command_whowas_process(cmd);
1473 silc_server_command_free(cmd);
1476 /******************************************************************************
1480 ******************************************************************************/
1483 silc_server_command_identify_send_router(SilcServerCommandContext cmd)
1485 SilcServer server = cmd->server;
1487 SilcUInt16 old_ident;
1489 old_ident = silc_command_get_ident(cmd->payload);
1490 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1491 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1493 /* Send IDENTIFY command to our router */
1494 silc_server_packet_send(server, (SilcSocketConnection)
1495 SILC_PRIMARY_ROUTE(server),
1496 SILC_PACKET_COMMAND, cmd->packet->flags,
1497 tmpbuf->data, tmpbuf->len, TRUE);
1499 /* Reprocess this packet after received reply from router */
1500 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1501 silc_command_get_ident(cmd->payload),
1502 silc_server_command_identify,
1503 silc_server_command_dup(cmd));
1504 cmd->pending = TRUE;
1505 silc_command_set_ident(cmd->payload, old_ident);
1506 silc_buffer_free(tmpbuf);
1510 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1511 SilcClientEntry **clients,
1512 SilcUInt32 *clients_count,
1513 SilcServerEntry **servers,
1514 SilcUInt32 *servers_count,
1515 SilcChannelEntry **channels,
1516 SilcUInt32 *channels_count,
1518 ResolveError *error_id,
1519 SilcUInt32 *error_id_count)
1521 SilcServer server = cmd->server;
1524 SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
1526 bool check_global = FALSE;
1530 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1531 check_global = TRUE;
1532 else if (server->server_type != SILC_SERVER)
1533 check_global = TRUE;
1535 /* If ID Payload is in the command it must be used instead of names */
1536 tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1538 /* No ID, get the names. */
1540 /* If we are normal server and have not resolved information from
1541 router yet, do so now. */
1542 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1543 server->server_type == SILC_SERVER && !cmd->pending &&
1544 !server->standalone) {
1545 silc_server_command_identify_send_router(cmd);
1549 /* Try to get nickname@server. */
1550 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1553 char *nick_server = NULL;
1555 silc_parse_userfqdn(tmp, &nick, &nick_server);
1557 if (!silc_idlist_get_clients_by_hash(server->local_list,
1558 nick, server->md5hash,
1559 clients, clients_count))
1560 silc_idlist_get_clients_by_nickname(server->local_list,
1562 clients, clients_count);
1564 if (!silc_idlist_get_clients_by_hash(server->global_list,
1565 nick, server->md5hash,
1566 clients, clients_count))
1567 silc_idlist_get_clients_by_nickname(server->global_list,
1569 clients, clients_count);
1573 silc_free(nick_server);
1576 /* the nickname does not exist, send error reply */
1577 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1578 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1579 3, tmp, strlen(tmp));
1584 /* Try to get server name */
1585 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1587 entry = silc_idlist_find_server_by_name(server->local_list,
1589 if (!entry && check_global)
1590 entry = silc_idlist_find_server_by_name(server->global_list,
1593 *servers = silc_realloc(*servers, sizeof(**servers) *
1594 (*servers_count + 1));
1595 (*servers)[(*servers_count)++] = entry;
1599 /* the server does not exist, send error reply */
1600 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1601 SILC_STATUS_ERR_NO_SUCH_SERVER,
1602 0, 3, tmp, strlen(tmp));
1607 /* Try to get channel name */
1608 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1610 entry = silc_idlist_find_channel_by_name(server->local_list,
1612 if (!entry && check_global)
1613 entry = silc_idlist_find_channel_by_name(server->global_list,
1616 *channels = silc_realloc(*channels, sizeof(**channels) *
1617 (*channels_count + 1));
1618 (*channels)[(*channels_count)++] = entry;
1622 /* The channel does not exist, send error reply */
1623 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1624 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1625 0, 3, tmp, strlen(tmp));
1630 if (!(*clients) && !(*servers) && !(*channels)) {
1631 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1632 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1637 /* Command includes ID, we must use that. Also check whether the command
1638 has more than one ID set - take them all. */
1640 /* Take all ID's from the command packet */
1641 for (i = 0; i < argc; i++) {
1644 tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
1648 idp = silc_id_payload_parse(tmp, len);
1650 ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1651 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1653 id = silc_id_payload_get_id(idp);
1654 switch (silc_id_payload_get_type(idp)) {
1656 case SILC_ID_CLIENT:
1657 entry = silc_idlist_find_client_by_id(server->local_list,
1659 if (!entry && check_global)
1660 entry = silc_idlist_find_client_by_id(server->global_list,
1663 *clients = silc_realloc(*clients, sizeof(**clients) *
1664 (*clients_count + 1));
1665 (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
1667 /* If we are normal server and have not resolved information from
1668 router yet, do so now. */
1669 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1670 server->server_type == SILC_SERVER && !cmd->pending &&
1671 !server->standalone) {
1672 silc_server_command_identify_send_router(cmd);
1673 silc_free(*clients);
1674 silc_free(*servers);
1675 silc_free(*channels);
1676 silc_free(*error_id);
1680 ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1681 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
1686 case SILC_ID_SERVER:
1687 entry = silc_idlist_find_server_by_id(server->local_list,
1689 if (!entry && check_global)
1690 entry = silc_idlist_find_server_by_id(server->global_list,
1693 *servers = silc_realloc(*servers, sizeof(**servers) *
1694 (*servers_count + 1));
1695 (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
1697 /* If we are normal server and have not resolved information from
1698 router yet, do so now. */
1699 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1700 server->server_type == SILC_SERVER && !cmd->pending &&
1701 !server->standalone) {
1702 silc_server_command_identify_send_router(cmd);
1703 silc_free(*clients);
1704 silc_free(*servers);
1705 silc_free(*channels);
1706 silc_free(*error_id);
1710 ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1711 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
1715 case SILC_ID_CHANNEL:
1716 entry = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
1717 if (!entry && check_global)
1718 entry = silc_idlist_find_channel_by_id(server->global_list, id,
1721 *channels = silc_realloc(*channels, sizeof(**channels) *
1722 (*channels_count + 1));
1723 (*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
1725 /* If we are normal server and have not resolved information from
1726 router yet, do so now. */
1727 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1728 server->server_type == SILC_SERVER && !cmd->pending &&
1729 !server->standalone) {
1730 silc_server_command_identify_send_router(cmd);
1731 silc_free(*clients);
1732 silc_free(*servers);
1733 silc_free(*channels);
1734 silc_free(*error_id);
1738 ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1739 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID);
1744 silc_id_payload_free(idp);
1749 /* Get the max count of reply messages allowed */
1750 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1752 SILC_GET32_MSB(*count, tmp);
1759 /* Checks that all mandatory fields in client entry are present. If not
1760 then send WHOIS request to the server who owns the client. We use
1761 WHOIS because we want to get as much information as possible at once. */
1764 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1765 SilcClientEntry *clients,
1766 SilcUInt32 clients_count)
1768 SilcServer server = cmd->server;
1769 SilcClientEntry entry;
1770 SilcServerResolveContext resolve = NULL, r = NULL;
1771 SilcUInt32 resolve_count = 0;
1775 for (i = 0; i < clients_count; i++) {
1780 if (entry->nickname ||
1781 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1785 /* If we are normal server, and we've not resolved this client from
1786 router and it is global client, we'll check whether it is on some
1787 channel. If not then we cannot be sure about its validity, and
1788 we'll resolve it from router. */
1789 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
1790 entry->connection || silc_hash_table_count(entry->channels))
1794 /* We need to resolve this entry since it is not complete */
1796 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1797 /* The entry is being resolved (and we are not the resolver) so attach
1798 to the command reply and we're done with this one. */
1799 silc_server_command_pending(server, SILC_COMMAND_NONE,
1800 entry->resolve_cmd_ident,
1801 silc_server_command_identify,
1802 silc_server_command_dup(cmd));
1805 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1806 /* We've resolved this and it still is not ready. We'll return
1807 and are that this will be handled again after it is resolved. */
1808 for (i = 0; i < resolve_count; i++) {
1809 for (k = 0; k < r->res_argc; k++)
1810 silc_free(r->res_argv[k]);
1811 silc_free(r->res_argv);
1812 silc_free(r->res_argv_lens);
1813 silc_free(r->res_argv_types);
1818 /* We'll resolve this client */
1822 for (k = 0; k < resolve_count; k++) {
1823 if (resolve[k].sock == entry->router->connection) {
1830 resolve = silc_realloc(resolve, sizeof(*resolve) *
1831 (resolve_count + 1));
1832 r = &resolve[resolve_count];
1833 memset(r, 0, sizeof(*r));
1834 r->sock = entry->router->connection;
1835 r->ident = ++server->cmd_ident;
1839 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1841 r->res_argv_lens = silc_realloc(r->res_argv_lens,
1842 sizeof(*r->res_argv_lens) *
1844 r->res_argv_types = silc_realloc(r->res_argv_types,
1845 sizeof(*r->res_argv_types) *
1847 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1848 r->res_argv[r->res_argc] = silc_calloc(idp->len,
1849 sizeof(**r->res_argv));
1850 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1851 r->res_argv_lens[r->res_argc] = idp->len;
1852 r->res_argv_types[r->res_argc] = r->res_argc + 4;
1854 silc_buffer_free(idp);
1856 entry->resolve_cmd_ident = r->ident;
1857 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1858 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1863 /* Do the resolving */
1864 for (i = 0; i < resolve_count; i++) {
1869 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1870 now anyway so make it a good one. */
1871 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1872 r->res_argc, r->res_argv,
1876 silc_server_packet_send(server, r->sock, SILC_PACKET_COMMAND,
1877 cmd->packet->flags, res_cmd->data,
1878 res_cmd->len, FALSE);
1880 /* Reprocess this packet after received reply */
1881 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1883 silc_server_command_identify,
1884 silc_server_command_dup(cmd));
1885 cmd->pending = TRUE;
1887 silc_buffer_free(res_cmd);
1888 for (k = 0; k < r->res_argc; k++)
1889 silc_free(r->res_argv[k]);
1890 silc_free(r->res_argv);
1891 silc_free(r->res_argv_lens);
1892 silc_free(r->res_argv_types);
1901 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1902 SilcClientEntry *clients,
1903 SilcUInt32 clients_count,
1904 SilcServerEntry *servers,
1905 SilcUInt32 servers_count,
1906 SilcChannelEntry *channels,
1907 SilcUInt32 channels_count,
1908 ResolveError errors,
1909 SilcUInt32 errors_count,
1912 SilcServer server = cmd->server;
1913 int i, k, valid_count;
1915 SilcBuffer packet, idp;
1917 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1918 char nh[256], uh[256];
1919 SilcSocketConnection hsock;
1922 status = SILC_STATUS_OK;
1925 SilcClientEntry entry;
1926 valid_count = clients_count;
1928 if (silc_argument_get_arg_type(cmd->args, 1, NULL)) {
1929 /* Process only valid clients and ignore those that are not registered.
1930 This is checked with nickname only because when resolved client IDs
1931 we check that they are registered earlier. */
1933 for (i = 0; i < clients_count; i++) {
1934 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1941 /* No valid entries found at all, just send error */
1942 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1943 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1944 SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1945 3, tmp, tmp ? strlen(tmp) : 0);
1950 /* Process all valid client entries and send command replies */
1952 if (valid_count > 1)
1953 status = SILC_STATUS_LIST_START;
1955 for (i = 0, k = 0; i < clients_count; i++) {
1961 status = SILC_STATUS_LIST_ITEM;
1962 if (valid_count > 1 && k == valid_count - 1
1963 && !servers_count && !channels_count && !errors_count)
1964 status = SILC_STATUS_LIST_END;
1965 if (count && k - 1 == count)
1966 status = SILC_STATUS_LIST_END;
1968 /* Send IDENTIFY reply */
1970 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1971 memset(uh, 0, sizeof(uh));
1972 memset(nh, 0, sizeof(nh));
1973 strncat(nh, entry->nickname, strlen(entry->nickname));
1974 if (!strchr(entry->nickname, '@')) {
1975 strncat(nh, "@", 1);
1976 if (entry->servername) {
1977 strncat(nh, entry->servername, strlen(entry->servername));
1979 len = entry->router ? strlen(entry->router->server_name) :
1980 strlen(server->server_name);
1981 strncat(nh, entry->router ? entry->router->server_name :
1982 server->server_name, len);
1986 if (!entry->username) {
1987 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1988 status, 0, ident, 2,
1989 2, idp->data, idp->len,
1992 strncat(uh, entry->username, strlen(entry->username));
1993 if (!strchr(entry->username, '@') && entry->connection) {
1994 strncat(uh, "@", 1);
1995 hsock = (SilcSocketConnection)entry->connection;
1996 len = strlen(hsock->hostname);
1997 strncat(uh, hsock->hostname, len);
2000 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
2001 status, 0, ident, 3,
2002 2, idp->data, idp->len,
2007 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2008 0, packet->data, packet->len, FALSE);
2010 silc_buffer_free(packet);
2011 silc_buffer_free(idp);
2013 if (status == SILC_STATUS_LIST_END)
2020 SilcServerEntry entry;
2022 if (status == SILC_STATUS_OK && servers_count > 1)
2023 status = SILC_STATUS_LIST_START;
2025 for (i = 0, k = 0; i < servers_count; i++) {
2029 status = SILC_STATUS_LIST_ITEM;
2030 if (servers_count > 1 && k == servers_count - 1 && !channels_count &&
2032 status = SILC_STATUS_LIST_END;
2033 if (count && k - 1 == count)
2034 status = SILC_STATUS_LIST_END;
2036 /* Send IDENTIFY reply */
2037 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2039 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
2040 status, 0, ident, 2,
2041 2, idp->data, idp->len,
2042 3, entry->server_name,
2043 entry->server_name ?
2044 strlen(entry->server_name) : 0);
2045 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2046 0, packet->data, packet->len, FALSE);
2048 silc_buffer_free(packet);
2049 silc_buffer_free(idp);
2051 if (status == SILC_STATUS_LIST_END)
2058 SilcChannelEntry entry;
2060 if (status == SILC_STATUS_OK && channels_count > 1)
2061 status = SILC_STATUS_LIST_START;
2063 for (i = 0, k = 0; i < channels_count; i++) {
2064 entry = channels[i];
2067 status = SILC_STATUS_LIST_ITEM;
2068 if (channels_count > 1 && k == channels_count - 1 && !errors_count)
2069 status = SILC_STATUS_LIST_END;
2070 if (count && k - 1 == count)
2071 status = SILC_STATUS_LIST_END;
2073 /* Send IDENTIFY reply */
2074 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2076 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
2077 status, 0, ident, 2,
2078 2, idp->data, idp->len,
2079 3, entry->channel_name,
2080 entry->channel_name ?
2081 strlen(entry->channel_name): 0);
2082 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2083 0, packet->data, packet->len, FALSE);
2085 silc_buffer_free(packet);
2086 silc_buffer_free(idp);
2088 if (status == SILC_STATUS_LIST_END)
2094 /* Send error replies */
2096 if (status == SILC_STATUS_OK && errors_count > 1)
2097 status = SILC_STATUS_LIST_START;
2100 for (i = 0, k = 0; i < errors_count; i++) {
2102 idp = silc_id_payload_encode(errors[i].id, SILC_ID_CLIENT);
2106 tmp = silc_argument_get_arg_type(cmd->args, errors[i].index, &len);
2110 status = SILC_STATUS_LIST_ITEM;
2111 if (errors_count > 1 && k == errors_count - 1)
2112 status = SILC_STATUS_LIST_END;
2113 if (count && k - 1 == count)
2114 status = SILC_STATUS_LIST_END;
2117 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
2118 (status == SILC_STATUS_OK ?
2119 errors[i].error : status),
2120 (status == SILC_STATUS_OK ?
2121 0 : errors[i].error),
2123 silc_buffer_free(idp);
2126 if (status == SILC_STATUS_LIST_END)
2134 silc_server_command_identify_process(SilcServerCommandContext cmd)
2136 SilcUInt32 count = 0;
2138 SilcClientEntry *clients = NULL;
2139 SilcServerEntry *servers = NULL;
2140 SilcChannelEntry *channels = NULL;
2141 SilcUInt32 clients_count = 0, servers_count = 0, channels_count = 0;
2142 SilcUInt32 errors_count = 0;
2143 ResolveError errors = NULL;
2145 /* Parse the IDENTIFY request */
2146 ret = silc_server_command_identify_parse(cmd,
2147 &clients, &clients_count,
2148 &servers, &servers_count,
2149 &channels, &channels_count,
2150 &count, &errors, &errors_count);
2155 /* Check that all mandatory fields are present and request those data
2156 from the server who owns the client if necessary. */
2157 if (!silc_server_command_identify_check_client(cmd, clients,
2163 /* Send the command reply to the client */
2164 silc_server_command_identify_send_reply(cmd,
2165 clients, clients_count,
2166 servers, servers_count,
2167 channels, channels_count,
2168 errors, errors_count,
2174 silc_free(channels);
2179 SILC_SERVER_CMD_FUNC(identify)
2181 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2184 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 256);
2186 ret = silc_server_command_identify_process(cmd);
2187 silc_server_command_free(cmd);
2190 /* Server side of command NICK. Sets nickname for user. Setting
2191 nickname causes generation of a new client ID for the client. The
2192 new client ID is sent to the client after changing the nickname. */
2194 SILC_SERVER_CMD_FUNC(nick)
2196 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2197 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2198 SilcServer server = cmd->server;
2199 SilcBuffer packet, nidp, oidp = NULL;
2200 SilcClientID *new_id;
2201 SilcUInt32 nick_len;
2203 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2206 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
2209 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
2211 /* Check nickname */
2212 nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
2215 if (silc_server_name_bad_chars(nick, nick_len) == TRUE) {
2216 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2217 SILC_STATUS_ERR_BAD_NICKNAME, 0);
2221 /* Check for same nickname */
2222 if (!strcmp(client->nickname, nick)) {
2223 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2227 /* Create new Client ID */
2228 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
2230 cmd->server->md5hash, nick,
2234 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2235 SILC_STATUS_ERR_BAD_NICKNAME, 0);
2238 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2241 /* Send notify about nickname change to our router. We send the new
2242 ID and ask to replace it with the old one. If we are router the
2243 packet is broadcasted. Send NICK_CHANGE notify. */
2244 silc_server_send_notify_nick_change(server, SILC_PRIMARY_ROUTE(server),
2245 SILC_BROADCAST(server), client->id,
2248 /* Check if anyone is watching the old nickname */
2249 if (server->server_type == SILC_ROUTER)
2250 silc_server_check_watcher_list(server, client, nick,
2251 SILC_NOTIFY_TYPE_NICK_CHANGE);
2253 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2255 /* Remove old cache entry */
2256 silc_idcache_del_by_context(server->local_list->clients, client);
2258 silc_free(client->id);
2259 client->id = new_id;
2261 silc_free(client->nickname);
2262 client->nickname = strdup(nick);
2264 /* Update client cache */
2265 silc_idcache_add(server->local_list->clients, client->nickname,
2266 client->id, (void *)client, 0, NULL);
2268 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2270 /* Send NICK_CHANGE notify to the client's channels */
2271 silc_server_send_notify_on_channels(server, NULL, client,
2272 SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
2273 oidp->data, oidp->len,
2274 nidp->data, nidp->len,
2276 strlen(client->nickname));
2278 /* Check if anyone is watching the new nickname */
2279 if (server->server_type == SILC_ROUTER)
2280 silc_server_check_watcher_list(server, client, NULL,
2281 SILC_NOTIFY_TYPE_NICK_CHANGE);
2284 /* Send the new Client ID as reply command back to client */
2285 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
2286 SILC_STATUS_OK, 0, ident, 2,
2287 2, nidp->data, nidp->len,
2288 3, nick, strlen(nick));
2289 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2290 0, packet->data, packet->len, FALSE);
2292 silc_buffer_free(packet);
2293 silc_buffer_free(nidp);
2295 silc_buffer_free(oidp);
2298 silc_server_command_free(cmd);
2301 /* Sends the LIST command reply */
2304 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2305 SilcChannelEntry *lch,
2306 SilcUInt32 lch_count,
2307 SilcChannelEntry *gch,
2308 SilcUInt32 gch_count)
2311 SilcBuffer packet, idp;
2312 SilcChannelEntry entry;
2314 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2316 unsigned char usercount[4];
2318 int valid_lcount = 0, valid_rcount = 0;
2320 for (i = 0; i < lch_count; i++) {
2321 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2326 for (i = 0; i < gch_count; i++) {
2327 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2333 status = SILC_STATUS_OK;
2334 if ((lch_count + gch_count) > 1)
2335 status = SILC_STATUS_LIST_START;
2338 for (i = 0, k = 0; i < lch_count; i++) {
2344 status = SILC_STATUS_LIST_ITEM;
2345 if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
2346 status = SILC_STATUS_LIST_END;
2348 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2350 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2351 topic = "*private*";
2352 memset(usercount, 0, sizeof(usercount));
2354 topic = entry->topic;
2355 users = silc_hash_table_count(entry->user_list);
2356 SILC_PUT32_MSB(users, usercount);
2359 /* Send the reply */
2361 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2362 status, 0, ident, 4,
2363 2, idp->data, idp->len,
2364 3, entry->channel_name,
2365 strlen(entry->channel_name),
2366 4, topic, topic ? strlen(topic) : 0,
2368 silc_server_packet_send(cmd->server, cmd->sock,
2369 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2370 packet->len, FALSE);
2371 silc_buffer_free(packet);
2372 silc_buffer_free(idp);
2377 for (i = 0, k = 0; i < gch_count; i++) {
2383 status = SILC_STATUS_LIST_ITEM;
2384 if (valid_rcount > 1 && k == valid_rcount - 1)
2385 status = SILC_STATUS_LIST_END;
2387 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2389 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2390 topic = "*private*";
2391 memset(usercount, 0, sizeof(usercount));
2393 topic = entry->topic;
2394 users = entry->user_count;
2395 SILC_PUT32_MSB(users, usercount);
2398 /* Send the reply */
2400 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2401 status, 0, ident, 4,
2402 2, idp->data, idp->len,
2403 3, entry->channel_name,
2404 strlen(entry->channel_name),
2405 4, topic, topic ? strlen(topic) : 0,
2407 silc_server_packet_send(cmd->server, cmd->sock,
2408 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2409 packet->len, FALSE);
2410 silc_buffer_free(packet);
2411 silc_buffer_free(idp);
2416 /* Server side of LIST command. This lists the channel of the requested
2417 server. Secret channels are not listed. */
2419 SILC_SERVER_CMD_FUNC(list)
2421 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2422 SilcServer server = cmd->server;
2423 SilcChannelID *channel_id = NULL;
2426 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2427 SilcUInt32 lch_count = 0, gch_count = 0;
2429 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2431 /* If we are normal server, send the command to router, since we
2432 want to know all channels in the network. */
2433 if (!cmd->pending && server->server_type == SILC_SERVER &&
2434 !server->standalone) {
2436 SilcUInt16 old_ident;
2438 old_ident = silc_command_get_ident(cmd->payload);
2439 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2440 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2441 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
2442 SILC_PACKET_COMMAND, cmd->packet->flags,
2443 tmpbuf->data, tmpbuf->len, TRUE);
2445 /* Reprocess this packet after received reply from router */
2446 silc_server_command_pending(server, SILC_COMMAND_LIST,
2447 silc_command_get_ident(cmd->payload),
2448 silc_server_command_list,
2449 silc_server_command_dup(cmd));
2450 cmd->pending = TRUE;
2451 silc_command_set_ident(cmd->payload, old_ident);
2452 silc_buffer_free(tmpbuf);
2456 /* Get Channel ID */
2457 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2459 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2461 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2462 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2467 /* Get the channels from local list */
2468 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2471 /* Get the channels from global list */
2472 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2475 /* Send the reply */
2476 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2477 gchannels, gch_count);
2479 silc_free(lchannels);
2480 silc_free(gchannels);
2483 silc_server_command_free(cmd);
2486 /* Server side of TOPIC command. Sets topic for channel and/or returns
2487 current topic to client. */
2489 SILC_SERVER_CMD_FUNC(topic)
2491 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2492 SilcServer server = cmd->server;
2493 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2494 SilcChannelID *channel_id;
2495 SilcChannelEntry channel;
2496 SilcChannelClientEntry chl;
2497 SilcBuffer packet, idp;
2499 SilcUInt32 argc, tmp_len;
2500 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2502 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
2505 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2507 argc = silc_argument_get_arg_num(cmd->args);
2509 /* Get Channel ID */
2510 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2512 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2513 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2516 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2518 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2519 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2523 /* Check whether the channel exists */
2524 channel = silc_idlist_find_channel_by_id(server->local_list,
2527 channel = silc_idlist_find_channel_by_id(server->global_list,
2530 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2531 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
2539 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2541 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2542 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2547 if (strlen(tmp) > 256) {
2548 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2549 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2554 /* See whether the client is on channel and has rights to change topic */
2555 if (!silc_server_client_on_channel(client, channel, &chl)) {
2556 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2557 SILC_STATUS_ERR_NOT_ON_CHANNEL,
2562 if (channel->mode & SILC_CHANNEL_MODE_TOPIC &&
2563 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
2564 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
2565 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2566 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
2571 if (!channel->topic || strcmp(channel->topic, tmp)) {
2572 /* Set the topic for channel */
2573 silc_free(channel->topic);
2574 channel->topic = strdup(tmp);
2576 /* Send TOPIC_SET notify type to the network */
2577 silc_server_send_notify_topic_set(server, SILC_PRIMARY_ROUTE(server),
2578 SILC_BROADCAST(server), channel,
2579 client->id, SILC_ID_CLIENT,
2582 /* Send notify about topic change to all clients on the channel */
2583 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2584 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2585 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2586 idp->data, idp->len,
2588 strlen(channel->topic));
2589 silc_buffer_free(idp);
2593 /* Send the topic to client as reply packet */
2594 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2595 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2596 SILC_STATUS_OK, 0, ident, 2,
2597 2, idp->data, idp->len,
2600 strlen(channel->topic) : 0);
2601 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2602 0, packet->data, packet->len, FALSE);
2604 silc_buffer_free(packet);
2605 silc_buffer_free(idp);
2606 silc_free(channel_id);
2609 silc_server_command_free(cmd);
2612 /* Server side of INVITE command. Invites some client to join some channel.
2613 This command is also used to manage the invite list of the channel. */
2615 SILC_SERVER_CMD_FUNC(invite)
2617 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2618 SilcServer server = cmd->server;
2619 SilcSocketConnection sock = cmd->sock, dest_sock;
2620 SilcChannelClientEntry chl;
2621 SilcClientEntry sender, dest;
2622 SilcClientID *dest_id = NULL;
2623 SilcChannelEntry channel;
2624 SilcChannelID *channel_id = NULL;
2625 SilcIDListData idata;
2626 SilcBuffer idp, idp2, packet;
2627 unsigned char *tmp, *add, *del;
2629 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2631 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2633 /* Get Channel ID */
2634 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2636 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2637 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2640 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
2642 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2643 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2647 /* Get the channel entry */
2648 channel = silc_idlist_find_channel_by_id(server->local_list,
2651 channel = silc_idlist_find_channel_by_id(server->global_list,
2654 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2655 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
2661 /* Check whether the sender of this command is on the channel. */
2662 sender = (SilcClientEntry)sock->user_data;
2663 if (!sender || !silc_server_client_on_channel(sender, channel, &chl)) {
2664 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2665 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
2669 /* Check whether the channel is invite-only channel. If yes then the
2670 sender of this command must be at least channel operator. */
2671 if (channel->mode & SILC_CHANNEL_MODE_INVITE &&
2672 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
2673 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
2674 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2675 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
2680 /* Get destination client ID */
2681 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2686 dest_id = silc_id_payload_parse_id(tmp, len, NULL);
2688 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2689 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
2693 /* Get the client entry */
2694 dest = silc_server_query_client(server, dest_id, FALSE, &resolve);
2696 if (server->server_type != SILC_SERVER || !resolve) {
2697 silc_server_command_send_status_reply(
2698 cmd, SILC_COMMAND_INVITE,
2699 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0);
2703 /* The client info is being resolved. Reprocess this packet after
2704 receiving the reply to the query. */
2705 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2707 silc_server_command_invite,
2708 silc_server_command_dup(cmd));
2709 cmd->pending = TRUE;
2710 silc_free(channel_id);
2715 /* Check whether the requested client is already on the channel. */
2716 if (silc_server_client_on_channel(dest, channel, NULL)) {
2717 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2718 SILC_STATUS_ERR_USER_ON_CHANNEL,
2723 /* Get route to the client */
2724 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id,
2727 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2728 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2733 memset(invite, 0, sizeof(invite));
2734 strncat(invite, dest->nickname, strlen(dest->nickname));
2735 strncat(invite, "!", 1);
2736 strncat(invite, dest->username, strlen(dest->username));
2737 if (!strchr(dest->username, '@')) {
2738 strncat(invite, "@", 1);
2739 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2742 len = strlen(invite);
2743 if (!channel->invite_list)
2744 channel->invite_list = silc_calloc(len + 2,
2745 sizeof(*channel->invite_list));
2747 channel->invite_list = silc_realloc(channel->invite_list,
2748 sizeof(*channel->invite_list) *
2750 strlen(channel->invite_list) + 2));
2751 strncat(channel->invite_list, invite, len);
2752 strncat(channel->invite_list, ",", 1);
2754 if (!(dest->mode & SILC_UMODE_BLOCK_INVITE)) {
2755 /* Send notify to the client that is invited to the channel */
2756 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2757 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2758 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2760 SILC_NOTIFY_TYPE_INVITE, 3,
2761 idp->data, idp->len,
2762 channel->channel_name,
2763 strlen(channel->channel_name),
2764 idp2->data, idp2->len);
2765 silc_buffer_free(idp);
2766 silc_buffer_free(idp2);
2770 /* Add the client to the invite list of the channel */
2771 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2773 if (!channel->invite_list)
2774 channel->invite_list = silc_calloc(len + 2,
2775 sizeof(*channel->invite_list));
2777 channel->invite_list = silc_realloc(channel->invite_list,
2778 sizeof(*channel->invite_list) *
2780 strlen(channel->invite_list) + 2));
2781 if (add[len - 1] == ',')
2782 add[len - 1] = '\0';
2784 strncat(channel->invite_list, add, len);
2785 strncat(channel->invite_list, ",", 1);
2788 /* Get the invite to be removed and remove it from the list */
2789 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2790 if (del && channel->invite_list) {
2791 char *start, *end, *n;
2793 if (!strncmp(channel->invite_list, del,
2794 strlen(channel->invite_list) - 1)) {
2795 silc_free(channel->invite_list);
2796 channel->invite_list = NULL;
2798 start = strstr(channel->invite_list, del);
2799 if (start && strlen(start) >= len) {
2801 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2802 strncat(n, channel->invite_list, start - channel->invite_list);
2803 strncat(n, end + 1, ((channel->invite_list +
2804 strlen(channel->invite_list)) - end) - 1);
2805 silc_free(channel->invite_list);
2806 channel->invite_list = n;
2811 /* Send notify to the primary router */
2812 silc_server_send_notify_invite(server, SILC_PRIMARY_ROUTE(server),
2813 SILC_BROADCAST(server), channel,
2814 sender->id, add, del);
2816 /* Send command reply */
2817 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2821 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2822 SILC_STATUS_OK, 0, ident, 2,
2824 3, channel->invite_list,
2825 channel->invite_list ?
2826 strlen(channel->invite_list) : 0);
2829 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2830 SILC_STATUS_OK, 0, ident, 1,
2832 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2833 packet->data, packet->len, FALSE);
2834 silc_buffer_free(packet);
2838 silc_free(channel_id);
2839 silc_server_command_free(cmd);
2843 SilcSocketConnection sock;
2847 /* Quits connection to client. This gets called if client won't
2848 close the connection even when it has issued QUIT command. */
2850 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2852 SilcServer server = app_context;
2853 QuitInternal q = (QuitInternal)context;
2855 /* Free all client specific data, such as client entry and entires
2856 on channels this client may be on. */
2857 silc_server_free_client_data(server, q->sock, q->sock->user_data,
2859 q->sock->user_data = NULL;
2861 /* Close the connection on our side */
2862 silc_server_close_connection(server, q->sock);
2864 silc_socket_free(q->sock);
2865 silc_free(q->signoff);
2869 /* Quits SILC session. This is the normal way to disconnect client. */
2871 SILC_SERVER_CMD_FUNC(quit)
2873 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2874 SilcServer server = cmd->server;
2875 SilcSocketConnection sock = cmd->sock;
2877 unsigned char *tmp = NULL;
2880 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2882 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2886 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2890 q = silc_calloc(1, sizeof(*q));
2891 q->sock = silc_socket_dup(sock);
2892 q->signoff = tmp ? strdup(tmp) : NULL;
2894 /* We quit the connection with little timeout */
2895 silc_schedule_task_add(server->schedule, sock->sock,
2896 silc_server_command_quit_cb, (void *)q,
2897 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2900 silc_server_command_free(cmd);
2903 /* Server side of command KILL. This command is used by router operator
2904 to remove an client from the SILC Network temporarily. */
2906 SILC_SERVER_CMD_FUNC(kill)
2908 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2909 SilcServer server = cmd->server;
2910 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2911 SilcClientEntry remote_client;
2912 SilcClientID *client_id;
2913 unsigned char *tmp, *comment;
2914 SilcUInt32 tmp_len, tmp_len2;
2917 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2919 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
2922 /* KILL command works only on router */
2923 if (server->server_type != SILC_ROUTER) {
2924 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2925 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
2929 /* Check whether client has the permissions. */
2930 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2931 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2932 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
2936 /* Get the client ID */
2937 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2939 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2940 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2944 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2946 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2947 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2952 /* Get the client entry */
2953 remote_client = silc_idlist_find_client_by_id(server->local_list,
2954 client_id, TRUE, NULL);
2956 if (!remote_client) {
2957 remote_client = silc_idlist_find_client_by_id(server->global_list,
2958 client_id, TRUE, NULL);
2960 if (!remote_client) {
2961 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2962 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2969 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2973 /* Send reply to the sender */
2974 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2977 /* Check if anyone is watching this nickname */
2978 if (server->server_type == SILC_ROUTER)
2979 silc_server_check_watcher_list(server, client, NULL,
2980 SILC_NOTIFY_TYPE_KILLED);
2982 /* Now do the killing */
2983 silc_server_kill_client(server, remote_client, comment, client->id,
2987 silc_server_command_free(cmd);
2990 /* Server side of command INFO. This sends information about us to
2991 the client. If client requested specific server we will send the
2992 command to that server. */
2994 SILC_SERVER_CMD_FUNC(info)
2996 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2997 SilcServer server = cmd->server;
2998 SilcBuffer packet, idp;
3001 char *dest_server, *server_info = NULL, *server_name;
3002 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3003 SilcServerEntry entry = NULL;
3004 SilcServerID *server_id = NULL;
3006 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
3008 /* Get server name */
3009 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3012 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3014 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3016 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3017 SILC_STATUS_ERR_NO_SERVER_ID, 0);
3023 /* Check whether we have this server cached */
3024 entry = silc_idlist_find_server_by_id(server->local_list,
3025 server_id, TRUE, NULL);
3027 entry = silc_idlist_find_server_by_id(server->global_list,
3028 server_id, TRUE, NULL);
3029 if (!entry && server->server_type != SILC_SERVER) {
3030 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3031 SILC_STATUS_ERR_NO_SUCH_SERVER,
3038 /* Some buggy servers has sent request to router about themselves. */
3039 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
3042 if ((!dest_server && !server_id && !entry) || (entry &&
3043 entry == server->id_entry) ||
3044 (dest_server && !cmd->pending &&
3045 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
3046 /* Send our reply */
3047 char info_string[256];
3049 memset(info_string, 0, sizeof(info_string));
3050 snprintf(info_string, sizeof(info_string),
3051 "location: %s server: %s admin: %s <%s>",
3052 server->config->server_info->location,
3053 server->config->server_info->server_type,
3054 server->config->server_info->admin,
3055 server->config->server_info->email);
3057 server_info = info_string;
3058 entry = server->id_entry;
3060 /* Check whether we have this server cached */
3061 if (!entry && dest_server) {
3062 entry = silc_idlist_find_server_by_name(server->global_list,
3063 dest_server, TRUE, NULL);
3065 entry = silc_idlist_find_server_by_name(server->local_list,
3066 dest_server, TRUE, NULL);
3070 if (!cmd->pending &&
3071 server->server_type != SILC_SERVER && entry && !entry->server_info) {
3072 /* Send to the server */
3074 SilcUInt16 old_ident;
3076 old_ident = silc_command_get_ident(cmd->payload);
3077 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3078 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3080 silc_server_packet_send(server, entry->connection,
3081 SILC_PACKET_COMMAND, cmd->packet->flags,
3082 tmpbuf->data, tmpbuf->len, TRUE);
3084 /* Reprocess this packet after received reply from router */
3085 silc_server_command_pending(server, SILC_COMMAND_INFO,
3086 silc_command_get_ident(cmd->payload),
3087 silc_server_command_info,
3088 silc_server_command_dup(cmd));
3089 cmd->pending = TRUE;
3090 silc_command_set_ident(cmd->payload, old_ident);
3091 silc_buffer_free(tmpbuf);
3095 if (!entry && !cmd->pending && !server->standalone) {
3096 /* Send to the primary router */
3098 SilcUInt16 old_ident;
3100 old_ident = silc_command_get_ident(cmd->payload);
3101 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3102 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3104 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
3105 SILC_PACKET_COMMAND, cmd->packet->flags,
3106 tmpbuf->data, tmpbuf->len, TRUE);
3108 /* Reprocess this packet after received reply from router */
3109 silc_server_command_pending(server, SILC_COMMAND_INFO,
3110 silc_command_get_ident(cmd->payload),
3111 silc_server_command_info,
3112 silc_server_command_dup(cmd));
3113 cmd->pending = TRUE;
3114 silc_command_set_ident(cmd->payload, old_ident);
3115 silc_buffer_free(tmpbuf);
3120 silc_free(server_id);
3123 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3124 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3128 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
3130 server_info = entry->server_info;
3131 server_name = entry->server_name;
3133 /* Send the reply */
3134 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
3135 SILC_STATUS_OK, 0, ident, 3,
3136 2, idp->data, idp->len,
3138 strlen(server_name),
3141 strlen(server_info) : 0);
3142 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3143 packet->data, packet->len, FALSE);
3145 silc_buffer_free(packet);
3146 silc_buffer_free(idp);
3149 silc_server_command_free(cmd);
3152 /* Server side of command PING. This just replies to the ping. */
3154 SILC_SERVER_CMD_FUNC(ping)
3156 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3157 SilcServer server = cmd->server;
3162 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
3165 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
3167 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3168 SILC_STATUS_ERR_NO_SERVER_ID, 0);
3171 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
3175 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
3176 /* Send our reply */
3177 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3180 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3181 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3188 silc_server_command_free(cmd);
3191 /* Server side of command STATS. */
3193 SILC_SERVER_CMD_FUNC(stats)
3195 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3196 SilcServer server = cmd->server;
3197 SilcServerID *server_id;
3200 SilcBuffer packet, stats;
3201 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3204 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1);
3207 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3209 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3210 SILC_STATUS_ERR_NO_SERVER_ID, 0);
3213 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3217 /* The ID must be ours */
3218 if (!SILC_ID_SERVER_COMPARE(server->id, server_id)) {
3219 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3220 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3221 silc_free(server_id);
3224 silc_free(server_id);
3226 /* If we are router then just send everything we got. If we are normal
3227 server then we'll send this to our router to get all the latest
3228 statistical information. */
3229 if (!cmd->pending && server->server_type != SILC_ROUTER &&
3230 !server->standalone) {
3231 /* Send request to our router */
3232 SilcBuffer idp = silc_id_payload_encode(server->router->id,
3234 packet = silc_command_payload_encode_va(SILC_COMMAND_STATS,
3235 ++server->cmd_ident, 1,
3236 1, idp->data, idp->len);
3237 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
3238 SILC_PACKET_COMMAND, 0, packet->data,
3239 packet->len, FALSE);
3241 /* Reprocess this packet after received reply from router */
3242 silc_server_command_pending(server, SILC_COMMAND_STATS,
3244 silc_server_command_stats,
3245 silc_server_command_dup(cmd));
3246 cmd->pending = TRUE;
3247 silc_buffer_free(packet);
3248 silc_buffer_free(idp);
3252 /* Send our reply to sender */
3253 uptime = time(NULL) - server->starttime;
3255 stats = silc_buffer_alloc_size(60);
3256 silc_buffer_format(stats,
3257 SILC_STR_UI_INT(server->starttime),
3258 SILC_STR_UI_INT(uptime),
3259 SILC_STR_UI_INT(server->stat.my_clients),
3260 SILC_STR_UI_INT(server->stat.my_channels),
3261 SILC_STR_UI_INT(server->stat.my_server_ops),
3262 SILC_STR_UI_INT(server->stat.my_router_ops),
3263 SILC_STR_UI_INT(server->stat.cell_clients),
3264 SILC_STR_UI_INT(server->stat.cell_channels),
3265 SILC_STR_UI_INT(server->stat.cell_servers),
3266 SILC_STR_UI_INT(server->stat.clients),
3267 SILC_STR_UI_INT(server->stat.channels),
3268 SILC_STR_UI_INT(server->stat.servers),
3269 SILC_STR_UI_INT(server->stat.routers),
3270 SILC_STR_UI_INT(server->stat.server_ops),
3271 SILC_STR_UI_INT(server->stat.router_ops),
3274 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_STATS,
3275 SILC_STATUS_OK, 0, ident, 2,
3277 3, stats->data, stats->len);
3278 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
3279 0, packet->data, packet->len, FALSE);
3280 silc_buffer_free(packet);
3281 silc_buffer_free(stats);
3284 silc_server_command_free(cmd);
3287 /* Internal routine to join channel. The channel sent to this function
3288 has been either created or resolved from ID lists. This joins the sent
3289 client to the channel. */
3291 static void silc_server_command_join_channel(SilcServer server,
3292 SilcServerCommandContext cmd,
3293 SilcChannelEntry channel,
3294 SilcClientID *client_id,
3298 const unsigned char *auth,
3299 SilcUInt32 auth_len)
3301 SilcSocketConnection sock = cmd->sock;
3303 SilcUInt32 tmp_len, user_count;
3304 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
3305 SilcClientEntry client;
3306 SilcChannelClientEntry chl;
3307 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
3308 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3309 char check[512], check2[512];
3310 bool founder = FALSE;
3312 unsigned char *fkey = NULL;
3313 SilcUInt32 fkey_len = 0;
3315 SILC_LOG_DEBUG(("Joining client to channel"));
3320 /* Get the client entry */
3321 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3322 client = (SilcClientEntry)sock->user_data;
3326 client = silc_server_query_client(server, client_id, FALSE,
3333 silc_server_command_send_status_reply(
3334 cmd, SILC_COMMAND_JOIN,
3335 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3339 /* The client info is being resolved. Reprocess this packet after
3340 receiving the reply to the query. */
3341 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
3343 silc_server_command_join,
3344 silc_server_command_dup(cmd));
3345 cmd->pending = TRUE;
3349 cmd->pending = FALSE;
3353 * Check founder auth payload if provided. If client can gain founder
3354 * privileges it can override various conditions on joining the channel,
3355 * and can have directly the founder mode set on the channel.
3357 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3358 SilcIDListData idata = (SilcIDListData)client;
3359 SilcChannelClientEntry chl2;
3360 SilcHashTableList htl;
3362 if (channel->founder_key && idata->public_key &&
3363 silc_pkcs_public_key_compare(channel->founder_key,
3364 idata->public_key)) {
3365 /* Check whether the client is to become founder */
3366 if (silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
3367 channel->founder_key, 0, server->sha1hash,
3368 client->id, SILC_ID_CLIENT)) {
3370 /* There cannot be anyone else as founder on the channel now. This
3371 client is definitely the founder due to this authentication */
3372 silc_hash_table_list(channel->user_list, &htl);
3373 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
3374 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
3375 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3376 silc_server_force_cumode_change(server, NULL, channel, chl2,
3380 silc_hash_table_list_reset(&htl);
3382 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3389 * Check channel modes
3393 memset(check, 0, sizeof(check));
3394 memset(check2, 0, sizeof(check2));
3395 strncat(check, client->nickname, strlen(client->nickname));
3396 strncat(check, "!", 1);
3397 strncat(check, client->username, strlen(client->username));
3398 if (!strchr(client->username, '@')) {
3399 strncat(check, "@", 1);
3400 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3403 strncat(check2, client->nickname, strlen(client->nickname));
3404 if (!strchr(client->nickname, '@')) {
3405 strncat(check2, "@", 1);
3406 strncat(check2, server->server_name, strlen(server->server_name));
3408 strncat(check2, "!", 1);
3409 strncat(check2, client->username, strlen(client->username));
3410 if (!strchr(client->username, '@')) {
3411 strncat(check2, "@", 1);
3412 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3415 /* Check invite list if channel is invite-only channel */
3416 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3417 if (!channel->invite_list ||
3418 (!silc_string_match(channel->invite_list, check) &&
3419 !silc_string_match(channel->invite_list, check2))) {
3420 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3421 SILC_STATUS_ERR_NOT_INVITED, 0);
3426 /* Check ban list if it exists. If the client's nickname, server,
3427 username and/or hostname is in the ban list the access to the
3428 channel is denied. */
3429 if (channel->ban_list) {
3430 if (silc_string_match(channel->ban_list, check) ||
3431 silc_string_match(channel->ban_list, check2)) {
3432 silc_server_command_send_status_reply(
3433 cmd, SILC_COMMAND_JOIN,
3434 SILC_STATUS_ERR_BANNED_FROM_CHANNEL, 0);
3439 /* Check user count limit if set. */
3440 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3441 if (silc_hash_table_count(channel->user_list) + 1 >
3442 channel->user_limit) {
3443 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3444 SILC_STATUS_ERR_CHANNEL_IS_FULL,
3451 /* Check the channel passphrase if set. */
3452 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3453 /* Get passphrase */
3454 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3456 passphrase = silc_memdup(tmp, tmp_len);
3458 if (!passphrase || !channel->passphrase ||
3459 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3460 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3461 SILC_STATUS_ERR_BAD_PASSWORD, 0);
3467 * Client is allowed to join to the channel. Make it happen.
3470 /* Check whether the client already is on the channel */
3471 if (silc_server_client_on_channel(client, channel, NULL)) {
3472 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3473 SILC_STATUS_ERR_USER_ON_CHANNEL, 0);
3477 /* Generate new channel key as protocol dictates */
3479 if (!silc_server_create_channel_key(server, channel, 0))
3482 /* Send the channel key. This is broadcasted to the channel but is not
3483 sent to the client who is joining to the channel. */
3484 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3485 silc_server_send_channel_key(server, NULL, channel,
3486 server->server_type == SILC_ROUTER ?
3487 FALSE : !server->standalone);
3490 /* Join the client to the channel by adding it to channel's user list.
3491 Add also the channel to client entry's channels list for fast cross-
3493 chl = silc_calloc(1, sizeof(*chl));
3495 chl->client = client;
3496 chl->channel = channel;
3497 silc_hash_table_add(channel->user_list, client, chl);
3498 silc_hash_table_add(client->channels, channel, chl);
3499 channel->user_count++;
3500 channel->disabled = FALSE;
3502 /* Get users on the channel */
3503 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3506 /* Encode Client ID Payload of the original client who wants to join */
3507 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3509 /* Encode command reply packet */
3510 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3511 SILC_PUT32_MSB(channel->mode, mode);
3512 SILC_PUT32_MSB(created, tmp2);
3513 SILC_PUT32_MSB(user_count, tmp3);
3515 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3516 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3517 keyp = silc_channel_key_payload_encode(silc_id_get_len(channel->id,
3520 strlen(channel->channel_key->
3522 channel->channel_key->cipher->name,
3523 channel->key_len / 8, channel->key);
3527 if (channel->founder_key)
3528 fkey = silc_pkcs_public_key_encode(channel->founder_key, &fkey_len);
3531 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3532 SILC_STATUS_OK, 0, ident, 14,
3533 2, channel->channel_name,
3534 strlen(channel->channel_name),
3535 3, chidp->data, chidp->len,
3536 4, clidp->data, clidp->len,
3539 7, keyp ? keyp->data : NULL,
3540 keyp ? keyp->len : 0,
3541 8, channel->ban_list,
3543 strlen(channel->ban_list) : 0,
3544 9, channel->invite_list,
3545 channel->invite_list ?
3546 strlen(channel->invite_list) : 0,
3549 strlen(channel->topic) : 0,
3550 11, silc_hmac_get_name(channel->hmac),
3551 strlen(silc_hmac_get_name(channel->
3554 13, user_list->data, user_list->len,
3555 14, mode_list->data,
3557 15, fkey, fkey_len);
3559 /* Send command reply */
3560 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3561 reply->data, reply->len, FALSE);
3563 /* Send JOIN notify to locally connected clients on the channel. If
3564 we are normal server then router will send or have sent JOIN notify
3565 already. However since we've added the client already to our channel
3566 we'll ignore it (in packet_receive.c) so we must send it here. If
3567 we are router then this will send it to local clients and local
3569 SILC_LOG_DEBUG(("Send JOIN notify to channel"));
3570 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3571 SILC_NOTIFY_TYPE_JOIN, 2,
3572 clidp->data, clidp->len,
3573 chidp->data, chidp->len);
3575 /* Update statistics */
3576 server->stat.my_chanclients++;
3577 if (server->server_type == SILC_ROUTER) {
3578 server->stat.cell_chanclients++;
3579 server->stat.chanclients++;
3582 if (!cmd->pending) {
3583 /* Send JOIN notify packet to our primary router */
3584 silc_server_send_notify_join(server, SILC_PRIMARY_ROUTE(server),
3585 SILC_BROADCAST(server), channel, client->id);
3588 /* Distribute the channel key to all backup routers. */
3589 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3590 keyp->data, keyp->len, FALSE, TRUE);
3592 /* If client became founder by providing correct founder auth data
3593 notify the mode change to the channel. */
3595 SILC_PUT32_MSB(chl->mode, mode);
3596 SILC_LOG_DEBUG(("Send CUMODE_CHANGE notify to channel"));
3597 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3598 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
3599 clidp->data, clidp->len,
3600 mode, 4, clidp->data, clidp->len,
3605 /* Set CUMODE notify type to network */
3607 silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
3608 SILC_BROADCAST(server), channel,
3609 chl->mode, client->id, SILC_ID_CLIENT,
3610 client->id, channel->founder_key);
3612 silc_buffer_free(reply);
3613 silc_buffer_free(clidp);
3614 silc_buffer_free(chidp);
3615 silc_buffer_free(keyp);
3616 silc_buffer_free(user_list);
3617 silc_buffer_free(mode_list);
3621 silc_free(passphrase);
3624 /* Server side of command JOIN. Joins client into requested channel. If
3625 the channel does not exist it will be created. */
3627 SILC_SERVER_CMD_FUNC(join)
3629 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3630 SilcServer server = cmd->server;
3631 unsigned char *auth;
3632 SilcUInt32 tmp_len, auth_len;
3633 char *tmp, *channel_name = NULL, *cipher, *hmac;
3634 SilcChannelEntry channel;
3635 SilcUInt32 umode = 0;
3636 bool created = FALSE, create_key = TRUE;
3637 SilcClientID *client_id;
3639 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3641 /* Get channel name */
3642 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3644 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3645 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3652 channel_name[255] = '\0';
3654 if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
3655 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3656 SILC_STATUS_ERR_BAD_CHANNEL, 0);
3660 /* Get Client ID of the client who is joining to the channel */
3661 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3663 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3664 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3668 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3670 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3671 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3676 /* Get cipher, hmac name and auth payload */
3677 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3678 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3679 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3681 /* See if the channel exists */
3682 channel = silc_idlist_find_channel_by_name(server->local_list,
3683 channel_name, NULL);
3685 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3686 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3688 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3689 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3694 silc_free(client_id);
3695 client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
3698 (channel->disabled && server->server_type != SILC_ROUTER)) {
3699 /* Channel not found or not valid */
3701 /* If we are standalone server we don't have a router, we just create
3702 the channel by ourselves (unless it existed). */
3703 if (server->standalone) {
3705 channel = silc_server_create_new_channel(server, server->id, cipher,
3706 hmac, channel_name, TRUE);
3708 silc_server_command_send_status_reply(
3709 cmd, SILC_COMMAND_JOIN,
3710 SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
3712 silc_free(client_id);
3716 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3722 /* The channel does not exist on our server. If we are normal server
3723 we will send JOIN command to our router which will handle the
3724 joining procedure (either creates the channel if it doesn't exist
3725 or joins the client to it). */
3726 if (server->server_type != SILC_ROUTER) {
3728 SilcUInt16 old_ident;
3730 /* If this is pending command callback then we've resolved
3731 it and it didn't work, return since we've notified the
3732 client already in the command reply callback. */
3734 silc_free(client_id);
3738 old_ident = silc_command_get_ident(cmd->payload);
3739 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3740 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3742 /* Send JOIN command to our router */
3743 silc_server_packet_send(server, (SilcSocketConnection)
3744 SILC_PRIMARY_ROUTE(server),
3745 SILC_PACKET_COMMAND, cmd->packet->flags,
3746 tmpbuf->data, tmpbuf->len, TRUE);
3748 /* Reprocess this packet after received reply from router */
3749 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3750 silc_command_get_ident(cmd->payload),
3751 silc_server_command_join,
3752 silc_server_command_dup(cmd));
3753 cmd->pending = TRUE;
3754 silc_command_set_ident(cmd->payload, old_ident);
3755 silc_buffer_free(tmpbuf);
3756 silc_free(client_id);
3760 /* We are router and the channel does not seem exist so we will check
3761 our global list as well for the channel. */
3762 channel = silc_idlist_find_channel_by_name(server->global_list,
3763 channel_name, NULL);
3765 /* Channel really does not exist, create it */
3766 channel = silc_server_create_new_channel(server, server->id, cipher,
3767 hmac, channel_name, TRUE);
3769 silc_server_command_send_status_reply(
3770 cmd, SILC_COMMAND_JOIN,
3771 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
3772 silc_free(client_id);
3776 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3784 /* Channel not found */
3786 /* If the command came from router and we are normal server then
3787 something went wrong with the joining as the channel was not found.
3788 We can't do anything else but ignore this. */
3789 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3790 server->server_type != SILC_ROUTER) {
3791 silc_free(client_id);
3795 /* We are router and the channel does not seem exist so we will check
3796 our global list as well for the channel. */
3797 channel = silc_idlist_find_channel_by_name(server->global_list,
3798 channel_name, NULL);
3800 /* Channel really does not exist, create it */
3801 channel = silc_server_create_new_channel(server, server->id, cipher,
3802 hmac, channel_name, TRUE);
3804 silc_server_command_send_status_reply(
3805 cmd, SILC_COMMAND_JOIN,
3806 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
3807 silc_free(client_id);
3811 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3818 /* Check whether the channel was created by our router */
3819 if (cmd->pending && context2) {
3820 SilcServerCommandReplyContext reply = context2;
3822 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3823 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3824 SILC_GET32_MSB(created, tmp);
3825 if (silc_argument_get_arg_type(reply->args, 7, NULL))
3826 create_key = FALSE; /* Router returned the key already */
3828 if (silc_command_get_status(reply->payload, NULL, NULL) &&
3829 channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3830 /* Save channel passphrase, if user provided it successfully */
3833 pa = silc_argument_get_arg_type(cmd->args, 3, &pa_len);
3835 silc_free(channel->passphrase);
3836 channel->passphrase = silc_memdup(pa, pa_len);
3841 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
3842 !channel->disabled && !silc_hash_table_count(channel->user_list))
3846 /* If the channel does not have global users and is also empty the client
3847 will be the channel founder and operator. */
3848 if (!channel->disabled &&
3849 !channel->global_users && !silc_hash_table_count(channel->user_list))
3850 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3852 /* Join to the channel */
3853 silc_server_command_join_channel(server, cmd, channel, client_id,
3854 created, create_key, umode,
3857 silc_free(client_id);
3860 silc_server_command_free(cmd);
3863 /* Server side of command MOTD. Sends server's current "message of the
3864 day" to the client. */
3866 SILC_SERVER_CMD_FUNC(motd)
3868 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3869 SilcServer server = cmd->server;
3870 SilcBuffer packet, idp;
3871 char *motd, *dest_server;
3872 SilcUInt32 motd_len;
3873 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3875 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3877 /* Get server name */
3878 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3880 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3881 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3885 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3888 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3890 if (server->config && server->config->server_info &&
3891 server->config->server_info->motd_file) {
3893 motd = silc_file_readfile(server->config->server_info->motd_file,
3899 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3906 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3912 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3913 packet->data, packet->len, FALSE);
3914 silc_buffer_free(packet);
3915 silc_buffer_free(idp);
3917 SilcServerEntry entry;
3919 /* Check whether we have this server cached */
3920 entry = silc_idlist_find_server_by_name(server->global_list,
3921 dest_server, TRUE, NULL);
3923 entry = silc_idlist_find_server_by_name(server->local_list,
3924 dest_server, TRUE, NULL);
3927 if (server->server_type != SILC_SERVER && !cmd->pending &&
3928 entry && !entry->motd) {
3929 /* Send to the server */
3931 SilcUInt16 old_ident;
3933 old_ident = silc_command_get_ident(cmd->payload);
3934 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3935 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3937 silc_server_packet_send(server, entry->connection,
3938 SILC_PACKET_COMMAND, cmd->packet->flags,
3939 tmpbuf->data, tmpbuf->len, TRUE);
3941 /* Reprocess this packet after received reply from router */
3942 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3943 silc_command_get_ident(cmd->payload),
3944 silc_server_command_motd,
3945 silc_server_command_dup(cmd));
3946 cmd->pending = TRUE;
3947 silc_command_set_ident(cmd->payload, old_ident);
3948 silc_buffer_free(tmpbuf);
3952 if (!entry && !cmd->pending && !server->standalone) {
3953 /* Send to the primary router */
3955 SilcUInt16 old_ident;
3957 old_ident = silc_command_get_ident(cmd->payload);
3958 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3959 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3961 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
3962 SILC_PACKET_COMMAND, cmd->packet->flags,
3963 tmpbuf->data, tmpbuf->len, TRUE);
3965 /* Reprocess this packet after received reply from router */
3966 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3967 silc_command_get_ident(cmd->payload),
3968 silc_server_command_motd,
3969 silc_server_command_dup(cmd));
3970 cmd->pending = TRUE;
3971 silc_command_set_ident(cmd->payload, old_ident);
3972 silc_buffer_free(tmpbuf);
3977 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3978 SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3982 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3983 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3984 SILC_STATUS_OK, 0, ident, 2,
3988 strlen(entry->motd) : 0);
3989 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3990 packet->data, packet->len, FALSE);
3991 silc_buffer_free(packet);
3992 silc_buffer_free(idp);
3996 silc_server_command_free(cmd);
3999 /* Server side of command UMODE. Client can use this command to set/unset
4000 user mode. Client actually cannot set itself to be as server/router
4001 operator so this can be used only to unset the modes. */
4003 SILC_SERVER_CMD_FUNC(umode)
4005 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4006 SilcServer server = cmd->server;
4007 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4009 unsigned char *tmp_mask, m[4];
4010 SilcUInt32 mask = 0;
4011 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4012 bool set_mask = FALSE;
4014 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
4017 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2);
4019 /* Get the client's mode mask */
4020 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4022 SILC_GET32_MSB(mask, tmp_mask);
4027 /* Check that mode changing is allowed. */
4028 if (!silc_server_check_umode_rights(server, client, mask)) {
4029 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
4030 SILC_STATUS_ERR_PERM_DENIED, 0);
4034 /* Anonymous mode cannot be set by client */
4035 if (mask & SILC_UMODE_ANONYMOUS) {
4036 if (!(client->mode & SILC_UMODE_ANONYMOUS)) {
4037 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
4038 SILC_STATUS_ERR_PERM_DENIED, 0);
4042 if (client->mode & SILC_UMODE_ANONYMOUS) {
4043 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
4044 SILC_STATUS_ERR_PERM_DENIED, 0);
4049 /* Update statistics */
4050 if (mask & SILC_UMODE_GONE) {
4051 if (!(client->mode & SILC_UMODE_GONE))
4052 server->stat.my_aways++;
4054 if (client->mode & SILC_UMODE_GONE)
4055 server->stat.my_aways--;
4058 /* Change the mode */
4059 client->mode = mask;
4061 /* Send UMODE change to primary router */
4062 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
4063 SILC_BROADCAST(server), client->id,
4066 /* Check if anyone is watching this nickname */
4067 if (server->server_type == SILC_ROUTER)
4068 silc_server_check_watcher_list(server, client, NULL,
4069 SILC_NOTIFY_TYPE_UMODE_CHANGE);
4072 /* Send command reply to sender */
4073 SILC_PUT32_MSB(client->mode, m);
4074 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
4075 SILC_STATUS_OK, 0, ident, 1,
4077 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4078 packet->data, packet->len, FALSE);
4079 silc_buffer_free(packet);
4082 silc_server_command_free(cmd);
4085 /* Server side command of CMODE. Changes channel mode */
4087 SILC_SERVER_CMD_FUNC(cmode)
4089 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4090 SilcServer server = cmd->server;
4091 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4092 SilcIDListData idata = (SilcIDListData)client;
4093 SilcChannelID *channel_id = NULL;
4094 SilcChannelEntry channel;
4095 SilcChannelClientEntry chl;
4096 SilcBuffer packet, cidp;
4097 unsigned char *tmp, *tmp_id, *tmp_mask;
4098 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
4099 SilcUInt32 mode_mask = 0, old_mask = 0, tmp_len, tmp_len2;
4100 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4101 bool set_mask = FALSE;
4102 SilcPublicKey founder_key = NULL;
4103 unsigned char *fkey = NULL;
4104 SilcUInt32 fkey_len = 0;
4107 silc_server_command_free(cmd);
4111 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 7);
4113 /* Get Channel ID */
4114 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
4116 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4117 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4118 silc_server_command_free(cmd);
4121 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
4123 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4124 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4125 silc_server_command_free(cmd);
4129 /* Get channel entry */
4130 channel = silc_idlist_find_channel_by_id(server->local_list,
4133 channel = silc_idlist_find_channel_by_id(server->global_list,
4136 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4137 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4139 silc_free(channel_id);
4140 silc_server_command_free(cmd);
4144 old_mask = channel->mode;
4146 /* Get the channel mode mask */
4147 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4149 SILC_GET32_MSB(mode_mask, tmp_mask);
4153 /* Check whether this client is on the channel */
4154 if (!silc_server_client_on_channel(client, channel, &chl)) {
4155 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4156 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4160 /* Check that client has rights to change any requested channel modes */
4161 if (set_mask && !silc_server_check_cmode_rights(server, channel, chl,
4163 SILC_LOG_DEBUG(("Client does not have rights to change mode"));
4164 silc_server_command_send_status_reply(
4165 cmd, SILC_COMMAND_CMODE,
4166 (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) ?
4167 SILC_STATUS_ERR_NO_CHANNEL_PRIV :
4168 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV), 0);
4172 /* If mode mask was not sent as argument then merely return the current
4173 mode mask to the sender. */
4176 SILC_PUT32_MSB(channel->mode, m);
4177 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4178 SILC_STATUS_OK, 0, ident, 2,
4179 2, tmp_id, tmp_len2,
4181 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4182 packet->data, packet->len, FALSE);
4183 silc_buffer_free(packet);
4188 * Check the modes. Modes that requires nothing special operation are
4192 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
4193 /* Channel uses private keys to protect traffic. Client(s) has set the
4194 key locally they want to use, server does not know that key. */
4195 /* Nothing interesting to do here */
4197 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
4198 /* The mode is removed and we need to generate and distribute
4199 new channel key. Clients are not using private channel keys
4200 anymore after this. */
4202 /* Re-generate channel key */
4203 if (!silc_server_create_channel_key(server, channel, 0))
4206 /* Send the channel key. This sends it to our local clients and if
4207 we are normal server to our router as well. */
4208 silc_server_send_channel_key(server, NULL, channel,
4209 server->server_type == SILC_ROUTER ?
4210 FALSE : !server->standalone);
4212 cipher = channel->channel_key->cipher->name;
4213 hmac = (char *)silc_hmac_get_name(channel->hmac);
4217 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
4218 /* User limit is set on channel */
4219 SilcUInt32 user_limit;
4221 /* Get user limit */
4222 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
4224 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
4225 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4226 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4230 SILC_GET32_MSB(user_limit, tmp);
4231 channel->user_limit = user_limit;
4234 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
4235 /* User limit mode is unset. Remove user limit */
4236 channel->user_limit = 0;
4239 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
4240 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
4241 /* Passphrase has been set to channel */
4243 /* Get the passphrase */
4244 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
4246 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4247 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4251 /* Save the passphrase */
4252 passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
4255 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
4256 /* Passphrase mode is unset. remove the passphrase */
4257 silc_free(channel->passphrase);
4258 channel->passphrase = NULL;
4262 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
4263 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
4264 /* Cipher to use protect the traffic */
4265 SilcCipher newkey, oldkey;
4268 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
4270 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4271 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4275 /* Delete old cipher and allocate the new one */
4276 if (!silc_cipher_alloc(cipher, &newkey)) {
4277 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4278 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4282 oldkey = channel->channel_key;
4283 channel->channel_key = newkey;
4285 /* Re-generate channel key */
4286 if (!silc_server_create_channel_key(server, channel, 0)) {
4287 /* We don't have new key, revert to old one */
4288 channel->channel_key = oldkey;
4292 /* Remove old channel key for good */
4293 silc_cipher_free(oldkey);
4295 /* Send the channel key. This sends it to our local clients and if
4296 we are normal server to our router as well. */
4297 silc_server_send_channel_key(server, NULL, channel,
4298 server->server_type == SILC_ROUTER ?
4299 FALSE : !server->standalone);
4302 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
4303 /* Cipher mode is unset. Remove the cipher and revert back to
4305 SilcCipher newkey, oldkey;
4306 cipher = channel->cipher;
4308 /* Delete old cipher and allocate default one */
4309 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
4310 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4311 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4315 oldkey = channel->channel_key;
4316 channel->channel_key = newkey;
4318 /* Re-generate channel key */
4319 if (!silc_server_create_channel_key(server, channel, 0)) {
4320 /* We don't have new key, revert to old one */
4321 channel->channel_key = oldkey;
4325 /* Remove old channel key for good */
4326 silc_cipher_free(oldkey);
4328 /* Send the channel key. This sends it to our local clients and if
4329 we are normal server to our router as well. */
4330 silc_server_send_channel_key(server, NULL, channel,
4331 server->server_type == SILC_ROUTER ?
4332 FALSE : !server->standalone);
4336 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
4337 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
4338 /* HMAC to use protect the traffic */
4339 unsigned char hash[32];
4343 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4345 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4346 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4350 /* Delete old hmac and allocate the new one */
4351 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4352 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4353 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4357 silc_hmac_free(channel->hmac);
4358 channel->hmac = newhmac;
4360 /* Set the HMAC key out of current channel key. The client must do
4362 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4363 channel->key_len / 8, hash);
4364 silc_hmac_set_key(channel->hmac, hash,
4365 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4366 memset(hash, 0, sizeof(hash));
4369 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4370 /* Hmac mode is unset. Remove the hmac and revert back to
4373 unsigned char hash[32];
4374 hmac = channel->hmac_name;
4376 /* Delete old hmac and allocate default one */
4377 silc_hmac_free(channel->hmac);
4378 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4379 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4380 SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4384 silc_hmac_free(channel->hmac);
4385 channel->hmac = newhmac;
4387 /* Set the HMAC key out of current channel key. The client must do
4389 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4390 channel->key_len / 8,
4392 silc_hmac_set_key(channel->hmac, hash,
4393 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4394 memset(hash, 0, sizeof(hash));
4398 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4399 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4400 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4401 /* Set the founder authentication */
4402 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4404 silc_server_command_send_status_reply(
4405 cmd, SILC_COMMAND_CMODE,
4406 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4410 /* Verify the payload before setting the mode */
4411 if (!silc_auth_verify_data(tmp, tmp_len, SILC_AUTH_PUBLIC_KEY,
4412 idata->public_key, 0, server->sha1hash,
4413 client->id, SILC_ID_CLIENT)) {
4414 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4415 SILC_STATUS_ERR_AUTH_FAILED,
4420 /* Save the public key */
4421 channel->founder_key = silc_pkcs_public_key_copy(idata->public_key);
4422 if (!channel->founder_key) {
4423 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4424 SILC_STATUS_ERR_AUTH_FAILED,
4429 founder_key = channel->founder_key;
4430 fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
4432 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4433 SILC_STATUS_ERR_AUTH_FAILED,
4435 silc_pkcs_public_key_free(channel->founder_key);
4436 channel->founder_key = NULL;
4442 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4443 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4444 if (channel->founder_key)
4445 silc_pkcs_public_key_free(channel->founder_key);
4446 channel->founder_key = NULL;
4451 /* Finally, set the mode */
4452 old_mask = channel->mode = mode_mask;
4454 /* Send CMODE_CHANGE notify. */
4455 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4456 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4457 SILC_NOTIFY_TYPE_CMODE_CHANGE, 6,
4458 cidp->data, cidp->len,
4460 cipher, cipher ? strlen(cipher) : 0,
4461 hmac, hmac ? strlen(hmac) : 0,
4462 passphrase, passphrase ?
4463 strlen(passphrase) : 0,
4466 /* Set CMODE notify type to network */
4467 silc_server_send_notify_cmode(server, SILC_PRIMARY_ROUTE(server),
4468 SILC_BROADCAST(server), channel,
4469 mode_mask, client->id, SILC_ID_CLIENT,
4470 cipher, hmac, passphrase, founder_key);
4472 /* Send command reply to sender */
4473 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4474 SILC_STATUS_OK, 0, ident, 2,
4475 2, tmp_id, tmp_len2,
4477 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4478 packet->data, packet->len, FALSE);
4480 silc_buffer_free(packet);
4481 silc_buffer_free(cidp);
4484 channel->mode = old_mask;
4486 silc_free(channel_id);
4487 silc_server_command_free(cmd);
4490 /* Server side of CUMODE command. Changes client's mode on a channel. */
4492 SILC_SERVER_CMD_FUNC(cumode)
4494 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4495 SilcServer server = cmd->server;
4496 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4497 SilcIDListData idata = (SilcIDListData)client;
4498 SilcChannelID *channel_id;
4499 SilcClientID *client_id;
4500 SilcChannelEntry channel;
4501 SilcClientEntry target_client;
4502 SilcChannelClientEntry chl;
4503 SilcBuffer packet, idp;
4504 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4505 SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4507 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4508 SilcPublicKey founder_key = NULL;
4509 unsigned char *fkey = NULL;
4510 SilcUInt32 fkey_len = 0;
4515 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4517 /* Get Channel ID */
4518 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4520 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4521 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4524 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
4526 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4527 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4531 /* Get channel entry */
4532 channel = silc_idlist_find_channel_by_id(server->local_list,
4535 channel = silc_idlist_find_channel_by_id(server->global_list,
4538 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4539 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4545 /* Check whether sender is on the channel */
4546 if (!silc_server_client_on_channel(client, channel, &chl)) {
4547 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4548 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4551 sender_mask = chl->mode;
4553 /* Get the target client's channel mode mask */
4554 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4556 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4557 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4561 SILC_GET32_MSB(target_mask, tmp_mask);
4563 /* Get target Client ID */
4564 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4566 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4567 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4570 client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
4572 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4573 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4577 /* Get target client's entry */
4578 target_client = silc_idlist_find_client_by_id(server->local_list,
4579 client_id, TRUE, NULL);
4580 if (!target_client) {
4581 target_client = silc_idlist_find_client_by_id(server->global_list,
4582 client_id, TRUE, NULL);
4585 if (target_client != client &&
4586 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4587 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4588 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4589 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
4593 /* Check whether target client is on the channel */
4594 if (target_client != client) {
4595 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4596 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4597 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL, 0);
4606 /* If the target client is founder, no one else can change their mode
4608 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4609 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4610 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
4615 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4616 if (target_client != client) {
4617 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4618 SILC_STATUS_ERR_NOT_YOU, 0);
4622 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4623 /* The client tries to claim the founder rights. */
4624 unsigned char *tmp_auth;
4625 SilcUInt32 tmp_auth_len;
4626 SilcChannelClientEntry chl2;
4627 SilcHashTableList htl;
4629 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4630 !channel->founder_key || !idata->public_key ||
4631 !silc_pkcs_public_key_compare(channel->founder_key,
4632 idata->public_key)) {
4633 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4634 SILC_STATUS_ERR_AUTH_FAILED, 0);
4638 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4640 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4641 SILC_STATUS_ERR_AUTH_FAILED, 0);
4645 /* Verify the authentication payload */
4646 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len, SILC_AUTH_PUBLIC_KEY,
4647 channel->founder_key, 0, server->sha1hash,
4648 client->id, SILC_ID_CLIENT)) {
4649 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4650 SILC_STATUS_ERR_AUTH_FAILED, 0);
4655 founder_key = channel->founder_key;
4656 fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
4658 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4659 SILC_STATUS_ERR_AUTH_FAILED, 0);
4663 /* There cannot be anyone else as founder on the channel now. This
4664 client is definitely the founder due to this authentication */
4665 silc_hash_table_list(channel->user_list, &htl);
4666 while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
4667 if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
4668 chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4669 silc_server_force_cumode_change(server, NULL, channel, chl2,
4673 silc_hash_table_list_reset(&htl);
4675 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4678 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4679 if (target_client == client) {
4680 /* Remove channel founder rights from itself */
4681 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4684 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4685 SILC_STATUS_ERR_NOT_YOU, 0);
4691 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4692 /* Promote to operator */
4693 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4694 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4695 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4696 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4697 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
4702 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4706 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4707 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4708 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4709 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4710 SILC_STATUS_ERR_NO_CHANNEL_PRIV,
4715 /* Demote to normal user */
4716 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4721 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4722 if (target_client != client) {
4723 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4724 SILC_STATUS_ERR_NOT_YOU, 0);
4728 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
4729 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4733 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4734 if (target_client != client) {
4735 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4736 SILC_STATUS_ERR_NOT_YOU, 0);
4740 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4745 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4746 if (target_client != client) {
4747 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4748 SILC_STATUS_ERR_NOT_YOU, 0);
4752 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)) {
4753 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4757 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4758 if (target_client != client) {
4759 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4760 SILC_STATUS_ERR_NOT_YOU, 0);
4764 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4769 if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4770 if (target_client != client) {
4771 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4772 SILC_STATUS_ERR_NOT_YOU, 0);
4776 if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)) {
4777 chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4781 if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4782 if (target_client != client) {
4783 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4784 SILC_STATUS_ERR_NOT_YOU, 0);
4788 chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4793 if (target_mask & SILC_CHANNEL_UMODE_QUIET) {
4794 if (!(chl->mode & SILC_CHANNEL_UMODE_QUIET)) {
4795 if (client == target_client) {
4796 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4797 SILC_STATUS_ERR_PERM_DENIED, 0);
4800 chl->mode |= SILC_CHANNEL_UMODE_QUIET;
4804 if (chl->mode & SILC_CHANNEL_UMODE_QUIET) {
4805 if (client == target_client) {
4806 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4807 SILC_STATUS_ERR_PERM_DENIED, 0);
4810 chl->mode &= ~SILC_CHANNEL_UMODE_QUIET;
4815 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4816 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4818 /* Send notify to channel, notify only if mode was actually changed. */
4820 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4821 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
4822 idp->data, idp->len,
4827 /* Set CUMODE notify type to network */
4828 silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
4829 SILC_BROADCAST(server), channel,
4830 target_mask, client->id, SILC_ID_CLIENT,
4831 target_client->id, founder_key);
4834 /* Send command reply to sender */
4835 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4836 SILC_STATUS_OK, 0, ident, 3,
4838 3, tmp_ch_id, tmp_ch_len,
4839 4, tmp_id, tmp_len);
4840 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4841 packet->data, packet->len, FALSE);
4843 silc_buffer_free(packet);
4844 silc_free(channel_id);
4845 silc_free(client_id);
4846 silc_buffer_free(idp);
4850 silc_server_command_free(cmd);
4853 /* Server side of KICK command. Kicks client out of channel. */
4855 SILC_SERVER_CMD_FUNC(kick)
4857 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4858 SilcServer server = cmd->server;
4859 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4860 SilcClientEntry target_client;
4861 SilcChannelID *channel_id;
4862 SilcClientID *client_id;
4863 SilcChannelEntry channel;
4864 SilcChannelClientEntry chl;
4866 SilcUInt32 tmp_len, target_idp_len;
4867 unsigned char *tmp, *comment, *target_idp;
4872 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4874 /* Get Channel ID */
4875 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4877 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4878 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4881 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4883 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4884 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4888 /* Get channel entry */
4889 channel = silc_idlist_find_channel_by_id(server->local_list,
4892 channel = silc_idlist_find_channel_by_id(server->local_list,
4895 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4896 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4902 /* Check whether sender is on the channel */
4903 if (!silc_server_client_on_channel(client, channel, &chl)) {
4904 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4905 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4909 /* Check that the kicker is channel operator or channel founder */
4910 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
4911 !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4912 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4913 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
4917 /* Get target Client ID */
4918 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4920 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4921 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4924 client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
4926 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4927 SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4931 /* Get target client's entry */
4932 target_client = silc_idlist_find_client_by_id(server->local_list,
4933 client_id, TRUE, NULL);
4934 if (!target_client) {
4935 target_client = silc_idlist_find_client_by_id(server->global_list,
4936 client_id, TRUE, NULL);
4939 /* Check whether target client is on the channel */
4940 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4941 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4942 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL,
4947 /* Check that the target client is not channel founder. Channel founder
4948 cannot be kicked from the channel. */
4949 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4950 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4951 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
4958 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4962 /* Send command reply to sender */
4963 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4966 /* Send KICKED notify to local clients on the channel */
4967 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4968 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4969 SILC_NOTIFY_TYPE_KICKED, 3,
4970 target_idp, target_idp_len,
4971 comment, comment ? strlen(comment) : 0,
4972 idp->data, idp->len);
4973 silc_buffer_free(idp);
4975 /* Send KICKED notify to primary route */
4976 silc_server_send_notify_kicked(server, SILC_PRIMARY_ROUTE(server),
4977 SILC_BROADCAST(server), channel,
4978 target_client->id, client->id, comment);
4980 /* Remove the client from the channel. If the channel does not exist
4981 after removing the client then the client kicked itself off the channel
4982 and we don't have to send anything after that. */
4983 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4984 target_client, FALSE))
4987 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4988 /* Re-generate channel key */
4989 if (!silc_server_create_channel_key(server, channel, 0))
4992 /* Send the channel key to the channel. The key of course is not sent
4993 to the client who was kicked off the channel. */
4994 silc_server_send_channel_key(server, target_client->connection, channel,
4995 server->server_type == SILC_ROUTER ?
4996 FALSE : !server->standalone);
5000 silc_server_command_free(cmd);
5003 /* Server side of OPER command. Client uses this comand to obtain server
5004 operator privileges to this server/router. */
5006 SILC_SERVER_CMD_FUNC(oper)
5008 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5009 SilcServer server = cmd->server;
5010 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5011 unsigned char *username, *auth;
5013 SilcServerConfigAdmin *admin;
5014 SilcIDListData idata = (SilcIDListData)client;
5015 bool result = FALSE;
5016 SilcPublicKey cached_key;
5018 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
5021 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
5023 /* Get the username */
5024 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5026 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
5027 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5032 /* Get the admin configuration */
5033 admin = silc_server_config_find_admin(server, cmd->sock->ip,
5034 username, client->nickname);
5036 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
5037 username, client->nickname);
5039 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
5040 SILC_STATUS_ERR_AUTH_FAILED,
5046 /* Get the authentication payload */
5047 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5049 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
5050 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5055 /* Verify the authentication data. If both passphrase and public key
5056 is set then try both of them. */
5057 if (admin->passphrase)
5058 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
5059 admin->passphrase, admin->passphrase_len,
5060 idata->hash, client->id, SILC_ID_CLIENT);
5061 if (!result && admin->publickeys) {
5062 cached_key = silc_server_get_public_key(server, admin->publickeys);
5065 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
5066 cached_key, 0, idata->hash,
5067 client->id, SILC_ID_CLIENT);
5070 /* Authentication failed */
5071 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
5072 SILC_STATUS_ERR_AUTH_FAILED,
5077 /* Client is now server operator */
5078 client->mode |= SILC_UMODE_SERVER_OPERATOR;
5080 /* Update statistics */
5081 if (SILC_IS_LOCAL(client))
5082 server->stat.my_server_ops++;
5083 if (server->server_type == SILC_ROUTER)
5084 server->stat.server_ops++;
5086 /* Send UMODE change to primary router */
5087 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
5088 SILC_BROADCAST(server), client->id,
5091 /* Check if anyone is watching this nickname */
5092 if (server->server_type == SILC_ROUTER)
5093 silc_server_check_watcher_list(server, client, NULL,
5094 SILC_NOTIFY_TYPE_UMODE_CHANGE);
5096 /* Send reply to the sender */
5097 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
5101 silc_server_command_free(cmd);
5104 SILC_TASK_CALLBACK(silc_server_command_detach_cb)
5106 SilcServer server = app_context;
5107 QuitInternal q = (QuitInternal)context;
5108 SilcClientID *client_id = (SilcClientID *)q->sock;
5109 SilcClientEntry client;
5110 SilcSocketConnection sock;
5112 client = silc_idlist_find_client_by_id(server->local_list, client_id,
5114 if (client && client->connection) {
5115 sock = client->connection;
5117 /* If there is pending outgoing data for the client then purge it
5118 to the network before closing connection. */
5119 silc_server_packet_queue_purge(server, sock);
5121 /* Close the connection on our side */
5122 client->router = NULL;
5123 client->connection = NULL;
5124 sock->user_data = NULL;
5125 silc_server_close_connection(server, sock);
5128 silc_free(client_id);
5132 SILC_TASK_CALLBACK(silc_server_command_detach_timeout)
5134 SilcServer server = app_context;
5135 QuitInternal q = (QuitInternal)context;
5136 SilcClientID *client_id = (SilcClientID *)q->sock;
5137 SilcClientEntry client;
5139 client = silc_idlist_find_client_by_id(server->local_list, client_id,
5141 if (client && client->mode & SILC_UMODE_DETACHED) {
5142 SILC_LOG_DEBUG(("Detach timeout"));
5143 silc_server_free_client_data(server, NULL, client, TRUE,
5147 silc_free(client_id);
5151 /* Server side of DETACH command. Detached the client from the network
5152 by closing the connection but preserving the session. */
5154 SILC_SERVER_CMD_FUNC(detach)
5156 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5157 SilcServer server = cmd->server;
5158 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5161 if (server->config->detach_disabled) {
5162 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
5163 SILC_STATUS_ERR_UNKNOWN_COMMAND, 0);
5167 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
5170 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
5172 /* Remove operator privileges, since the client may resume in some
5173 other server which to it does not have operator privileges. */
5174 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
5175 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
5177 /* Send the user mode notify to notify that client is detached */
5178 client->mode |= SILC_UMODE_DETACHED;
5179 client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
5180 client->last_command = 0;
5181 client->fast_command = 0;
5182 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
5183 SILC_BROADCAST(server), client->id,
5185 server->stat.my_detached++;
5187 /* Check if anyone is watching this nickname */
5188 if (server->server_type == SILC_ROUTER)
5189 silc_server_check_watcher_list(server, client, NULL,
5190 SILC_NOTIFY_TYPE_UMODE_CHANGE);
5192 q = silc_calloc(1, sizeof(*q));
5193 q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
5194 silc_schedule_task_add(server->schedule, 0, silc_server_command_detach_cb,
5195 q, 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
5197 if (server->config->detach_timeout) {
5198 q = silc_calloc(1, sizeof(*q));
5199 q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
5200 silc_schedule_task_add(server->schedule, 0,
5201 silc_server_command_detach_timeout,
5202 q, server->config->detach_timeout * 60,
5203 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
5206 /* Send reply to the sender */
5207 silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
5211 silc_server_command_free(cmd);
5214 /* Server side of WATCH command. */
5216 SILC_SERVER_CMD_FUNC(watch)
5218 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5219 SilcServer server = cmd->server;
5220 char *add_nick, *del_nick;
5221 SilcUInt32 add_nick_len, del_nick_len, tmp_len;
5223 unsigned char hash[16], *tmp;
5224 SilcClientEntry client;
5225 SilcClientID *client_id = NULL;
5227 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WATCH, cmd, 1, 3);
5229 if (server->server_type == SILC_SERVER && !server->standalone) {
5230 if (!cmd->pending) {
5231 /* Send the command to router */
5233 SilcUInt16 old_ident;
5235 old_ident = silc_command_get_ident(cmd->payload);
5236 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5237 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5239 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5240 SILC_PACKET_COMMAND, cmd->packet->flags,
5241 tmpbuf->data, tmpbuf->len, TRUE);
5243 /* Reprocess this packet after received reply from router */
5244 silc_server_command_pending(server, SILC_COMMAND_WATCH,
5245 silc_command_get_ident(cmd->payload),
5246 silc_server_command_watch,
5247 silc_server_command_dup(cmd));
5248 cmd->pending = TRUE;
5249 silc_command_set_ident(cmd->payload, old_ident);
5250 silc_buffer_free(tmpbuf);
5251 } else if (context2) {
5252 /* Received reply from router, just send same data to the client. */
5253 SilcServerCommandReplyContext reply = context2;
5255 silc_command_get_status(reply->payload, &status, NULL);
5256 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, status,
5263 /* We are router and keep the watch list for local cell */
5265 /* Get the client ID */
5266 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5268 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5269 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5273 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
5275 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5276 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5281 /* Get the client entry which must be in local list */
5282 client = silc_idlist_find_client_by_id(server->local_list,
5283 client_id, TRUE, NULL);
5285 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5286 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5292 add_nick = silc_argument_get_arg_type(cmd->args, 2, &add_nick_len);
5293 del_nick = silc_argument_get_arg_type(cmd->args, 3, &del_nick_len);
5294 if (!add_nick && !del_nick) {
5295 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5296 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5301 if (add_nick && add_nick_len > 128)
5302 add_nick[128] = '\0';
5303 if (del_nick && del_nick_len > 128)
5304 del_nick[128] = '\0';
5306 memset(nick, 0, sizeof(nick));
5308 /* Add new nickname to be watched in our cell */
5310 if (silc_server_name_bad_chars(add_nick, strlen(add_nick)) == TRUE) {
5311 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5312 SILC_STATUS_ERR_BAD_NICKNAME, 0);
5316 /* Hash the nick, we have the hash saved, not nicks because we can
5317 do one to one mapping to the nick from Client ID hash this way. */
5318 silc_to_lower(add_nick, nick, sizeof(nick) - 1);
5319 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
5321 /* Check whether this client is already watching this nickname */
5322 if (silc_hash_table_find_by_context(server->watcher_list, hash,
5324 /* Nickname is alredy being watched for this client */
5325 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5326 SILC_STATUS_ERR_NICKNAME_IN_USE,
5331 /* Get the nickname from the watcher list and use the same key in
5332 new entries as well. If key doesn't exist then create it. */
5333 if (!silc_hash_table_find(server->watcher_list, hash, (void **)&tmp, NULL))
5334 tmp = silc_memdup(hash, CLIENTID_HASH_LEN);
5336 /* Add the client to the watcher list with the specified nickname hash. */
5337 silc_hash_table_add(server->watcher_list, tmp, client);
5340 /* Delete nickname from watch list */
5342 if (silc_server_name_bad_chars(del_nick, strlen(del_nick)) == TRUE) {
5343 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5344 SILC_STATUS_ERR_BAD_NICKNAME, 0);
5348 /* Hash the nick, we have the hash saved, not nicks because we can
5349 do one to one mapping to the nick from Client ID hash this way. */
5350 silc_to_lower(del_nick, nick, sizeof(nick) - 1);
5351 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
5353 /* Check that this client is watching for this nickname */
5354 if (!silc_hash_table_find_by_context(server->watcher_list, hash,
5355 client, (void **)&tmp)) {
5356 /* Nickname is alredy being watched for this client */
5357 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5358 SILC_STATUS_ERR_NO_SUCH_NICK, 0);
5362 /* Delete the nickname from the watcher list. */
5363 silc_hash_table_del_by_context(server->watcher_list, hash, client);
5365 /* Now check whether there still exists entries with this key, if not
5366 then free the key to not leak memory. */
5367 if (!silc_hash_table_find(server->watcher_list, hash, NULL, NULL))
5371 /* Distribute the watch list to backup routers too */
5372 if (server->backup) {
5374 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5375 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5376 silc_server_backup_send(server, NULL, SILC_PACKET_COMMAND,
5377 cmd->packet->flags, tmpbuf->data, tmpbuf->len,
5379 silc_buffer_free(tmpbuf);
5382 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5386 silc_free(client_id);
5387 silc_server_command_free(cmd);
5390 /* Server side of SILCOPER command. Client uses this comand to obtain router
5391 operator privileges to this router. */
5393 SILC_SERVER_CMD_FUNC(silcoper)
5395 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5396 SilcServer server = cmd->server;
5397 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5398 unsigned char *username, *auth;
5400 SilcServerConfigAdmin *admin;
5401 SilcIDListData idata = (SilcIDListData)client;
5402 bool result = FALSE;
5403 SilcPublicKey cached_key;
5405 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
5408 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
5410 if (server->server_type != SILC_ROUTER) {
5411 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5412 SILC_STATUS_ERR_AUTH_FAILED, 0);
5416 /* Get the username */
5417 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5419 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5420 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5425 /* Get the admin configuration */
5426 admin = silc_server_config_find_admin(server, cmd->sock->ip,
5427 username, client->nickname);
5429 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
5430 username, client->nickname);
5432 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5433 SILC_STATUS_ERR_AUTH_FAILED, 0);
5438 /* Get the authentication payload */
5439 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5441 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5442 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5447 /* Verify the authentication data. If both passphrase and public key
5448 is set then try both of them. */
5449 if (admin->passphrase)
5450 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
5451 admin->passphrase, admin->passphrase_len,
5452 idata->hash, client->id, SILC_ID_CLIENT);
5453 if (!result && admin->publickeys) {
5454 cached_key = silc_server_get_public_key(server, admin->publickeys);
5457 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
5458 cached_key, 0, idata->hash,
5459 client->id, SILC_ID_CLIENT);
5462 /* Authentication failed */
5463 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
5464 SILC_STATUS_ERR_AUTH_FAILED, 0);
5468 /* Client is now router operator */
5469 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
5471 /* Update statistics */
5472 if (SILC_IS_LOCAL(client))
5473 server->stat.my_router_ops++;
5474 if (server->server_type == SILC_ROUTER)
5475 server->stat.router_ops++;
5477 /* Send UMODE change to primary router */
5478 silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
5479 SILC_BROADCAST(server), client->id,
5482 /* Check if anyone is watching this nickname */
5483 if (server->server_type == SILC_ROUTER)
5484 silc_server_check_watcher_list(server, client, NULL,
5485 SILC_NOTIFY_TYPE_UMODE_CHANGE);
5487 /* Send reply to the sender */
5488 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5492 silc_server_command_free(cmd);
5495 /* Server side of command BAN. This is used to manage the ban list of the
5496 channel. To add clients and remove clients from the ban list. */
5498 SILC_SERVER_CMD_FUNC(ban)
5500 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5501 SilcServer server = cmd->server;
5502 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5504 SilcChannelEntry channel;
5505 SilcChannelClientEntry chl;
5506 SilcChannelID *channel_id = NULL;
5507 unsigned char *id, *add, *del;
5508 SilcUInt32 id_len, tmp_len;
5509 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5511 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
5514 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
5516 /* Get Channel ID */
5517 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
5519 channel_id = silc_id_payload_parse_id(id, id_len, NULL);
5521 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5522 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5527 /* Get channel entry. The server must know about the channel since the
5528 client is expected to be on the channel. */
5529 channel = silc_idlist_find_channel_by_id(server->local_list,
5532 channel = silc_idlist_find_channel_by_id(server->global_list,
5535 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5536 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5542 /* Check whether this client is on the channel */
5543 if (!silc_server_client_on_channel(client, channel, &chl)) {
5544 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5545 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5549 /* The client must be at least channel operator. */
5550 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
5551 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5552 SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
5556 /* Get the new ban and add it to the ban list */
5557 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5559 if (!channel->ban_list)
5560 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
5562 channel->ban_list = silc_realloc(channel->ban_list,
5563 sizeof(*channel->ban_list) *
5565 strlen(channel->ban_list) + 2));
5566 if (add[tmp_len - 1] == ',')
5567 add[tmp_len - 1] = '\0';
5569 strncat(channel->ban_list, add, tmp_len);
5570 strncat(channel->ban_list, ",", 1);
5573 /* Get the ban to be removed and remove it from the list */
5574 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
5575 if (del && channel->ban_list) {
5576 char *start, *end, *n;
5578 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
5579 silc_free(channel->ban_list);
5580 channel->ban_list = NULL;
5582 start = strstr(channel->ban_list, del);
5583 if (start && strlen(start) >= tmp_len) {
5584 end = start + tmp_len;
5585 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
5586 strncat(n, channel->ban_list, start - channel->ban_list);
5587 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
5589 silc_free(channel->ban_list);
5590 channel->ban_list = n;
5595 /* Send the BAN notify type to our primary router. */
5597 silc_server_send_notify_ban(server, SILC_PRIMARY_ROUTE(server),
5598 SILC_BROADCAST(server), channel, add, del);
5600 /* Send the reply back to the client */
5602 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
5603 SILC_STATUS_OK, 0, ident, 2,
5605 3, channel->ban_list,
5607 strlen(channel->ban_list) -1 : 0);
5608 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5609 packet->data, packet->len, FALSE);
5611 silc_buffer_free(packet);
5614 silc_free(channel_id);
5615 silc_server_command_free(cmd);
5618 /* Server side command of LEAVE. Removes client from a channel. */
5620 SILC_SERVER_CMD_FUNC(leave)
5622 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5623 SilcServer server = cmd->server;
5624 SilcSocketConnection sock = cmd->sock;
5625 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
5626 SilcChannelID *id = NULL;
5627 SilcChannelEntry channel;
5631 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !id_entry)
5634 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
5636 /* Get Channel ID */
5637 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
5639 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5640 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5643 id = silc_id_payload_parse_id(tmp, len, NULL);
5645 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5646 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5650 /* Get channel entry */
5651 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5653 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5655 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5656 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5662 /* Check whether this client is on the channel */
5663 if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
5664 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5665 SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5669 /* Notify routers that they should remove this client from their list
5670 of clients on the channel. Send LEAVE notify type. */
5671 silc_server_send_notify_leave(server, SILC_PRIMARY_ROUTE(server),
5672 SILC_BROADCAST(server), channel, id_entry->id);
5674 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
5675 SILC_STATUS_OK, 0, 2, tmp, len);
5677 /* Remove client from channel */
5678 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5680 /* If the channel does not exist anymore we won't send anything */
5683 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5684 /* Re-generate channel key */
5685 if (!silc_server_create_channel_key(server, channel, 0))
5688 /* Send the channel key */
5689 silc_server_send_channel_key(server, NULL, channel,
5690 server->server_type == SILC_ROUTER ?
5691 FALSE : !server->standalone);
5696 silc_server_command_free(cmd);
5699 /* Server side of command USERS. Resolves clients and their USERS currently
5700 joined on the requested channel. The list of Client ID's and their modes
5701 on the channel is sent back. */
5703 SILC_SERVER_CMD_FUNC(users)
5705 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5706 SilcServer server = cmd->server;
5707 SilcChannelEntry channel;
5708 SilcChannelID *id = NULL;
5709 SilcBuffer packet, idp;
5710 unsigned char *channel_id;
5711 SilcUInt32 channel_id_len;
5712 SilcBuffer client_id_list;
5713 SilcBuffer client_mode_list;
5714 unsigned char lc[4];
5715 SilcUInt32 list_count = 0;
5716 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5719 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5721 /* Get Channel ID */
5722 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5724 /* Get channel name */
5725 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5727 if (!channel_id && !channel_name) {
5728 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5729 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5734 id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
5736 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5737 SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5742 /* If we are server and we don't know about this channel we will send
5743 the command to our router. If we know about the channel then we also
5744 have the list of users already. */
5746 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5748 channel = silc_idlist_find_channel_by_name(server->local_list,
5749 channel_name, NULL);
5751 if (!channel || (!server->standalone && (channel->disabled ||
5752 !channel->users_resolved))) {
5753 if (server->server_type != SILC_ROUTER && !server->standalone &&
5757 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5758 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5760 /* Send USERS command */
5761 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5762 SILC_PACKET_COMMAND, cmd->packet->flags,
5763 tmpbuf->data, tmpbuf->len, TRUE);
5765 /* Reprocess this packet after received reply */
5766 silc_server_command_pending(server, SILC_COMMAND_USERS,
5767 silc_command_get_ident(cmd->payload),
5768 silc_server_command_users,
5769 silc_server_command_dup(cmd));
5770 cmd->pending = TRUE;
5771 silc_command_set_ident(cmd->payload, ident);
5772 silc_buffer_free(tmpbuf);
5777 /* Check the global list as well. */
5779 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5781 channel = silc_idlist_find_channel_by_name(server->global_list,
5782 channel_name, NULL);
5784 /* Channel really does not exist */
5785 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5786 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5792 /* If the channel is private or secret do not send anything, unless the
5793 user requesting this command is on the channel or is server */
5794 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5795 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5796 && !silc_server_client_on_channel(cmd->sock->user_data, channel,
5798 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5799 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5805 /* Get the users list */
5806 if (!silc_server_get_users_on_channel(server, channel, &client_id_list,
5807 &client_mode_list, &list_count)) {
5809 client_id_list = NULL;
5810 client_mode_list = NULL;
5814 SILC_PUT32_MSB(list_count, lc);
5817 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5818 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5819 SILC_STATUS_OK, 0, ident, 4,
5820 2, idp->data, idp->len,
5823 client_id_list->data : NULL,
5825 client_id_list->len : 0,
5826 5, client_mode_list ?
5827 client_mode_list->data : NULL,
5829 client_mode_list->len : 0);
5830 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5831 packet->data, packet->len, FALSE);
5833 silc_buffer_free(idp);
5834 silc_buffer_free(packet);
5836 silc_buffer_free(client_id_list);
5837 if (client_mode_list)
5838 silc_buffer_free(client_mode_list);
5842 silc_server_command_free(cmd);
5845 /* Server side of command GETKEY. This fetches the client's public key
5846 from the server where to the client is connected. */
5848 SILC_SERVER_CMD_FUNC(getkey)
5850 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5851 SilcServer server = cmd->server;
5853 SilcClientEntry client;
5854 SilcServerEntry server_entry;
5855 SilcClientID *client_id = NULL;
5856 SilcServerID *server_id = NULL;
5857 SilcIDPayload idp = NULL;
5858 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5859 unsigned char *tmp, *pkdata;
5860 SilcUInt32 tmp_len, pklen;
5861 SilcBuffer pk = NULL;
5863 SilcPublicKey public_key;
5865 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5867 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5868 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5872 idp = silc_id_payload_parse(tmp, tmp_len);
5874 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5875 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5880 id_type = silc_id_payload_get_type(idp);
5881 if (id_type == SILC_ID_CLIENT) {
5882 client_id = silc_id_payload_get_id(idp);
5884 /* If the client is not found from local list there is no chance it
5885 would be locally connected client so send the command further. */
5886 client = silc_idlist_find_client_by_id(server->local_list,
5887 client_id, TRUE, NULL);
5889 client = silc_idlist_find_client_by_id(server->global_list,
5890 client_id, TRUE, NULL);
5892 if ((!client && !cmd->pending && !server->standalone) ||
5893 (client && !client->connection && !cmd->pending &&
5894 !(client->mode & SILC_UMODE_DETACHED)) ||
5895 (client && !client->data.public_key && !cmd->pending)) {
5897 SilcUInt16 old_ident;
5898 SilcSocketConnection dest_sock;
5900 dest_sock = silc_server_get_client_route(server, NULL, 0,
5901 client_id, NULL, NULL);
5905 old_ident = silc_command_get_ident(cmd->payload);
5906 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5907 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5909 silc_server_packet_send(server, dest_sock,
5910 SILC_PACKET_COMMAND, cmd->packet->flags,
5911 tmpbuf->data, tmpbuf->len, TRUE);
5913 /* Reprocess this packet after received reply from router */
5914 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5915 silc_command_get_ident(cmd->payload),
5916 silc_server_command_getkey,
5917 silc_server_command_dup(cmd));
5918 cmd->pending = TRUE;
5919 silc_command_set_ident(cmd->payload, old_ident);
5920 silc_buffer_free(tmpbuf);
5925 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5926 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5931 /* The client is locally connected, just get the public key and
5932 send it back. If they key does not exist then do not send it,
5933 send just OK reply */
5934 public_key = client->data.public_key;
5939 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5940 pk = silc_buffer_alloc(4 + tmp_len);
5941 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5942 silc_buffer_format(pk,
5943 SILC_STR_UI_SHORT(tmp_len),
5944 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5945 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5951 } else if (id_type == SILC_ID_SERVER) {
5952 server_id = silc_id_payload_get_id(idp);
5954 /* If the server is not found from local list there is no chance it
5955 would be locally connected server so send the command further. */
5956 server_entry = silc_idlist_find_server_by_id(server->local_list,
5957 server_id, TRUE, NULL);
5959 server_entry = silc_idlist_find_server_by_id(server->global_list,
5960 server_id, TRUE, NULL);
5962 if (server_entry != server->id_entry &&
5963 ((!server_entry && !cmd->pending && !server->standalone) ||
5964 (server_entry && !server_entry->connection && !cmd->pending &&
5965 !server->standalone) ||
5966 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5967 !server->standalone))) {
5969 SilcUInt16 old_ident;
5971 old_ident = silc_command_get_ident(cmd->payload);
5972 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5973 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5975 silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5976 SILC_PACKET_COMMAND, cmd->packet->flags,
5977 tmpbuf->data, tmpbuf->len, TRUE);
5979 /* Reprocess this packet after received reply from router */
5980 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5981 silc_command_get_ident(cmd->payload),
5982 silc_server_command_getkey,
5983 silc_server_command_dup(cmd));
5984 cmd->pending = TRUE;
5985 silc_command_set_ident(cmd->payload, old_ident);
5986 silc_buffer_free(tmpbuf);
5990 if (!server_entry) {
5991 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5992 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
5997 /* If they key does not exist then do not send it, send just OK reply */
5998 public_key = (!server_entry->data.public_key ?
5999 (server_entry == server->id_entry ? server->public_key :
6000 NULL) : server_entry->data.public_key);
6005 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
6006 pk = silc_buffer_alloc(4 + tmp_len);
6007 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
6008 silc_buffer_format(pk,
6009 SILC_STR_UI_SHORT(tmp_len),
6010 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
6011 SILC_STR_UI_XNSTRING(tmp, tmp_len),
6021 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
6022 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
6023 SILC_STATUS_OK, 0, ident,
6027 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
6028 packet->data, packet->len, FALSE);
6029 silc_buffer_free(packet);
6032 silc_buffer_free(pk);
6036 silc_id_payload_free(idp);
6037 silc_free(client_id);
6038 silc_free(server_id);
6039 silc_server_command_free(cmd);
6043 /* Private range commands, specific to this implementation */
6045 /* Server side command of CONNECT. Connects us to the specified remote
6046 server or router. */
6048 SILC_SERVER_CMD_FUNC(connect)
6050 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
6051 SilcServer server = cmd->server;
6052 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
6053 unsigned char *tmp, *host;
6055 SilcUInt32 port = SILC_PORT;
6057 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
6060 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
6062 /* Check whether client has the permissions. */
6063 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
6064 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
6065 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
6066 SILC_STATUS_ERR_NO_SERVER_PRIV, 0);
6070 if (server->server_type == SILC_ROUTER &&
6071 client->mode & SILC_UMODE_SERVER_OPERATOR) {
6072 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
6073 SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
6077 /* Get the remote server */
6078 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
6080 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
6081 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
6087 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
6089 SILC_GET32_MSB(port, tmp);
6091 /* Create the connection. It is done with timeout and is async. */
6092 silc_server_create_connection(server, host, port);
6094 /* Send reply to the sender */
6095 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
6099 silc_server_command_free(cmd);
6102 /* Server side command of CLOSE. Closes connection to a specified server. */
6104 SILC_SERVER_CMD_FUNC(close)
6106 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
6107 SilcServer server = cmd->server;
6108 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
6109 SilcServerEntry server_entry;
6110 SilcSocketConnection sock;
6113 unsigned char *name;
6114 SilcUInt32 port = SILC_PORT;
6116 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
6119 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
6121 /* Check whether client has the permissions. */
6122 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
6123 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
6124 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
6125 SILC_STATUS_ERR_NO_SERVER_PRIV,
6130 /* Get the remote server */
6131 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
6133 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
6134 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
6140 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
6142 SILC_GET32_MSB(port, tmp);
6144 server_entry = silc_idlist_find_server_by_conn(server->local_list,
6145 name, port, FALSE, NULL);
6147 server_entry = silc_idlist_find_server_by_conn(server->global_list,
6148 name, port, FALSE, NULL);
6149 if (!server_entry) {
6150 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
6151 SILC_STATUS_ERR_NO_SERVER_ID, 0);
6155 if (server_entry == server->id_entry) {
6156 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
6157 SILC_STATUS_ERR_NO_SERVER_ID, 0);
6161 /* Send reply to the sender */
6162 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
6165 /* Close the connection to the server */
6166 sock = (SilcSocketConnection)server_entry->connection;
6168 /* If we shutdown primary router connection manually then don't trigger
6169 any reconnect or backup router connections, by setting the router
6171 if (server->router == server_entry) {
6172 server->id_entry->router = NULL;
6173 server->router = NULL;
6174 server->standalone = TRUE;
6176 silc_server_free_sock_user_data(server, sock, NULL);
6177 silc_server_close_connection(server, sock);
6180 silc_server_command_free(cmd);
6183 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
6184 active connections. */
6186 SILC_SERVER_CMD_FUNC(shutdown)
6188 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
6189 SilcServer server = cmd->server;
6190 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
6192 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
6195 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
6197 /* Check whether client has the permission. */
6198 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
6199 !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
6200 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
6201 SILC_STATUS_ERR_NO_SERVER_PRIV,
6206 /* Send reply to the sender */
6207 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
6210 /* Then, gracefully, or not, bring the server down. */
6211 silc_server_stop(server);
6215 silc_server_command_free(cmd);