5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2002 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
22 #include "serverincludes.h"
23 #include "server_internal.h"
25 static int silc_server_is_registered(SilcServer server,
26 SilcSocketConnection sock,
27 SilcServerCommandContext cmd,
30 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
32 SilcCommandStatus status);
34 silc_server_command_send_status_data(SilcServerCommandContext cmd,
36 SilcCommandStatus status,
38 const unsigned char *arg,
41 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
42 SilcServerCommandReplyContext cmdr,
44 SILC_TASK_CALLBACK(silc_server_command_process_timeout);
46 /* Server command list. */
47 SilcServerCommand silc_command_list[] =
49 SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
50 SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
51 SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
52 SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
53 SILC_SERVER_CMD(list, LIST, SILC_CF_LAG_STRICT | SILC_CF_REG),
54 SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
55 SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
56 SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
57 SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG_STRICT | SILC_CF_REG | SILC_CF_OPER),
58 SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
59 SILC_SERVER_CMD(stats, STATS, SILC_CF_LAG | SILC_CF_REG),
60 SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
61 SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
62 SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG_STRICT | SILC_CF_REG),
63 SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
64 SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
65 SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG_STRICT | SILC_CF_REG),
66 SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
67 SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
68 SILC_SERVER_CMD(ban, BAN, SILC_CF_LAG_STRICT | SILC_CF_REG),
69 SILC_SERVER_CMD(silcoper, SILCOPER,
70 SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
71 SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
72 SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
73 SILC_SERVER_CMD(getkey, GETKEY, SILC_CF_LAG | SILC_CF_REG),
75 SILC_SERVER_CMD(connect, PRIV_CONNECT,
76 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
77 SILC_SERVER_CMD(close, PRIV_CLOSE,
78 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
79 SILC_SERVER_CMD(shutdown, PRIV_SHUTDOWN, SILC_CF_LAG | SILC_CF_REG |
85 /* Performs several checks to the command. It first checks whether this
86 command was called as pending command callback. If it was then it checks
87 whether error occurred in the command reply where the pending command
90 It also checks that the requested command includes correct amount
92 #define SILC_SERVER_COMMAND_CHECK(command, context, min, max) \
96 SILC_LOG_DEBUG(("Start")); \
98 if (silc_server_command_pending_error_check(cmd, context2, command)) { \
99 silc_server_command_free(cmd); \
103 _argc = silc_argument_get_arg_num(cmd->args); \
105 silc_server_command_send_status_reply(cmd, command, \
106 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
107 silc_server_command_free(cmd); \
111 silc_server_command_send_status_reply(cmd, command, \
112 SILC_STATUS_ERR_TOO_MANY_PARAMS); \
113 silc_server_command_free(cmd); \
118 /* Returns TRUE if the connection is registered. Unregistered connections
119 usually cannot send commands hence the check. */
121 static int silc_server_is_registered(SilcServer server,
122 SilcSocketConnection sock,
123 SilcServerCommandContext cmd,
126 SilcIDListData idata = (SilcIDListData)sock->user_data;
131 if (idata->status & SILC_IDLIST_STATUS_REGISTERED)
134 silc_server_command_send_status_reply(cmd, command,
135 SILC_STATUS_ERR_NOT_REGISTERED);
139 /* Internal context to hold data when executed command with timeout. */
141 SilcServerCommandContext ctx;
142 SilcServerCommand *cmd;
143 } *SilcServerCommandTimeout;
145 /* Timeout callback to process commands with timeout for client. Client's
146 commands are always executed with timeout. */
148 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
150 SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
151 SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data;
154 silc_server_command_free(timeout->ctx);
158 /* Update access time */
159 client->last_command = time(NULL);
161 if (!(timeout->cmd->flags & SILC_CF_REG))
162 timeout->cmd->cb(timeout->ctx, NULL);
163 else if (silc_server_is_registered(timeout->ctx->server,
167 timeout->cmd->cb(timeout->ctx, NULL);
169 silc_server_command_free(timeout->ctx);
174 /* Processes received command packet. */
176 void silc_server_command_process(SilcServer server,
177 SilcSocketConnection sock,
178 SilcPacketContext *packet)
180 SilcServerCommandContext ctx;
181 SilcServerCommand *cmd;
184 /* Allocate command context. This must be free'd by the
185 command routine receiving it. */
186 ctx = silc_server_command_alloc();
187 ctx->server = server;
188 ctx->sock = silc_socket_dup(sock);
189 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
191 /* Parse the command payload in the packet */
192 ctx->payload = silc_command_payload_parse(packet->buffer->data,
193 packet->buffer->len);
195 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
196 silc_buffer_free(packet->buffer);
197 silc_packet_context_free(packet);
198 silc_socket_free(ctx->sock);
202 ctx->args = silc_command_get_args(ctx->payload);
204 /* Get the command */
205 command = silc_command_get(ctx->payload);
206 for (cmd = silc_command_list; cmd->cb; cmd++)
207 if (cmd->cmd == command)
210 if (!cmd || !cmd->cb) {
211 silc_server_command_send_status_reply(ctx, command,
212 SILC_STATUS_ERR_UNKNOWN_COMMAND);
213 silc_server_command_free(ctx);
217 /* Execute client's commands always with timeout. Normally they are
218 executed with zero (0) timeout but if client is sending command more
219 frequently than once in 2 seconds, then the timeout may be 0 to 2
221 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
222 SilcClientEntry client = (SilcClientEntry)sock->user_data;
223 SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
229 if (client->last_command && (time(NULL) - client->last_command) < 2) {
230 client->fast_command++;
233 client->fast_command = ((client->fast_command - 1) <= 0 ? 0 :
234 client->fast_command--);
238 if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
239 (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
240 silc_schedule_task_add(server->schedule, sock->sock,
241 silc_server_command_process_timeout,
243 2 - (time(NULL) - client->last_command), 0,
244 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
246 silc_schedule_task_add(server->schedule, sock->sock,
247 silc_server_command_process_timeout,
248 (void *)timeout, 0, 1,
249 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
253 /* Execute for server */
255 if (!(cmd->flags & SILC_CF_REG))
257 else if (silc_server_is_registered(server, sock, ctx, cmd->cmd))
260 silc_server_command_free(ctx);
263 /* Allocate Command Context */
265 SilcServerCommandContext silc_server_command_alloc()
267 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
272 /* Free's the command context allocated before executing the command */
274 void silc_server_command_free(SilcServerCommandContext ctx)
277 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
279 if (ctx->users < 1) {
281 silc_command_payload_free(ctx->payload);
283 silc_packet_context_free(ctx->packet);
285 silc_socket_free(ctx->sock); /* Decrease reference counter */
290 /* Duplicate Command Context by adding reference counter. The context won't
291 be free'd untill it hits zero. */
293 SilcServerCommandContext
294 silc_server_command_dup(SilcServerCommandContext ctx)
297 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
302 /* Add new pending command to be executed when reply to a command has been
303 received. The `reply_cmd' is the command that will call the `callback'
304 with `context' when reply has been received. It can be SILC_COMMAND_NONE
305 to match any command with the `ident'. If `ident' is non-zero
306 the `callback' will be executed when received reply with command
307 identifier `ident'. If there already exists pending command for the
308 specified command, ident, callback and context this function has no
311 bool silc_server_command_pending(SilcServer server,
312 SilcCommand reply_cmd,
314 SilcCommandCb callback,
317 SilcServerCommandPending *reply;
319 /* Check whether identical pending already exists for same command,
320 ident, callback and callback context. If it does then it would be
321 error to register it again. */
322 silc_dlist_start(server->pending_commands);
323 while ((reply = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
324 if (reply->reply_cmd == reply_cmd && reply->ident == ident &&
325 reply->callback == callback && reply->context == context)
329 reply = silc_calloc(1, sizeof(*reply));
330 reply->reply_cmd = reply_cmd;
331 reply->ident = ident;
332 reply->context = context;
333 reply->callback = callback;
334 silc_dlist_add(server->pending_commands, reply);
339 /* Deletes pending command by reply command type. */
341 void silc_server_command_pending_del(SilcServer server,
342 SilcCommand reply_cmd,
345 SilcServerCommandPending *r;
347 silc_dlist_start(server->pending_commands);
348 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
349 if (r->reply_cmd == reply_cmd && r->ident == ident) {
350 silc_dlist_del(server->pending_commands, r);
356 /* Checks for pending commands and marks callbacks to be called from
357 the command reply function. Returns TRUE if there were pending command. */
359 SilcServerCommandPendingCallbacks
360 silc_server_command_pending_check(SilcServer server,
361 SilcServerCommandReplyContext ctx,
364 SilcUInt32 *callbacks_count)
366 SilcServerCommandPending *r;
367 SilcServerCommandPendingCallbacks callbacks = NULL;
370 silc_dlist_start(server->pending_commands);
371 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
372 if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE)
373 && r->ident == ident) {
374 callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
375 callbacks[i].context = r->context;
376 callbacks[i].callback = r->callback;
382 *callbacks_count = i;
386 /* Sends simple status message as command reply packet */
389 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
391 SilcCommandStatus status)
395 SILC_LOG_DEBUG(("Sending command status %d", status));
398 silc_command_reply_payload_encode_va(command, status,
399 silc_command_get_ident(cmd->payload),
401 silc_server_packet_send(cmd->server, cmd->sock,
402 SILC_PACKET_COMMAND_REPLY, 0,
403 buffer->data, buffer->len, FALSE);
404 silc_buffer_free(buffer);
407 /* Sends command status reply with one extra argument. The argument
408 type must be sent as argument. */
411 silc_server_command_send_status_data(SilcServerCommandContext cmd,
413 SilcCommandStatus status,
415 const unsigned char *arg,
420 SILC_LOG_DEBUG(("Sending command status %d", status));
423 silc_command_reply_payload_encode_va(command, status,
424 silc_command_get_ident(cmd->payload),
425 1, arg_type, arg, arg_len);
426 silc_server_packet_send(cmd->server, cmd->sock,
427 SILC_PACKET_COMMAND_REPLY, 0,
428 buffer->data, buffer->len, FALSE);
429 silc_buffer_free(buffer);
432 /* This function can be called to check whether in the command reply
433 an error occurred. This function has no effect if this is called
434 when the command function was not called as pending command callback.
435 This returns TRUE if error had occurred. */
438 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
439 SilcServerCommandReplyContext cmdr,
442 SilcCommandStatus status;
444 if (!cmd->pending || !cmdr)
447 SILC_GET16_MSB(status, silc_argument_get_arg_type(cmdr->args, 1, NULL));
448 if (status != SILC_STATUS_OK &&
449 status != SILC_STATUS_LIST_START &&
450 status != SILC_STATUS_LIST_ITEM &&
451 status != SILC_STATUS_LIST_END) {
454 /* Send the same command reply payload */
455 silc_command_set_ident(cmdr->payload,
456 silc_command_get_ident(cmd->payload));
457 buffer = silc_command_payload_encode_payload(cmdr->payload);
458 silc_server_packet_send(cmd->server, cmd->sock,
459 SILC_PACKET_COMMAND_REPLY, 0,
460 buffer->data, buffer->len, FALSE);
461 silc_buffer_free(buffer);
468 /******************************************************************************
472 ******************************************************************************/
475 silc_server_command_whois_parse(SilcServerCommandContext cmd,
476 SilcClientID ***client_id,
477 SilcUInt32 *client_id_count,
485 SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
488 /* If client ID is in the command it must be used instead of nickname */
489 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
491 /* No ID, get the nickname@server string and parse it. */
492 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
494 silc_parse_userfqdn(tmp, nickname, server_name);
496 silc_server_command_send_status_reply(cmd, command,
497 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
501 /* Command includes ID, we must use that. Also check whether the command
502 has more than one ID set - take them all. */
504 *client_id = silc_calloc(1, sizeof(**client_id));
505 (*client_id)[0] = silc_id_payload_parse_id(tmp, len, NULL);
506 if ((*client_id)[0] == NULL) {
507 silc_free(*client_id);
508 silc_server_command_send_status_reply(cmd, command,
509 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
512 *client_id_count = 1;
514 /* Take all ID's from the command packet */
516 for (k = 1, i = 1; i < argc; i++) {
517 tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
519 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
520 (*client_id_count + 1));
521 (*client_id)[k] = silc_id_payload_parse_id(tmp, len, NULL);
522 if ((*client_id)[k] == NULL) {
523 /* Cleanup all and fail */
524 for (i = 0; i < *client_id_count; i++)
525 silc_free((*client_id)[i]);
526 silc_free(*client_id);
527 silc_server_command_send_status_reply(
529 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
532 (*client_id_count)++;
539 /* Get the max count of reply messages allowed */
540 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
549 /* Resolve context used by both WHOIS and IDENTIFY commands */
551 SilcServerEntry router;
553 unsigned char **res_argv;
554 SilcUInt32 *res_argv_lens;
555 SilcUInt32 *res_argv_types;
557 } *SilcServerResolveContext;
560 silc_server_command_whois_check(SilcServerCommandContext cmd,
561 SilcClientEntry *clients,
562 SilcUInt32 clients_count)
564 SilcServer server = cmd->server;
565 SilcClientEntry entry;
566 SilcServerResolveContext resolve = NULL, r = NULL;
567 SilcUInt32 resolve_count = 0;
571 SILC_LOG_DEBUG(("Start"));
573 for (i = 0; i < clients_count; i++) {
578 if ((entry->nickname && entry->username && entry->userinfo) ||
579 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
583 /* If we are normal server, and we've not resolved this client from
584 router and it is global client, we'll check whether it is on some
585 channel. If not then we cannot be sure about its validity, and
586 we'll resolve it from router. */
587 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
588 entry->connection || silc_hash_table_count(entry->channels))
592 /* We need to resolve this entry since it is not complete */
594 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
595 /* The entry is being resolved (and we are not the resolver) so attach
596 to the command reply and we're done with this one. */
597 silc_server_command_pending(server, SILC_COMMAND_NONE,
598 entry->resolve_cmd_ident,
599 silc_server_command_whois,
600 silc_server_command_dup(cmd));
603 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
604 /* We've resolved this and it still is not ready. We'll return
605 and are that this will be handled again after it is resolved. */
606 for (i = 0; i < resolve_count; i++) {
607 for (k = 0; k < r->res_argc; k++)
608 silc_free(r->res_argv[k]);
609 silc_free(r->res_argv);
610 silc_free(r->res_argv_lens);
611 silc_free(r->res_argv_types);
616 /* We'll resolve this client */
620 for (k = 0; k < resolve_count; k++) {
621 if (resolve[k].router == entry->router) {
628 resolve = silc_realloc(resolve, sizeof(*resolve) *
629 (resolve_count + 1));
630 r = &resolve[resolve_count];
631 memset(r, 0, sizeof(*r));
632 r->router = entry->router;
633 r->ident = ++server->cmd_ident;
637 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
639 r->res_argv_lens = silc_realloc(r->res_argv_lens,
640 sizeof(*r->res_argv_lens) *
642 r->res_argv_types = silc_realloc(r->res_argv_types,
643 sizeof(*r->res_argv_types) *
645 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
646 r->res_argv[r->res_argc] = silc_calloc(idp->len,
647 sizeof(**r->res_argv));
648 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
649 r->res_argv_lens[r->res_argc] = idp->len;
650 r->res_argv_types[r->res_argc] = r->res_argc + 3;
652 silc_buffer_free(idp);
654 entry->resolve_cmd_ident = r->ident;
655 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
656 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
661 /* Do the resolving */
662 for (i = 0; i < resolve_count; i++) {
667 /* Send WHOIS request. We send WHOIS since we're doing the requesting
668 now anyway so make it a good one. */
669 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
670 r->res_argc, r->res_argv,
674 silc_server_packet_send(server, r->router->connection,
675 SILC_PACKET_COMMAND, cmd->packet->flags,
676 res_cmd->data, res_cmd->len, FALSE);
678 /* Reprocess this packet after received reply */
679 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
681 silc_server_command_whois,
682 silc_server_command_dup(cmd));
685 silc_buffer_free(res_cmd);
686 for (k = 0; k < r->res_argc; k++)
687 silc_free(r->res_argv[k]);
688 silc_free(r->res_argv);
689 silc_free(r->res_argv_lens);
690 silc_free(r->res_argv_types);
699 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
700 SilcClientEntry *clients,
701 SilcUInt32 clients_count,
703 const char *nickname,
704 SilcClientID **client_ids)
706 SilcServer server = cmd->server;
708 int i, k, len, valid_count;
709 SilcBuffer packet, idp, channels;
710 SilcClientEntry entry;
711 SilcCommandStatus status;
712 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
713 char nh[256], uh[256];
714 unsigned char idle[4], mode[4];
715 unsigned char *fingerprint;
716 SilcSocketConnection hsock;
718 /* Process only valid clients and ignore those that are not registered. */
720 for (i = 0; i < clients_count; i++) {
721 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
728 /* No valid clients found, send error reply */
730 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
731 SILC_STATUS_ERR_NO_SUCH_NICK,
732 3, nickname, strlen(nickname));
733 } else if (client_ids && client_ids[0]) {
734 SilcBuffer idp = silc_id_payload_encode(client_ids[0], SILC_ID_CLIENT);
735 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
736 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
737 2, idp->data, idp->len);
738 silc_buffer_free(idp);
743 /* Start processing found clients. */
745 status = SILC_STATUS_LIST_START;
747 status = SILC_STATUS_OK;
749 for (i = 0, k = 0; i < clients_count; i++) {
755 status = SILC_STATUS_LIST_ITEM;
756 if (valid_count > 1 && k == valid_count - 1)
757 status = SILC_STATUS_LIST_END;
758 if (count && k - 1 == count)
759 status = SILC_STATUS_LIST_END;
761 /* Send WHOIS reply */
762 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
763 tmp = silc_argument_get_first_arg(cmd->args, NULL);
765 memset(uh, 0, sizeof(uh));
766 memset(nh, 0, sizeof(nh));
767 memset(idle, 0, sizeof(idle));
769 strncat(nh, entry->nickname, strlen(entry->nickname));
770 if (!strchr(entry->nickname, '@')) {
772 if (entry->servername) {
773 strncat(nh, entry->servername, strlen(entry->servername));
775 len = entry->router ? strlen(entry->router->server_name) :
776 strlen(server->server_name);
777 strncat(nh, entry->router ? entry->router->server_name :
778 server->server_name, len);
782 strncat(uh, entry->username, strlen(entry->username));
783 if (!strchr(entry->username, '@')) {
785 hsock = (SilcSocketConnection)entry->connection;
786 len = strlen(hsock->hostname);
787 strncat(uh, hsock->hostname, len);
790 channels = silc_server_get_client_channel_list(server, entry);
792 if (entry->data.fingerprint[0] != 0 && entry->data.fingerprint[1] != 0)
793 fingerprint = entry->data.fingerprint;
797 SILC_PUT32_MSB(entry->mode, mode);
799 if (entry->connection) {
800 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
804 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
806 2, idp->data, idp->len,
810 strlen(entry->userinfo),
811 6, channels ? channels->data : NULL,
812 channels ? channels->len : 0,
816 fingerprint ? 20 : 0);
818 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
819 0, packet->data, packet->len, FALSE);
821 silc_buffer_free(packet);
822 silc_buffer_free(idp);
824 silc_buffer_free(channels);
831 silc_server_command_whois_send_router(SilcServerCommandContext cmd)
833 SilcServer server = cmd->server;
835 SilcUInt16 old_ident;
837 old_ident = silc_command_get_ident(cmd->payload);
838 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
839 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
841 /* Send WHOIS command to our router */
842 silc_server_packet_send(server, (SilcSocketConnection)
843 server->router->connection,
844 SILC_PACKET_COMMAND, cmd->packet->flags,
845 tmpbuf->data, tmpbuf->len, TRUE);
847 /* Reprocess this packet after received reply from router */
848 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
849 silc_command_get_ident(cmd->payload),
850 silc_server_command_whois,
851 silc_server_command_dup(cmd));
853 silc_command_set_ident(cmd->payload, old_ident);
854 silc_buffer_free(tmpbuf);
858 silc_server_command_whois_process(SilcServerCommandContext cmd)
860 SilcServer server = cmd->server;
861 char *nick = NULL, *server_name = NULL;
863 SilcClientEntry *clients = NULL, entry;
864 SilcClientID **client_id = NULL;
865 SilcUInt32 client_id_count = 0, clients_count = 0;
867 bool check_global = FALSE;
869 /* Parse the whois request */
870 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
871 &nick, &server_name, &count,
875 /* Send the WHOIS request to the router only if it included nickname.
876 Since nicknames can be expanded into many clients we need to send it
877 to router. If the WHOIS included only client ID's we will check them
878 first locally since we just might have them. */
879 if (nick && !client_id_count && cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
880 server->server_type == SILC_SERVER && !cmd->pending &&
881 !server->standalone) {
882 silc_server_command_whois_send_router(cmd);
887 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
889 else if (server->server_type != SILC_SERVER)
892 /* Get all clients matching that ID or nickname from local list */
893 if (client_id_count) {
894 /* Check all Client ID's received in the command packet */
895 for (i = 0; i < client_id_count; i++) {
896 entry = silc_idlist_find_client_by_id(server->local_list,
897 client_id[i], TRUE, NULL);
898 if (!entry && check_global)
899 entry = silc_idlist_find_client_by_id(server->global_list,
900 client_id[i], TRUE, NULL);
902 clients = silc_realloc(clients, sizeof(*clients) *
903 (clients_count + 1));
904 clients[clients_count++] = entry;
906 /* If we are normal server and did not send the request first to router
907 do it now, since we do not have the Client ID information. */
908 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
909 server->server_type == SILC_SERVER && !cmd->pending &&
910 !server->standalone) {
911 silc_server_command_whois_send_router(cmd);
918 /* Find by nickname */
919 if (!silc_idlist_get_clients_by_hash(server->local_list,
920 nick, server->md5hash,
921 &clients, &clients_count))
922 silc_idlist_get_clients_by_nickname(server->local_list,
924 &clients, &clients_count);
926 if (!silc_idlist_get_clients_by_hash(server->global_list,
927 nick, server->md5hash,
928 &clients, &clients_count))
929 silc_idlist_get_clients_by_nickname(server->global_list,
931 &clients, &clients_count);
936 /* If we are normal server and did not send the request first to router
937 do it now, since we do not have the information. */
938 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
939 server->server_type == SILC_SERVER && !cmd->pending &&
940 !server->standalone) {
941 silc_server_command_whois_send_router(cmd);
946 /* Such client(s) really does not exist in the SILC network. */
947 if (!client_id_count) {
948 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
949 SILC_STATUS_ERR_NO_SUCH_NICK,
950 3, nick, strlen(nick));
952 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
953 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
954 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
955 2, idp->data, idp->len);
956 silc_buffer_free(idp);
961 /* Router always finds the client entry if it exists in the SILC network.
962 However, it might be incomplete entry and does not include all the
963 mandatory fields that WHOIS command reply requires. Check for these and
964 make query from the server who owns the client if some fields are
966 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
971 /* Send the command reply */
972 silc_server_command_whois_send_reply(cmd, clients, clients_count,
973 count, nick, client_id);
976 if (client_id_count) {
977 for (i = 0; i < client_id_count; i++)
978 silc_free(client_id[i]);
979 silc_free(client_id);
983 silc_free(server_name);
988 /* Server side of command WHOIS. Processes user's query and sends found
989 results as command replies back to the client. */
991 SILC_SERVER_CMD_FUNC(whois)
993 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
996 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 3328);
998 ret = silc_server_command_whois_process(cmd);
999 silc_server_command_free(cmd);
1002 /******************************************************************************
1006 ******************************************************************************/
1009 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
1017 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1019 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
1020 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1024 /* Get the nickname@server string and parse it. */
1025 silc_parse_userfqdn(tmp, nickname, server_name);
1027 /* Get the max count of reply messages allowed */
1028 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1038 silc_server_command_whowas_check(SilcServerCommandContext cmd,
1039 SilcClientEntry *clients,
1040 SilcUInt32 clients_count)
1042 SilcServer server = cmd->server;
1044 SilcClientEntry entry;
1046 for (i = 0; i < clients_count; i++) {
1049 if (!entry->nickname || !entry->username) {
1051 SilcUInt16 old_ident;
1056 old_ident = silc_command_get_ident(cmd->payload);
1057 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1058 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1060 /* Send WHOWAS command */
1061 silc_server_packet_send(server, entry->router->connection,
1062 SILC_PACKET_COMMAND, cmd->packet->flags,
1063 tmpbuf->data, tmpbuf->len, TRUE);
1065 /* Reprocess this packet after received reply */
1066 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1067 silc_command_get_ident(cmd->payload),
1068 silc_server_command_whowas,
1069 silc_server_command_dup(cmd));
1070 cmd->pending = TRUE;
1071 silc_command_set_ident(cmd->payload, old_ident);
1073 silc_buffer_free(tmpbuf);
1082 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1083 SilcClientEntry *clients,
1084 SilcUInt32 clients_count)
1086 SilcServer server = cmd->server;
1088 int i, k, count = 0, len;
1089 SilcBuffer packet, idp;
1090 SilcClientEntry entry = NULL;
1091 SilcCommandStatus status;
1092 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1093 char nh[256], uh[256];
1096 status = SILC_STATUS_OK;
1098 /* Process only entries that are not registered anymore. */
1100 for (i = 0; i < clients_count; i++) {
1101 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1108 /* No valid entries found at all, just send error */
1111 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1113 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1114 SILC_STATUS_ERR_NO_SUCH_NICK,
1115 3, tmp, strlen(tmp));
1119 if (valid_count > 1)
1120 status = SILC_STATUS_LIST_START;
1122 for (i = 0, k = 0; i < clients_count; i++) {
1128 status = SILC_STATUS_LIST_ITEM;
1129 if (valid_count > 1 && k == valid_count - 1)
1130 status = SILC_STATUS_LIST_END;
1131 if (count && k - 1 == count)
1132 status = SILC_STATUS_LIST_END;
1133 if (count && k - 1 > count)
1136 /* Send WHOWAS reply */
1137 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1138 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1139 memset(uh, 0, sizeof(uh));
1140 memset(nh, 0, sizeof(nh));
1142 strncat(nh, entry->nickname, strlen(entry->nickname));
1143 if (!strchr(entry->nickname, '@')) {
1144 strncat(nh, "@", 1);
1145 if (entry->servername) {
1146 strncat(nh, entry->servername, strlen(entry->servername));
1148 len = entry->router ? strlen(entry->router->server_name) :
1149 strlen(server->server_name);
1150 strncat(nh, entry->router ? entry->router->server_name :
1151 server->server_name, len);
1155 strncat(uh, entry->username, strlen(entry->username));
1156 if (!strchr(entry->username, '@')) {
1157 strncat(uh, "@", 1);
1158 strcat(uh, "*private*");
1162 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1164 2, idp->data, idp->len,
1169 strlen(entry->userinfo) : 0);
1170 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1171 0, packet->data, packet->len, FALSE);
1173 silc_buffer_free(packet);
1174 silc_buffer_free(idp);
1181 silc_server_command_whowas_process(SilcServerCommandContext cmd)
1183 SilcServer server = cmd->server;
1184 char *nick = NULL, *server_name = NULL;
1186 SilcClientEntry *clients = NULL;
1187 SilcUInt32 clients_count = 0;
1189 bool check_global = FALSE;
1191 /* Protocol dictates that we must always send the received WHOWAS request
1192 to our router if we are normal server, so let's do it now unless we
1193 are standalone. We will not send any replies to the client until we
1194 have received reply from the router. */
1195 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1196 server->server_type == SILC_SERVER && !cmd->pending &&
1197 !server->standalone) {
1199 SilcUInt16 old_ident;
1201 old_ident = silc_command_get_ident(cmd->payload);
1202 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1203 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1205 /* Send WHOWAS command to our router */
1206 silc_server_packet_send(server, (SilcSocketConnection)
1207 server->router->connection,
1208 SILC_PACKET_COMMAND, cmd->packet->flags,
1209 tmpbuf->data, tmpbuf->len, TRUE);
1211 /* Reprocess this packet after received reply from router */
1212 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1213 silc_command_get_ident(cmd->payload),
1214 silc_server_command_whowas,
1215 silc_server_command_dup(cmd));
1216 cmd->pending = TRUE;
1217 silc_command_set_ident(cmd->payload, old_ident);
1219 silc_buffer_free(tmpbuf);
1224 /* We are ready to process the command request. Let's search for the
1225 requested client and send reply to the requesting client. */
1227 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1228 check_global = TRUE;
1229 else if (server->server_type != SILC_SERVER)
1230 check_global = TRUE;
1232 /* Parse the whowas request */
1233 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1236 /* Get all clients matching that nickname from local list */
1237 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1239 &clients, &clients_count))
1240 silc_idlist_get_clients_by_hash(server->local_list,
1241 nick, server->md5hash,
1242 &clients, &clients_count);
1244 /* Check global list as well */
1246 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1248 &clients, &clients_count))
1249 silc_idlist_get_clients_by_hash(server->global_list,
1250 nick, server->md5hash,
1251 &clients, &clients_count);
1255 /* Such a client really does not exist in the SILC network. */
1256 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1257 SILC_STATUS_ERR_NO_SUCH_NICK,
1258 3, nick, strlen(nick));
1262 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1267 /* Send the command reply to the client */
1268 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1273 silc_free(server_name);
1277 /* Server side of command WHOWAS. */
1279 SILC_SERVER_CMD_FUNC(whowas)
1281 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1284 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1286 ret = silc_server_command_whowas_process(cmd);
1287 silc_server_command_free(cmd);
1290 /******************************************************************************
1294 ******************************************************************************/
1297 silc_server_command_identify_send_router(SilcServerCommandContext cmd)
1299 SilcServer server = cmd->server;
1301 SilcUInt16 old_ident;
1303 old_ident = silc_command_get_ident(cmd->payload);
1304 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1305 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1307 /* Send IDENTIFY command to our router */
1308 silc_server_packet_send(server, (SilcSocketConnection)
1309 server->router->connection,
1310 SILC_PACKET_COMMAND, cmd->packet->flags,
1311 tmpbuf->data, tmpbuf->len, TRUE);
1313 /* Reprocess this packet after received reply from router */
1314 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1315 silc_command_get_ident(cmd->payload),
1316 silc_server_command_identify,
1317 silc_server_command_dup(cmd));
1318 cmd->pending = TRUE;
1319 silc_command_set_ident(cmd->payload, old_ident);
1320 silc_buffer_free(tmpbuf);
1324 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1325 SilcClientEntry **clients,
1326 SilcUInt32 *clients_count,
1327 SilcServerEntry **servers,
1328 SilcUInt32 *servers_count,
1329 SilcChannelEntry **channels,
1330 SilcUInt32 *channels_count,
1333 SilcServer server = cmd->server;
1336 SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
1338 bool check_global = FALSE;
1343 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1344 check_global = TRUE;
1345 else if (server->server_type != SILC_SERVER)
1346 check_global = TRUE;
1348 /* If ID Payload is in the command it must be used instead of names */
1349 tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1351 /* No ID, get the names. */
1353 /* If we are normal server and have not resolved information from
1354 router yet, do so now. */
1355 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1356 server->server_type == SILC_SERVER && !cmd->pending &&
1357 !server->standalone) {
1358 silc_server_command_identify_send_router(cmd);
1362 /* Try to get nickname@server. */
1363 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1366 char *nick_server = NULL;
1368 silc_parse_userfqdn(tmp, &nick, &nick_server);
1370 if (!silc_idlist_get_clients_by_hash(server->local_list,
1371 nick, server->md5hash,
1372 clients, clients_count))
1373 silc_idlist_get_clients_by_nickname(server->local_list,
1375 clients, clients_count);
1377 if (!silc_idlist_get_clients_by_hash(server->global_list,
1378 nick, server->md5hash,
1379 clients, clients_count))
1380 silc_idlist_get_clients_by_nickname(server->global_list,
1382 clients, clients_count);
1386 silc_free(nick_server);
1389 /* the nickname does not exist, send error reply */
1390 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1391 SILC_STATUS_ERR_NO_SUCH_NICK,
1392 3, tmp, strlen(tmp));
1397 /* Try to get server name */
1398 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1400 entry = silc_idlist_find_server_by_name(server->local_list,
1402 if (!entry && check_global)
1403 entry = silc_idlist_find_server_by_name(server->global_list,
1406 *servers = silc_realloc(*servers, sizeof(**servers) *
1407 (*servers_count + 1));
1408 (*servers)[(*servers_count)++] = entry;
1412 /* the server does not exist, send error reply */
1413 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1414 SILC_STATUS_ERR_NO_SUCH_SERVER,
1415 3, tmp, strlen(tmp));
1420 /* Try to get channel name */
1421 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1423 entry = silc_idlist_find_channel_by_name(server->local_list,
1425 if (!entry && check_global)
1426 entry = silc_idlist_find_channel_by_name(server->global_list,
1429 *channels = silc_realloc(*channels, sizeof(**channels) *
1430 (*channels_count + 1));
1431 (*channels)[(*channels_count)++] = entry;
1435 /* The channel does not exist, send error reply */
1436 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1437 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1438 3, tmp, strlen(tmp));
1443 if (!(*clients) && !(*servers) && !(*channels)) {
1444 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1445 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1449 /* Command includes ID, we must use that. Also check whether the command
1450 has more than one ID set - take them all. */
1452 /* Take all ID's from the command packet */
1453 for (i = 0; i < argc; i++) {
1456 tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
1460 idp = silc_id_payload_parse(tmp, len);
1462 silc_free(*clients);
1463 silc_free(*servers);
1464 silc_free(*channels);
1465 silc_server_command_send_status_reply(
1466 cmd, SILC_COMMAND_IDENTIFY,
1467 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1471 id = silc_id_payload_get_id(idp);
1473 switch (silc_id_payload_get_type(idp)) {
1475 case SILC_ID_CLIENT:
1476 entry = (void *)silc_idlist_find_client_by_id(server->local_list,
1478 if (!entry && check_global)
1479 entry = (void *)silc_idlist_find_client_by_id(server->global_list,
1482 *clients = silc_realloc(*clients, sizeof(**clients) *
1483 (*clients_count + 1));
1484 (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
1486 /* If we are normal server and have not resolved information from
1487 router yet, do so now. */
1488 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1489 server->server_type == SILC_SERVER && !cmd->pending &&
1490 !server->standalone) {
1491 silc_server_command_identify_send_router(cmd);
1492 silc_free(*clients);
1493 silc_free(*servers);
1494 silc_free(*channels);
1497 silc_server_command_send_status_data(
1498 cmd, SILC_COMMAND_IDENTIFY,
1499 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1507 case SILC_ID_SERVER:
1508 entry = (void *)silc_idlist_find_server_by_id(server->local_list,
1510 if (!entry && check_global)
1511 entry = (void *)silc_idlist_find_server_by_id(server->global_list,
1514 *servers = silc_realloc(*servers, sizeof(**servers) *
1515 (*servers_count + 1));
1516 (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
1518 /* If we are normal server and have not resolved information from
1519 router yet, do so now. */
1520 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1521 server->server_type == SILC_SERVER && !cmd->pending &&
1522 !server->standalone) {
1523 silc_server_command_identify_send_router(cmd);
1524 silc_free(*clients);
1525 silc_free(*servers);
1526 silc_free(*channels);
1529 silc_server_command_send_status_data(
1530 cmd, SILC_COMMAND_IDENTIFY,
1531 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
1538 case SILC_ID_CHANNEL:
1539 entry = (void *)silc_idlist_find_channel_by_id(server->local_list,
1541 if (!entry && check_global)
1542 entry = (void *)silc_idlist_find_channel_by_id(server->global_list,
1545 *channels = silc_realloc(*channels, sizeof(**channels) *
1546 (*channels_count + 1));
1547 (*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
1549 /* If we are normal server and have not resolved information from
1550 router yet, do so now. */
1551 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1552 server->server_type == SILC_SERVER && !cmd->pending &&
1553 !server->standalone) {
1554 silc_server_command_identify_send_router(cmd);
1555 silc_free(*clients);
1556 silc_free(*servers);
1557 silc_free(*channels);
1560 silc_server_command_send_status_data(
1561 cmd, SILC_COMMAND_IDENTIFY,
1562 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
1575 silc_free(*clients);
1576 silc_free(*servers);
1577 silc_free(*channels);
1581 /* Get the max count of reply messages allowed */
1582 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1591 /* Checks that all mandatory fields in client entry are present. If not
1592 then send WHOIS request to the server who owns the client. We use
1593 WHOIS because we want to get as much information as possible at once. */
1596 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1597 SilcClientEntry *clients,
1598 SilcUInt32 clients_count)
1600 SilcServer server = cmd->server;
1601 SilcClientEntry entry;
1602 SilcServerResolveContext resolve = NULL, r = NULL;
1603 SilcUInt32 resolve_count = 0;
1607 for (i = 0; i < clients_count; i++) {
1612 if (entry->nickname ||
1613 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1617 /* If we are normal server, and we've not resolved this client from
1618 router and it is global client, we'll check whether it is on some
1619 channel. If not then we cannot be sure about its validity, and
1620 we'll resolve it from router. */
1621 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
1622 entry->connection || silc_hash_table_count(entry->channels))
1626 /* We need to resolve this entry since it is not complete */
1628 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1629 /* The entry is being resolved (and we are not the resolver) so attach
1630 to the command reply and we're done with this one. */
1631 silc_server_command_pending(server, SILC_COMMAND_NONE,
1632 entry->resolve_cmd_ident,
1633 silc_server_command_identify,
1634 silc_server_command_dup(cmd));
1637 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1638 /* We've resolved this and it still is not ready. We'll return
1639 and are that this will be handled again after it is resolved. */
1640 for (i = 0; i < resolve_count; i++) {
1641 for (k = 0; k < r->res_argc; k++)
1642 silc_free(r->res_argv[k]);
1643 silc_free(r->res_argv);
1644 silc_free(r->res_argv_lens);
1645 silc_free(r->res_argv_types);
1650 /* We'll resolve this client */
1654 for (k = 0; k < resolve_count; k++) {
1655 if (resolve[k].router == entry->router) {
1662 resolve = silc_realloc(resolve, sizeof(*resolve) *
1663 (resolve_count + 1));
1664 r = &resolve[resolve_count];
1665 memset(r, 0, sizeof(*r));
1666 r->router = entry->router;
1667 r->ident = ++server->cmd_ident;
1671 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1673 r->res_argv_lens = silc_realloc(r->res_argv_lens,
1674 sizeof(*r->res_argv_lens) *
1676 r->res_argv_types = silc_realloc(r->res_argv_types,
1677 sizeof(*r->res_argv_types) *
1679 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1680 r->res_argv[r->res_argc] = silc_calloc(idp->len,
1681 sizeof(**r->res_argv));
1682 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1683 r->res_argv_lens[r->res_argc] = idp->len;
1684 r->res_argv_types[r->res_argc] = r->res_argc + 3;
1686 silc_buffer_free(idp);
1688 entry->resolve_cmd_ident = r->ident;
1689 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1690 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1695 /* Do the resolving */
1696 for (i = 0; i < resolve_count; i++) {
1701 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1702 now anyway so make it a good one. */
1703 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1704 r->res_argc, r->res_argv,
1708 silc_server_packet_send(server, r->router->connection,
1709 SILC_PACKET_COMMAND, cmd->packet->flags,
1710 res_cmd->data, res_cmd->len, FALSE);
1712 /* Reprocess this packet after received reply */
1713 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1715 silc_server_command_identify,
1716 silc_server_command_dup(cmd));
1717 cmd->pending = TRUE;
1719 silc_buffer_free(res_cmd);
1720 for (k = 0; k < r->res_argc; k++)
1721 silc_free(r->res_argv[k]);
1722 silc_free(r->res_argv);
1723 silc_free(r->res_argv_lens);
1724 silc_free(r->res_argv_types);
1733 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1734 SilcClientEntry *clients,
1735 SilcUInt32 clients_count,
1736 SilcServerEntry *servers,
1737 SilcUInt32 servers_count,
1738 SilcChannelEntry *channels,
1739 SilcUInt32 channels_count,
1742 SilcServer server = cmd->server;
1743 int i, k, len, valid_count;
1744 SilcBuffer packet, idp;
1745 SilcCommandStatus status;
1746 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1747 char nh[256], uh[256];
1748 SilcSocketConnection hsock;
1750 status = SILC_STATUS_OK;
1753 SilcClientEntry entry;
1755 /* Process only valid entries. */
1757 for (i = 0; i < clients_count; i++) {
1758 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1765 /* No valid entries found at all, just send error */
1768 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1770 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1771 SILC_STATUS_ERR_NO_SUCH_NICK,
1772 3, tmp, strlen(tmp));
1774 tmp = silc_argument_get_arg_type(cmd->args, 5, (SilcUInt32 *)&len);
1775 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1776 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1782 /* Process all valid client entries and send command replies */
1784 if (valid_count > 1)
1785 status = SILC_STATUS_LIST_START;
1787 for (i = 0, k = 0; i < clients_count; i++) {
1793 status = SILC_STATUS_LIST_ITEM;
1794 if (valid_count > 1 && k == valid_count - 1
1795 && !servers_count && !channels_count)
1796 status = SILC_STATUS_LIST_END;
1797 if (count && k - 1 == count)
1798 status = SILC_STATUS_LIST_END;
1799 if (count && k - 1 > count)
1802 /* Send IDENTIFY reply */
1804 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1805 memset(uh, 0, sizeof(uh));
1806 memset(nh, 0, sizeof(nh));
1807 strncat(nh, entry->nickname, strlen(entry->nickname));
1808 if (!strchr(entry->nickname, '@')) {
1809 strncat(nh, "@", 1);
1810 if (entry->servername) {
1811 strncat(nh, entry->servername, strlen(entry->servername));
1813 len = entry->router ? strlen(entry->router->server_name) :
1814 strlen(server->server_name);
1815 strncat(nh, entry->router ? entry->router->server_name :
1816 server->server_name, len);
1820 if (!entry->username) {
1821 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1823 2, idp->data, idp->len,
1826 strncat(uh, entry->username, strlen(entry->username));
1827 if (!strchr(entry->username, '@')) {
1828 strncat(uh, "@", 1);
1829 hsock = (SilcSocketConnection)entry->connection;
1830 len = strlen(hsock->hostname);
1831 strncat(uh, hsock->hostname, len);
1834 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1836 2, idp->data, idp->len,
1841 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1842 0, packet->data, packet->len, FALSE);
1844 silc_buffer_free(packet);
1845 silc_buffer_free(idp);
1852 SilcServerEntry entry;
1854 if (status == SILC_STATUS_OK && servers_count > 1)
1855 status = SILC_STATUS_LIST_START;
1857 for (i = 0, k = 0; i < servers_count; i++) {
1861 status = SILC_STATUS_LIST_ITEM;
1862 if (servers_count > 1 && k == servers_count - 1 && !channels_count)
1863 status = SILC_STATUS_LIST_END;
1864 if (count && k - 1 == count)
1865 status = SILC_STATUS_LIST_END;
1866 if (count && k - 1 > count)
1869 /* Send IDENTIFY reply */
1870 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1872 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1874 2, idp->data, idp->len,
1875 3, entry->server_name,
1876 entry->server_name ?
1877 strlen(entry->server_name) : 0);
1878 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1879 0, packet->data, packet->len, FALSE);
1881 silc_buffer_free(packet);
1882 silc_buffer_free(idp);
1889 SilcChannelEntry entry;
1891 if (status == SILC_STATUS_OK && channels_count > 1)
1892 status = SILC_STATUS_LIST_START;
1894 for (i = 0, k = 0; i < channels_count; i++) {
1895 entry = channels[i];
1898 status = SILC_STATUS_LIST_ITEM;
1899 if (channels_count > 1 && k == channels_count - 1)
1900 status = SILC_STATUS_LIST_END;
1901 if (count && k - 1 == count)
1902 status = SILC_STATUS_LIST_END;
1903 if (count && k - 1 > count)
1906 /* Send IDENTIFY reply */
1907 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1909 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1911 2, idp->data, idp->len,
1912 3, entry->channel_name,
1913 entry->channel_name ?
1914 strlen(entry->channel_name): 0);
1915 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1916 0, packet->data, packet->len, FALSE);
1918 silc_buffer_free(packet);
1919 silc_buffer_free(idp);
1927 silc_server_command_identify_process(SilcServerCommandContext cmd)
1929 SilcUInt32 count = 0;
1931 SilcClientEntry *clients = NULL;
1932 SilcServerEntry *servers = NULL;
1933 SilcChannelEntry *channels = NULL;
1934 SilcUInt32 clients_count = 0, servers_count = 0, channels_count = 0;
1936 /* Parse the IDENTIFY request */
1937 ret = silc_server_command_identify_parse(cmd,
1938 &clients, &clients_count,
1939 &servers, &servers_count,
1940 &channels, &channels_count,
1946 /* Check that all mandatory fields are present and request those data
1947 from the server who owns the client if necessary. */
1948 if (clients && !silc_server_command_identify_check_client(cmd, clients,
1954 /* Send the command reply to the client */
1955 silc_server_command_identify_send_reply(cmd,
1956 clients, clients_count,
1957 servers, servers_count,
1958 channels, channels_count,
1964 silc_free(channels);
1968 SILC_SERVER_CMD_FUNC(identify)
1970 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1973 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1975 ret = silc_server_command_identify_process(cmd);
1976 silc_server_command_free(cmd);
1979 /* Server side of command NICK. Sets nickname for user. Setting
1980 nickname causes generation of a new client ID for the client. The
1981 new client ID is sent to the client after changing the nickname. */
1983 SILC_SERVER_CMD_FUNC(nick)
1985 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1986 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1987 SilcServer server = cmd->server;
1988 SilcBuffer packet, nidp, oidp = NULL;
1989 SilcClientID *new_id;
1990 SilcUInt32 nick_len;
1992 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1995 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1998 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
2000 /* Check nickname */
2001 nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
2004 if (silc_server_name_bad_chars(nick, nick_len) == TRUE) {
2005 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2006 SILC_STATUS_ERR_BAD_NICKNAME);
2010 /* Check for same nickname */
2011 if (!strcmp(client->nickname, nick)) {
2012 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2016 /* Create new Client ID */
2017 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
2019 cmd->server->md5hash, nick,
2022 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2025 /* Send notify about nickname change to our router. We send the new
2026 ID and ask to replace it with the old one. If we are router the
2027 packet is broadcasted. Send NICK_CHANGE notify. */
2028 if (!server->standalone)
2029 silc_server_send_notify_nick_change(server, server->router->connection,
2030 server->server_type == SILC_SERVER ?
2031 FALSE : TRUE, client->id,
2034 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2036 /* Remove old cache entry */
2037 silc_idcache_del_by_context(server->local_list->clients, client);
2040 silc_free(client->id);
2042 /* Save the nickname as this client is our local client */
2043 silc_free(client->nickname);
2045 client->nickname = strdup(nick);
2046 client->id = new_id;
2048 /* Update client cache */
2049 silc_idcache_add(server->local_list->clients, client->nickname,
2050 client->id, (void *)client, 0, NULL);
2052 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2054 /* Send NICK_CHANGE notify to the client's channels */
2055 silc_server_send_notify_on_channels(server, NULL, client,
2056 SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
2057 oidp->data, oidp->len,
2058 nidp->data, nidp->len,
2060 strlen(client->nickname));
2063 /* Send the new Client ID as reply command back to client */
2064 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
2065 SILC_STATUS_OK, ident, 1,
2066 2, nidp->data, nidp->len);
2067 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2068 0, packet->data, packet->len, FALSE);
2070 silc_buffer_free(packet);
2071 silc_buffer_free(nidp);
2073 silc_buffer_free(oidp);
2076 silc_server_command_free(cmd);
2079 /* Sends the LIST command reply */
2082 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2083 SilcChannelEntry *lch,
2084 SilcUInt32 lch_count,
2085 SilcChannelEntry *gch,
2086 SilcUInt32 gch_count)
2089 SilcBuffer packet, idp;
2090 SilcChannelEntry entry;
2091 SilcCommandStatus status;
2092 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2094 unsigned char usercount[4];
2096 int valid_lcount = 0, valid_rcount = 0;
2098 for (i = 0; i < lch_count; i++) {
2099 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2104 for (i = 0; i < gch_count; i++) {
2105 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2111 status = SILC_STATUS_OK;
2112 if ((lch_count + gch_count) > 1)
2113 status = SILC_STATUS_LIST_START;
2116 for (i = 0, k = 0; i < lch_count; i++) {
2122 status = SILC_STATUS_LIST_ITEM;
2123 if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
2124 status = SILC_STATUS_LIST_END;
2126 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2128 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2129 topic = "*private*";
2130 memset(usercount, 0, sizeof(usercount));
2132 topic = entry->topic;
2133 users = silc_hash_table_count(entry->user_list);
2134 SILC_PUT32_MSB(users, usercount);
2137 /* Send the reply */
2139 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2141 2, idp->data, idp->len,
2142 3, entry->channel_name,
2143 strlen(entry->channel_name),
2144 4, topic, topic ? strlen(topic) : 0,
2146 silc_server_packet_send(cmd->server, cmd->sock,
2147 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2148 packet->len, FALSE);
2149 silc_buffer_free(packet);
2150 silc_buffer_free(idp);
2155 for (i = 0, k = 0; i < gch_count; i++) {
2161 status = SILC_STATUS_LIST_ITEM;
2162 if (valid_rcount > 1 && k == valid_rcount - 1)
2163 status = SILC_STATUS_LIST_END;
2165 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2167 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2168 topic = "*private*";
2169 memset(usercount, 0, sizeof(usercount));
2171 topic = entry->topic;
2172 users = entry->user_count;
2173 SILC_PUT32_MSB(users, usercount);
2176 /* Send the reply */
2178 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2180 2, idp->data, idp->len,
2181 3, entry->channel_name,
2182 strlen(entry->channel_name),
2183 4, topic, topic ? strlen(topic) : 0,
2185 silc_server_packet_send(cmd->server, cmd->sock,
2186 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2187 packet->len, FALSE);
2188 silc_buffer_free(packet);
2189 silc_buffer_free(idp);
2194 /* Server side of LIST command. This lists the channel of the requested
2195 server. Secret channels are not listed. */
2197 SILC_SERVER_CMD_FUNC(list)
2199 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2200 SilcServer server = cmd->server;
2201 SilcChannelID *channel_id = NULL;
2204 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2205 SilcUInt32 lch_count = 0, gch_count = 0;
2207 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2209 /* If we are normal server, send the command to router, since we
2210 want to know all channels in the network. */
2211 if (!cmd->pending && server->server_type == SILC_SERVER &&
2212 !server->standalone) {
2214 SilcUInt16 old_ident;
2216 old_ident = silc_command_get_ident(cmd->payload);
2217 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2218 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2219 silc_server_packet_send(server, server->router->connection,
2220 SILC_PACKET_COMMAND, cmd->packet->flags,
2221 tmpbuf->data, tmpbuf->len, TRUE);
2223 /* Reprocess this packet after received reply from router */
2224 silc_server_command_pending(server, SILC_COMMAND_LIST,
2225 silc_command_get_ident(cmd->payload),
2226 silc_server_command_list,
2227 silc_server_command_dup(cmd));
2228 cmd->pending = TRUE;
2229 silc_command_set_ident(cmd->payload, old_ident);
2230 silc_buffer_free(tmpbuf);
2234 /* Get Channel ID */
2235 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2237 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2239 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2240 SILC_STATUS_ERR_NO_CHANNEL_ID);
2245 /* Get the channels from local list */
2246 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2249 /* Get the channels from global list */
2250 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2253 /* Send the reply */
2254 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2255 gchannels, gch_count);
2257 silc_free(lchannels);
2258 silc_free(gchannels);
2261 silc_server_command_free(cmd);
2264 /* Server side of TOPIC command. Sets topic for channel and/or returns
2265 current topic to client. */
2267 SILC_SERVER_CMD_FUNC(topic)
2269 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2270 SilcServer server = cmd->server;
2271 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2272 SilcChannelID *channel_id;
2273 SilcChannelEntry channel;
2274 SilcChannelClientEntry chl;
2275 SilcBuffer packet, idp;
2277 SilcUInt32 argc, tmp_len;
2278 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2280 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2282 argc = silc_argument_get_arg_num(cmd->args);
2284 /* Get Channel ID */
2285 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2287 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2288 SILC_STATUS_ERR_NO_CHANNEL_ID);
2291 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2293 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2294 SILC_STATUS_ERR_NO_CHANNEL_ID);
2298 /* Check whether the channel exists */
2299 channel = silc_idlist_find_channel_by_id(server->local_list,
2302 channel = silc_idlist_find_channel_by_id(server->global_list,
2305 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2306 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2313 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2315 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2316 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2320 if (strlen(tmp) > 256) {
2321 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2322 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2326 /* See whether the client is on channel and has rights to change topic */
2327 if (!silc_server_client_on_channel(client, channel, &chl)) {
2328 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2329 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2333 if (chl->mode == SILC_CHANNEL_UMODE_NONE &&
2334 channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2335 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2336 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2340 /* Set the topic for channel */
2341 silc_free(channel->topic);
2342 channel->topic = strdup(tmp);
2344 /* Send TOPIC_SET notify type to the network */
2345 if (!server->standalone)
2346 silc_server_send_notify_topic_set(server, server->router->connection,
2347 server->server_type == SILC_ROUTER ?
2348 TRUE : FALSE, channel,
2349 client->id, SILC_ID_CLIENT,
2352 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2354 /* Send notify about topic change to all clients on the channel */
2355 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2356 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2357 idp->data, idp->len,
2358 channel->topic, strlen(channel->topic));
2359 silc_buffer_free(idp);
2362 /* Send the topic to client as reply packet */
2363 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2364 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2365 SILC_STATUS_OK, ident, 2,
2366 2, idp->data, idp->len,
2369 strlen(channel->topic) : 0);
2370 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2371 0, packet->data, packet->len, FALSE);
2373 silc_buffer_free(packet);
2374 silc_buffer_free(idp);
2375 silc_free(channel_id);
2378 silc_server_command_free(cmd);
2381 /* Server side of INVITE command. Invites some client to join some channel.
2382 This command is also used to manage the invite list of the channel. */
2384 SILC_SERVER_CMD_FUNC(invite)
2386 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2387 SilcServer server = cmd->server;
2388 SilcSocketConnection sock = cmd->sock, dest_sock;
2389 SilcChannelClientEntry chl;
2390 SilcClientEntry sender, dest;
2391 SilcClientID *dest_id = NULL;
2392 SilcChannelEntry channel;
2393 SilcChannelID *channel_id = NULL;
2394 SilcIDListData idata;
2395 SilcBuffer idp, idp2, packet;
2396 unsigned char *tmp, *add, *del;
2398 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2400 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2402 /* Get Channel ID */
2403 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2405 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2406 SILC_STATUS_ERR_NO_CHANNEL_ID);
2409 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
2411 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2412 SILC_STATUS_ERR_NO_CHANNEL_ID);
2416 /* Get the channel entry */
2417 channel = silc_idlist_find_channel_by_id(server->local_list,
2420 channel = silc_idlist_find_channel_by_id(server->global_list,
2423 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2424 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2429 /* Check whether the sender of this command is on the channel. */
2430 sender = (SilcClientEntry)sock->user_data;
2431 if (!silc_server_client_on_channel(sender, channel, &chl)) {
2432 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2433 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2437 /* Check whether the channel is invite-only channel. If yes then the
2438 sender of this command must be at least channel operator. */
2439 if (chl->mode == SILC_CHANNEL_UMODE_NONE &&
2440 channel->mode & SILC_CHANNEL_MODE_INVITE) {
2441 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2442 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2446 /* Get destination client ID */
2447 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2452 dest_id = silc_id_payload_parse_id(tmp, len, NULL);
2454 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2455 SILC_STATUS_ERR_NO_CLIENT_ID);
2459 /* Get the client entry */
2460 dest = silc_server_get_client_resolve(server, dest_id, &resolve);
2462 if (server->server_type != SILC_SERVER || !resolve) {
2463 silc_server_command_send_status_reply(
2464 cmd, SILC_COMMAND_INVITE,
2465 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2469 /* The client info is being resolved. Reprocess this packet after
2470 receiving the reply to the query. */
2471 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2473 silc_server_command_invite,
2474 silc_server_command_dup(cmd));
2475 cmd->pending = TRUE;
2476 silc_free(channel_id);
2481 /* Check whether the requested client is already on the channel. */
2482 if (silc_server_client_on_channel(dest, channel, NULL)) {
2483 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2484 SILC_STATUS_ERR_USER_ON_CHANNEL);
2488 /* Get route to the client */
2489 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2491 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2492 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2496 memset(invite, 0, sizeof(invite));
2497 strncat(invite, dest->nickname, strlen(dest->nickname));
2498 strncat(invite, "!", 1);
2499 strncat(invite, dest->username, strlen(dest->username));
2500 if (!strchr(dest->username, '@')) {
2501 strncat(invite, "@", 1);
2502 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2505 len = strlen(invite);
2506 if (!channel->invite_list)
2507 channel->invite_list = silc_calloc(len + 2,
2508 sizeof(*channel->invite_list));
2510 channel->invite_list = silc_realloc(channel->invite_list,
2511 sizeof(*channel->invite_list) *
2513 strlen(channel->invite_list) + 2));
2514 strncat(channel->invite_list, invite, len);
2515 strncat(channel->invite_list, ",", 1);
2517 /* Send notify to the client that is invited to the channel */
2518 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2519 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2520 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2522 SILC_NOTIFY_TYPE_INVITE, 3,
2523 idp->data, idp->len,
2524 channel->channel_name,
2525 strlen(channel->channel_name),
2526 idp2->data, idp2->len);
2527 silc_buffer_free(idp);
2528 silc_buffer_free(idp2);
2531 /* Add the client to the invite list of the channel */
2532 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2534 if (!channel->invite_list)
2535 channel->invite_list = silc_calloc(len + 2,
2536 sizeof(*channel->invite_list));
2538 channel->invite_list = silc_realloc(channel->invite_list,
2539 sizeof(*channel->invite_list) *
2541 strlen(channel->invite_list) + 2));
2542 if (add[len - 1] == ',')
2543 add[len - 1] = '\0';
2545 strncat(channel->invite_list, add, len);
2546 strncat(channel->invite_list, ",", 1);
2549 /* Get the invite to be removed and remove it from the list */
2550 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2551 if (del && channel->invite_list) {
2552 char *start, *end, *n;
2554 if (!strncmp(channel->invite_list, del,
2555 strlen(channel->invite_list) - 1)) {
2556 silc_free(channel->invite_list);
2557 channel->invite_list = NULL;
2559 start = strstr(channel->invite_list, del);
2560 if (start && strlen(start) >= len) {
2562 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2563 strncat(n, channel->invite_list, start - channel->invite_list);
2564 strncat(n, end + 1, ((channel->invite_list +
2565 strlen(channel->invite_list)) - end) - 1);
2566 silc_free(channel->invite_list);
2567 channel->invite_list = n;
2572 /* Send notify to the primary router */
2573 if (!server->standalone)
2574 silc_server_send_notify_invite(server, server->router->connection,
2575 server->server_type == SILC_ROUTER ?
2576 TRUE : FALSE, channel,
2577 sender->id, add, del);
2579 /* Send command reply */
2580 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2584 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2585 SILC_STATUS_OK, ident, 2,
2587 3, channel->invite_list,
2588 channel->invite_list ?
2589 strlen(channel->invite_list) : 0);
2592 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2593 SILC_STATUS_OK, ident, 1,
2595 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2596 packet->data, packet->len, FALSE);
2597 silc_buffer_free(packet);
2601 silc_free(channel_id);
2602 silc_server_command_free(cmd);
2607 SilcSocketConnection sock;
2611 /* Quits connection to client. This gets called if client won't
2612 close the connection even when it has issued QUIT command. */
2614 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2616 QuitInternal q = (QuitInternal)context;
2618 /* Free all client specific data, such as client entry and entires
2619 on channels this client may be on. */
2620 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2622 q->sock->user_data = NULL;
2624 /* Close the connection on our side */
2625 silc_server_close_connection(q->server, q->sock);
2627 silc_free(q->signoff);
2631 /* Quits SILC session. This is the normal way to disconnect client. */
2633 SILC_SERVER_CMD_FUNC(quit)
2635 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2636 SilcServer server = cmd->server;
2637 SilcSocketConnection sock = cmd->sock;
2639 unsigned char *tmp = NULL;
2642 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2644 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2647 /* Get destination ID */
2648 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2652 q = silc_calloc(1, sizeof(*q));
2655 q->signoff = tmp ? strdup(tmp) : NULL;
2657 /* We quit the connection with little timeout */
2658 silc_schedule_task_add(server->schedule, sock->sock,
2659 silc_server_command_quit_cb, (void *)q,
2660 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2663 silc_server_command_free(cmd);
2666 /* Server side of command KILL. This command is used by router operator
2667 to remove an client from the SILC Network temporarily. */
2669 SILC_SERVER_CMD_FUNC(kill)
2671 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2672 SilcServer server = cmd->server;
2673 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2674 SilcClientEntry remote_client;
2675 SilcClientID *client_id;
2676 unsigned char *tmp, *comment;
2677 SilcUInt32 tmp_len, tmp_len2;
2681 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2683 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2686 /* KILL command works only on router */
2687 if (server->server_type != SILC_ROUTER) {
2688 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2689 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2693 /* Check whether client has the permissions. */
2694 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2695 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2696 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2700 /* Get the client ID */
2701 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2703 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2704 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2707 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2709 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2710 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2714 /* Get the client entry */
2715 remote_client = silc_idlist_find_client_by_id(server->local_list,
2716 client_id, TRUE, NULL);
2718 if (!remote_client) {
2719 remote_client = silc_idlist_find_client_by_id(server->global_list,
2720 client_id, TRUE, NULL);
2722 if (!remote_client) {
2723 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2724 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2730 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2734 /* Send reply to the sender */
2735 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2738 /* Send the KILL notify packets. First send it to the channel, then
2739 to our primary router and then directly to the client who is being
2740 killed right now. */
2742 /* Send KILLED notify to the channels. It is not sent to the client
2743 as it will be sent differently destined directly to the client and not
2745 killer = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2746 silc_server_send_notify_on_channels(server, remote_client,
2747 remote_client, SILC_NOTIFY_TYPE_KILLED,
2749 comment, comment ? tmp_len2 : 0,
2750 killer->data, killer->len);
2751 silc_buffer_free(killer);
2753 /* Send KILLED notify to primary route */
2754 if (!server->standalone)
2755 silc_server_send_notify_killed(server, server->router->connection, TRUE,
2756 remote_client->id, comment, client->id);
2758 /* Send KILLED notify to the client directly */
2759 silc_server_send_notify_killed(server, remote_client->connection ?
2760 remote_client->connection :
2761 remote_client->router->connection, FALSE,
2762 remote_client->id, comment, client->id);
2764 /* Remove the client from all channels. This generates new keys to the
2765 channels as well. */
2766 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2769 /* Remove the client entry, If it is locally connected then we will also
2770 disconnect the client here */
2771 if (remote_client->connection) {
2772 /* Remove locally conneted client */
2773 SilcSocketConnection sock = remote_client->connection;
2774 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2775 silc_server_close_connection(server, sock);
2777 /* Update statistics */
2778 if (remote_client->connection)
2779 server->stat.my_clients--;
2780 if (server->stat.cell_clients)
2781 server->stat.cell_clients--;
2782 SILC_OPER_STATS_UPDATE(remote_client, server, SILC_UMODE_SERVER_OPERATOR);
2783 SILC_OPER_STATS_UPDATE(remote_client, router, SILC_UMODE_ROUTER_OPERATOR);
2785 /* Remove remote client */
2786 silc_idlist_del_client(local ? server->local_list :
2787 server->global_list, remote_client);
2791 silc_server_command_free(cmd);
2794 /* Server side of command INFO. This sends information about us to
2795 the client. If client requested specific server we will send the
2796 command to that server. */
2798 SILC_SERVER_CMD_FUNC(info)
2800 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2801 SilcServer server = cmd->server;
2802 SilcBuffer packet, idp;
2805 char *dest_server, *server_info = NULL, *server_name;
2806 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2807 SilcServerEntry entry = NULL;
2808 SilcServerID *server_id = NULL;
2810 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2812 /* Get server name */
2813 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2816 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2818 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2820 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2821 SILC_STATUS_ERR_NO_SERVER_ID);
2827 /* Check whether we have this server cached */
2828 entry = silc_idlist_find_server_by_id(server->local_list,
2829 server_id, TRUE, NULL);
2831 entry = silc_idlist_find_server_by_id(server->global_list,
2832 server_id, TRUE, NULL);
2833 if (!entry && server->server_type != SILC_SERVER) {
2834 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2835 SILC_STATUS_ERR_NO_SUCH_SERVER);
2841 /* Some buggy servers has sent request to router about themselves. */
2842 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2845 if ((!dest_server && !server_id && !entry) || (entry &&
2846 entry == server->id_entry) ||
2847 (dest_server && !cmd->pending &&
2848 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2849 /* Send our reply */
2850 char info_string[256];
2852 memset(info_string, 0, sizeof(info_string));
2853 snprintf(info_string, sizeof(info_string),
2854 "location: %s server: %s admin: %s <%s>",
2855 server->config->server_info->location,
2856 server->config->server_info->server_type,
2857 server->config->server_info->admin,
2858 server->config->server_info->email);
2860 server_info = info_string;
2861 entry = server->id_entry;
2863 /* Check whether we have this server cached */
2864 if (!entry && dest_server) {
2865 entry = silc_idlist_find_server_by_name(server->global_list,
2866 dest_server, TRUE, NULL);
2868 entry = silc_idlist_find_server_by_name(server->local_list,
2869 dest_server, TRUE, NULL);
2873 if (!cmd->pending &&
2874 server->server_type != SILC_SERVER && entry && !entry->server_info) {
2875 /* Send to the server */
2877 SilcUInt16 old_ident;
2879 old_ident = silc_command_get_ident(cmd->payload);
2880 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2881 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2883 silc_server_packet_send(server, entry->connection,
2884 SILC_PACKET_COMMAND, cmd->packet->flags,
2885 tmpbuf->data, tmpbuf->len, TRUE);
2887 /* Reprocess this packet after received reply from router */
2888 silc_server_command_pending(server, SILC_COMMAND_INFO,
2889 silc_command_get_ident(cmd->payload),
2890 silc_server_command_info,
2891 silc_server_command_dup(cmd));
2892 cmd->pending = TRUE;
2893 silc_command_set_ident(cmd->payload, old_ident);
2894 silc_buffer_free(tmpbuf);
2898 if (!entry && !cmd->pending && !server->standalone) {
2899 /* Send to the primary router */
2901 SilcUInt16 old_ident;
2903 old_ident = silc_command_get_ident(cmd->payload);
2904 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2905 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2907 silc_server_packet_send(server, server->router->connection,
2908 SILC_PACKET_COMMAND, cmd->packet->flags,
2909 tmpbuf->data, tmpbuf->len, TRUE);
2911 /* Reprocess this packet after received reply from router */
2912 silc_server_command_pending(server, SILC_COMMAND_INFO,
2913 silc_command_get_ident(cmd->payload),
2914 silc_server_command_info,
2915 silc_server_command_dup(cmd));
2916 cmd->pending = TRUE;
2917 silc_command_set_ident(cmd->payload, old_ident);
2918 silc_buffer_free(tmpbuf);
2923 silc_free(server_id);
2926 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2927 SILC_STATUS_ERR_NO_SUCH_SERVER);
2931 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2933 server_info = entry->server_info;
2934 server_name = entry->server_name;
2936 /* Send the reply */
2937 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2938 SILC_STATUS_OK, ident, 3,
2939 2, idp->data, idp->len,
2941 strlen(server_name),
2944 strlen(server_info) : 0);
2945 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2946 packet->data, packet->len, FALSE);
2948 silc_buffer_free(packet);
2949 silc_buffer_free(idp);
2952 silc_server_command_free(cmd);
2955 /* Server side of command PING. This just replies to the ping. */
2957 SILC_SERVER_CMD_FUNC(ping)
2959 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2960 SilcServer server = cmd->server;
2965 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
2968 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2970 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2971 SILC_STATUS_ERR_NO_SERVER_ID);
2974 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2978 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2979 /* Send our reply */
2980 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2983 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2984 SILC_STATUS_ERR_NO_SUCH_SERVER);
2991 silc_server_command_free(cmd);
2994 /* Server side of command STATS. */
2996 SILC_SERVER_CMD_FUNC(stats)
2998 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2999 SilcServer server = cmd->server;
3000 SilcServerID *server_id;
3003 SilcBuffer packet, stats;
3004 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3007 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1);
3010 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3012 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3013 SILC_STATUS_ERR_NO_SERVER_ID);
3016 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3020 /* The ID must be ours */
3021 if (!SILC_ID_SERVER_COMPARE(server->id, server_id)) {
3022 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3023 SILC_STATUS_ERR_NO_SUCH_SERVER);
3024 silc_free(server_id);
3027 silc_free(server_id);
3029 /* If we are router then just send everything we got. If we are normal
3030 server then we'll send this to our router to get all the latest
3031 statistical information. */
3032 if (!cmd->pending && server->server_type != SILC_ROUTER &&
3033 !server->standalone) {
3034 /* Send request to our router */
3035 SilcBuffer idp = silc_id_payload_encode(server->router->id,
3037 packet = silc_command_payload_encode_va(SILC_COMMAND_STATS,
3038 ++server->cmd_ident, 1,
3039 1, idp->data, idp->len);
3040 silc_server_packet_send(server, server->router->connection,
3041 SILC_PACKET_COMMAND, 0, packet->data,
3042 packet->len, FALSE);
3044 /* Reprocess this packet after received reply from router */
3045 silc_server_command_pending(server, SILC_COMMAND_STATS,
3047 silc_server_command_stats,
3048 silc_server_command_dup(cmd));
3049 cmd->pending = TRUE;
3050 silc_buffer_free(packet);
3051 silc_buffer_free(idp);
3055 /* Send our reply to sender */
3056 uptime = time(NULL) - server->starttime;
3058 stats = silc_buffer_alloc_size(60);
3059 silc_buffer_format(stats,
3060 SILC_STR_UI_INT(server->starttime),
3061 SILC_STR_UI_INT(uptime),
3062 SILC_STR_UI_INT(server->stat.my_clients),
3063 SILC_STR_UI_INT(server->stat.my_channels),
3064 SILC_STR_UI_INT(server->stat.my_server_ops),
3065 SILC_STR_UI_INT(server->stat.my_router_ops),
3066 SILC_STR_UI_INT(server->stat.cell_clients),
3067 SILC_STR_UI_INT(server->stat.cell_channels),
3068 SILC_STR_UI_INT(server->stat.cell_servers),
3069 SILC_STR_UI_INT(server->stat.clients),
3070 SILC_STR_UI_INT(server->stat.channels),
3071 SILC_STR_UI_INT(server->stat.servers),
3072 SILC_STR_UI_INT(server->stat.routers),
3073 SILC_STR_UI_INT(server->stat.server_ops),
3074 SILC_STR_UI_INT(server->stat.router_ops),
3077 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_STATS,
3078 SILC_STATUS_OK, ident, 2,
3080 3, stats->data, stats->len);
3081 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
3082 0, packet->data, packet->len, FALSE);
3083 silc_buffer_free(packet);
3084 silc_buffer_free(stats);
3087 silc_server_command_free(cmd);
3090 /* Internal routine to join channel. The channel sent to this function
3091 has been either created or resolved from ID lists. This joins the sent
3092 client to the channel. */
3094 static void silc_server_command_join_channel(SilcServer server,
3095 SilcServerCommandContext cmd,
3096 SilcChannelEntry channel,
3097 SilcClientID *client_id,
3101 const unsigned char *auth,
3102 SilcUInt32 auth_len)
3104 SilcSocketConnection sock = cmd->sock;
3106 SilcUInt32 tmp_len, user_count;
3107 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
3108 SilcClientEntry client;
3109 SilcChannelClientEntry chl;
3110 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
3111 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3112 char check[512], check2[512];
3113 bool founder = FALSE;
3116 SILC_LOG_DEBUG(("Start"));
3121 /* Get the client entry */
3122 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3123 client = (SilcClientEntry)sock->user_data;
3125 client = silc_server_get_client_resolve(server, client_id, &resolve);
3131 silc_server_command_send_status_reply(
3132 cmd, SILC_COMMAND_JOIN,
3133 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3137 /* The client info is being resolved. Reprocess this packet after
3138 receiving the reply to the query. */
3139 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
3141 silc_server_command_join,
3142 silc_server_command_dup(cmd));
3143 cmd->pending = TRUE;
3147 cmd->pending = FALSE;
3151 * Check founder auth payload if provided. If client can gain founder
3152 * privileges it can override various conditions on joining the channel,
3153 * and can have directly the founder mode set on the channel.
3155 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3156 SilcIDListData idata = (SilcIDListData)client;
3158 if (channel->founder_key && idata->public_key &&
3159 silc_pkcs_public_key_compare(channel->founder_key,
3160 idata->public_key)) {
3161 void *auth_data = (channel->founder_method == SILC_AUTH_PASSWORD ?
3162 (void *)channel->founder_passwd :
3163 (void *)channel->founder_key);
3164 SilcUInt32 auth_data_len =
3165 (channel->founder_method == SILC_AUTH_PASSWORD ?
3166 channel->founder_passwd_len : 0);
3168 /* Check whether the client is to become founder */
3169 if (silc_auth_verify_data(auth, auth_len, channel->founder_method,
3170 auth_data, auth_data_len,
3171 idata->hash, client->id, SILC_ID_CLIENT)) {
3172 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3179 * Check channel modes
3183 memset(check, 0, sizeof(check));
3184 memset(check2, 0, sizeof(check2));
3185 strncat(check, client->nickname, strlen(client->nickname));
3186 strncat(check, "!", 1);
3187 strncat(check, client->username, strlen(client->username));
3188 if (!strchr(client->username, '@')) {
3189 strncat(check, "@", 1);
3190 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3193 strncat(check2, client->nickname, strlen(client->nickname));
3194 if (!strchr(client->nickname, '@')) {
3195 strncat(check2, "@", 1);
3196 strncat(check2, server->server_name, strlen(server->server_name));
3198 strncat(check2, "!", 1);
3199 strncat(check2, client->username, strlen(client->username));
3200 if (!strchr(client->username, '@')) {
3201 strncat(check2, "@", 1);
3202 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3205 /* Check invite list if channel is invite-only channel */
3206 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3207 if (!channel->invite_list ||
3208 (!silc_string_match(channel->invite_list, check) &&
3209 !silc_string_match(channel->invite_list, check2))) {
3210 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3211 SILC_STATUS_ERR_NOT_INVITED);
3216 /* Check ban list if it exists. If the client's nickname, server,
3217 username and/or hostname is in the ban list the access to the
3218 channel is denied. */
3219 if (channel->ban_list) {
3220 if (silc_string_match(channel->ban_list, check) ||
3221 silc_string_match(channel->ban_list, check2)) {
3222 silc_server_command_send_status_reply(
3223 cmd, SILC_COMMAND_JOIN,
3224 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
3229 /* Check user count limit if set. */
3230 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3231 if (silc_hash_table_count(channel->user_list) + 1 >
3232 channel->user_limit) {
3233 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3234 SILC_STATUS_ERR_CHANNEL_IS_FULL);
3240 /* Check the channel passphrase if set. */
3241 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3242 /* Get passphrase */
3243 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3245 passphrase = silc_memdup(tmp, tmp_len);
3247 if (!passphrase || !channel->passphrase ||
3248 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3249 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3250 SILC_STATUS_ERR_BAD_PASSWORD);
3256 * Client is allowed to join to the channel. Make it happen.
3259 /* Check whether the client already is on the channel */
3260 if (silc_server_client_on_channel(client, channel, NULL)) {
3261 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3262 SILC_STATUS_ERR_USER_ON_CHANNEL);
3266 /* Generate new channel key as protocol dictates */
3268 if (!silc_server_create_channel_key(server, channel, 0))
3271 /* Send the channel key. This is broadcasted to the channel but is not
3272 sent to the client who is joining to the channel. */
3273 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3274 silc_server_send_channel_key(server, NULL, channel,
3275 server->server_type == SILC_ROUTER ?
3276 FALSE : !server->standalone);
3279 /* Join the client to the channel by adding it to channel's user list.
3280 Add also the channel to client entry's channels list for fast cross-
3282 chl = silc_calloc(1, sizeof(*chl));
3284 chl->client = client;
3285 chl->channel = channel;
3286 silc_hash_table_add(channel->user_list, client, chl);
3287 silc_hash_table_add(client->channels, channel, chl);
3288 channel->user_count++;
3290 /* Get users on the channel */
3291 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3294 /* Encode Client ID Payload of the original client who wants to join */
3295 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3297 /* Encode command reply packet */
3298 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3299 SILC_PUT32_MSB(channel->mode, mode);
3300 SILC_PUT32_MSB(created, tmp2);
3301 SILC_PUT32_MSB(user_count, tmp3);
3303 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3304 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3305 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
3306 strlen(channel->channel_key->
3308 channel->channel_key->cipher->name,
3309 channel->key_len / 8, channel->key);
3314 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3315 SILC_STATUS_OK, ident, 13,
3316 2, channel->channel_name,
3317 strlen(channel->channel_name),
3318 3, chidp->data, chidp->len,
3319 4, clidp->data, clidp->len,
3322 7, keyp ? keyp->data : NULL,
3323 keyp ? keyp->len : 0,
3324 8, channel->ban_list,
3326 strlen(channel->ban_list) : 0,
3327 9, channel->invite_list,
3328 channel->invite_list ?
3329 strlen(channel->invite_list) : 0,
3332 strlen(channel->topic) : 0,
3333 11, silc_hmac_get_name(channel->hmac),
3334 strlen(silc_hmac_get_name(channel->
3337 13, user_list->data, user_list->len,
3338 14, mode_list->data,
3341 /* Send command reply */
3342 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3343 reply->data, reply->len, FALSE);
3345 /* Send JOIN notify to locally connected clients on the channel. If
3346 we are normal server then router will send or have sent JOIN notify
3347 already. However since we've added the client already to our channel
3348 we'll ignore it (in packet_receive.c) so we must send it here. If
3349 we are router then this will send it to local clients and local
3351 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3352 SILC_NOTIFY_TYPE_JOIN, 2,
3353 clidp->data, clidp->len,
3354 chidp->data, chidp->len);
3356 if (!cmd->pending) {
3357 /* Send JOIN notify packet to our primary router */
3358 if (!server->standalone)
3359 silc_server_send_notify_join(server, server->router->connection,
3360 server->server_type == SILC_ROUTER ?
3361 TRUE : FALSE, channel, client->id);
3364 /* Distribute the channel key to all backup routers. */
3365 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3366 keyp->data, keyp->len, FALSE, TRUE);
3369 /* If client became founder by providing correct founder auth data
3370 notify the mode change to the channel. */
3372 SILC_PUT32_MSB(chl->mode, mode);
3373 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3374 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3375 clidp->data, clidp->len,
3376 mode, 4, clidp->data, clidp->len);
3378 /* Set CUMODE notify type to network */
3379 if (!server->standalone)
3380 silc_server_send_notify_cumode(server, server->router->connection,
3381 server->server_type == SILC_ROUTER ?
3382 TRUE : FALSE, channel,
3383 chl->mode, client->id, SILC_ID_CLIENT,
3387 silc_buffer_free(reply);
3388 silc_buffer_free(clidp);
3389 silc_buffer_free(chidp);
3390 silc_buffer_free(keyp);
3391 silc_buffer_free(user_list);
3392 silc_buffer_free(mode_list);
3395 silc_free(passphrase);
3398 /* Server side of command JOIN. Joins client into requested channel. If
3399 the channel does not exist it will be created. */
3401 SILC_SERVER_CMD_FUNC(join)
3403 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3404 SilcServer server = cmd->server;
3405 unsigned char *auth;
3406 SilcUInt32 tmp_len, auth_len;
3407 char *tmp, *channel_name = NULL, *cipher, *hmac;
3408 SilcChannelEntry channel;
3409 SilcUInt32 umode = 0;
3410 bool created = FALSE, create_key = TRUE;
3411 SilcClientID *client_id;
3413 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3415 /* Get channel name */
3416 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3418 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3419 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3425 channel_name[255] = '\0';
3427 if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
3428 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3429 SILC_STATUS_ERR_BAD_CHANNEL);
3433 /* Get Client ID of the client who is joining to the channel */
3434 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3436 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3437 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3440 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3442 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3443 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3447 /* Get cipher, hmac name and auth payload */
3448 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3449 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3450 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3452 /* See if the channel exists */
3453 channel = silc_idlist_find_channel_by_name(server->local_list,
3454 channel_name, NULL);
3456 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3457 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3458 client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
3460 if (!channel || channel->disabled) {
3461 /* Channel not found */
3463 /* If we are standalone server we don't have a router, we just create
3464 the channel by ourselves. */
3465 if (server->standalone) {
3466 channel = silc_server_create_new_channel(server, server->id, cipher,
3467 hmac, channel_name, TRUE);
3469 silc_server_command_send_status_reply(
3470 cmd, SILC_COMMAND_JOIN,
3471 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3475 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3481 /* The channel does not exist on our server. If we are normal server
3482 we will send JOIN command to our router which will handle the
3483 joining procedure (either creates the channel if it doesn't exist
3484 or joins the client to it). */
3485 if (server->server_type != SILC_ROUTER) {
3487 SilcUInt16 old_ident;
3489 /* If this is pending command callback then we've resolved
3490 it and it didn't work, return since we've notified the
3491 client already in the command reply callback. */
3495 old_ident = silc_command_get_ident(cmd->payload);
3496 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3497 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3499 /* Send JOIN command to our router */
3500 silc_server_packet_send(server, (SilcSocketConnection)
3501 server->router->connection,
3502 SILC_PACKET_COMMAND, cmd->packet->flags,
3503 tmpbuf->data, tmpbuf->len, TRUE);
3505 /* Reprocess this packet after received reply from router */
3506 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3507 silc_command_get_ident(cmd->payload),
3508 silc_server_command_join,
3509 silc_server_command_dup(cmd));
3510 cmd->pending = TRUE;
3511 silc_command_set_ident(cmd->payload, old_ident);
3512 silc_buffer_free(tmpbuf);
3516 /* We are router and the channel does not seem exist so we will check
3517 our global list as well for the channel. */
3518 channel = silc_idlist_find_channel_by_name(server->global_list,
3519 channel_name, NULL);
3521 /* Channel really does not exist, create it */
3522 channel = silc_server_create_new_channel(server, server->id, cipher,
3523 hmac, channel_name, TRUE);
3525 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3526 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3530 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3538 /* Channel not found */
3540 /* If the command came from router and we are normal server then
3541 something went wrong with the joining as the channel was not found.
3542 We can't do anything else but ignore this. */
3543 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3544 server->server_type != SILC_ROUTER)
3547 /* We are router and the channel does not seem exist so we will check
3548 our global list as well for the channel. */
3549 channel = silc_idlist_find_channel_by_name(server->global_list,
3550 channel_name, NULL);
3552 /* Channel really does not exist, create it */
3553 channel = silc_server_create_new_channel(server, server->id, cipher,
3554 hmac, channel_name, TRUE);
3556 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3557 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3561 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3568 /* Check whether the channel was created by our router */
3569 if (cmd->pending && context2) {
3570 SilcServerCommandReplyContext reply = context2;
3572 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3573 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3574 SILC_GET32_MSB(created, tmp);
3575 if (silc_argument_get_arg_type(reply->args, 7, NULL))
3576 create_key = FALSE; /* Router returned the key already */
3579 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
3580 !silc_hash_table_count(channel->user_list))
3584 /* If the channel does not have global users and is also empty the client
3585 will be the channel founder and operator. */
3586 if (!channel->global_users && !silc_hash_table_count(channel->user_list))
3587 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3589 /* Join to the channel */
3590 silc_server_command_join_channel(server, cmd, channel, client_id,
3591 created, create_key, umode,
3594 silc_free(client_id);
3597 silc_server_command_free(cmd);
3600 /* Server side of command MOTD. Sends server's current "message of the
3601 day" to the client. */
3603 SILC_SERVER_CMD_FUNC(motd)
3605 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3606 SilcServer server = cmd->server;
3607 SilcBuffer packet, idp;
3608 char *motd, *dest_server;
3609 SilcUInt32 motd_len;
3610 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3612 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3614 /* Get server name */
3615 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3617 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3618 SILC_STATUS_ERR_NO_SUCH_SERVER);
3622 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3625 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3627 if (server->config && server->config->server_info &&
3628 server->config->server_info->motd_file) {
3630 motd = silc_file_readfile(server->config->server_info->motd_file, &motd_len);
3635 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3636 SILC_STATUS_OK, ident, 2,
3641 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3642 SILC_STATUS_OK, ident, 1,
3646 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3647 packet->data, packet->len, FALSE);
3648 silc_buffer_free(packet);
3649 silc_buffer_free(idp);
3651 SilcServerEntry entry;
3653 /* Check whether we have this server cached */
3654 entry = silc_idlist_find_server_by_name(server->global_list,
3655 dest_server, TRUE, NULL);
3657 entry = silc_idlist_find_server_by_name(server->local_list,
3658 dest_server, TRUE, NULL);
3661 if (server->server_type != SILC_SERVER && !cmd->pending &&
3662 entry && !entry->motd) {
3663 /* Send to the server */
3665 SilcUInt16 old_ident;
3667 old_ident = silc_command_get_ident(cmd->payload);
3668 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3669 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3671 silc_server_packet_send(server, entry->connection,
3672 SILC_PACKET_COMMAND, cmd->packet->flags,
3673 tmpbuf->data, tmpbuf->len, TRUE);
3675 /* Reprocess this packet after received reply from router */
3676 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3677 silc_command_get_ident(cmd->payload),
3678 silc_server_command_motd,
3679 silc_server_command_dup(cmd));
3680 cmd->pending = TRUE;
3681 silc_command_set_ident(cmd->payload, old_ident);
3682 silc_buffer_free(tmpbuf);
3686 if (!entry && !cmd->pending && !server->standalone) {
3687 /* Send to the primary router */
3689 SilcUInt16 old_ident;
3691 old_ident = silc_command_get_ident(cmd->payload);
3692 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3693 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3695 silc_server_packet_send(server, server->router->connection,
3696 SILC_PACKET_COMMAND, cmd->packet->flags,
3697 tmpbuf->data, tmpbuf->len, TRUE);
3699 /* Reprocess this packet after received reply from router */
3700 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3701 silc_command_get_ident(cmd->payload),
3702 silc_server_command_motd,
3703 silc_server_command_dup(cmd));
3704 cmd->pending = TRUE;
3705 silc_command_set_ident(cmd->payload, old_ident);
3706 silc_buffer_free(tmpbuf);
3711 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3712 SILC_STATUS_ERR_NO_SUCH_SERVER);
3716 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3717 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3718 SILC_STATUS_OK, ident, 2,
3722 strlen(entry->motd) : 0);
3723 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3724 packet->data, packet->len, FALSE);
3725 silc_buffer_free(packet);
3726 silc_buffer_free(idp);
3730 silc_server_command_free(cmd);
3733 /* Server side of command UMODE. Client can use this command to set/unset
3734 user mode. Client actually cannot set itself to be as server/router
3735 operator so this can be used only to unset the modes. */
3737 SILC_SERVER_CMD_FUNC(umode)
3739 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3740 SilcServer server = cmd->server;
3741 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3743 unsigned char *tmp_mask;
3745 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3747 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3750 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 2, 2);
3752 /* Get the client's mode mask */
3753 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3755 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3756 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3759 SILC_GET32_MSB(mask, tmp_mask);
3761 /* Check that mode changing is allowed. */
3762 if (!silc_server_check_umode_rights(server, client, mask)) {
3763 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3764 SILC_STATUS_ERR_PERM_DENIED);
3768 /* Change the mode */
3769 client->mode = mask;
3771 /* Send UMODE change to primary router */
3772 if (!server->standalone)
3773 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3774 client->id, client->mode);
3776 /* Send command reply to sender */
3777 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3778 SILC_STATUS_OK, ident, 1,
3780 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3781 packet->data, packet->len, FALSE);
3782 silc_buffer_free(packet);
3785 silc_server_command_free(cmd);
3788 /* Server side command of CMODE. Changes channel mode */
3790 SILC_SERVER_CMD_FUNC(cmode)
3792 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3793 SilcServer server = cmd->server;
3794 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3795 SilcIDListData idata = (SilcIDListData)client;
3796 SilcChannelID *channel_id;
3797 SilcChannelEntry channel;
3798 SilcChannelClientEntry chl;
3799 SilcBuffer packet, cidp;
3800 unsigned char *tmp, *tmp_id, *tmp_mask;
3801 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3802 SilcUInt32 mode_mask, tmp_len, tmp_len2;
3803 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3805 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 2, 7);
3807 /* Get Channel ID */
3808 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3810 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3811 SILC_STATUS_ERR_NO_CHANNEL_ID);
3814 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
3816 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3817 SILC_STATUS_ERR_NO_CHANNEL_ID);
3821 /* Get the channel mode mask */
3822 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3824 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3825 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3828 SILC_GET32_MSB(mode_mask, tmp_mask);
3830 /* Get channel entry */
3831 channel = silc_idlist_find_channel_by_id(server->local_list,
3834 channel = silc_idlist_find_channel_by_id(server->global_list,
3837 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3838 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3843 /* Check whether this client is on the channel */
3844 if (!silc_server_client_on_channel(client, channel, &chl)) {
3845 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3846 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3850 /* Check that client has rights to change any requested channel modes */
3851 if (!silc_server_check_cmode_rights(server, channel, chl, mode_mask)) {
3852 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3854 SILC_STATUS_ERR_NO_CHANNEL_PRIV :
3855 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV));
3860 * Check the modes. Modes that requires nothing special operation are
3864 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3865 /* Channel uses private keys to protect traffic. Client(s) has set the
3866 key locally they want to use, server does not know that key. */
3867 /* Nothing interesting to do here */
3869 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3870 /* The mode is removed and we need to generate and distribute
3871 new channel key. Clients are not using private channel keys
3872 anymore after this. */
3874 /* Re-generate channel key */
3875 if (!silc_server_create_channel_key(server, channel, 0))
3878 /* Send the channel key. This sends it to our local clients and if
3879 we are normal server to our router as well. */
3880 silc_server_send_channel_key(server, NULL, channel,
3881 server->server_type == SILC_ROUTER ?
3882 FALSE : !server->standalone);
3884 cipher = channel->channel_key->cipher->name;
3885 hmac = (char *)silc_hmac_get_name(channel->hmac);
3889 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3890 /* User limit is set on channel */
3891 SilcUInt32 user_limit;
3893 /* Get user limit */
3894 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3896 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3897 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3898 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3902 SILC_GET32_MSB(user_limit, tmp);
3903 channel->user_limit = user_limit;
3906 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3907 /* User limit mode is unset. Remove user limit */
3908 channel->user_limit = 0;
3911 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3912 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3913 /* Passphrase has been set to channel */
3915 /* Get the passphrase */
3916 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3918 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3919 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3923 /* Save the passphrase */
3924 passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
3927 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3928 /* Passphrase mode is unset. remove the passphrase */
3929 silc_free(channel->passphrase);
3930 channel->passphrase = NULL;
3934 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3935 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3936 /* Cipher to use protect the traffic */
3937 SilcCipher newkey, oldkey;
3940 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3942 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3943 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3947 /* Delete old cipher and allocate the new one */
3948 if (!silc_cipher_alloc(cipher, &newkey)) {
3949 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3950 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3954 oldkey = channel->channel_key;
3955 channel->channel_key = newkey;
3957 /* Re-generate channel key */
3958 if (!silc_server_create_channel_key(server, channel, 0)) {
3959 /* We don't have new key, revert to old one */
3960 channel->channel_key = oldkey;
3964 /* Remove old channel key for good */
3965 silc_cipher_free(oldkey);
3967 /* Send the channel key. This sends it to our local clients and if
3968 we are normal server to our router as well. */
3969 silc_server_send_channel_key(server, NULL, channel,
3970 server->server_type == SILC_ROUTER ?
3971 FALSE : !server->standalone);
3974 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3975 /* Cipher mode is unset. Remove the cipher and revert back to
3977 SilcCipher newkey, oldkey;
3978 cipher = channel->cipher;
3980 /* Delete old cipher and allocate default one */
3981 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
3982 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3983 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3987 oldkey = channel->channel_key;
3988 channel->channel_key = newkey;
3990 /* Re-generate channel key */
3991 if (!silc_server_create_channel_key(server, channel, 0)) {
3992 /* We don't have new key, revert to old one */
3993 channel->channel_key = oldkey;
3997 /* Remove old channel key for good */
3998 silc_cipher_free(oldkey);
4000 /* Send the channel key. This sends it to our local clients and if
4001 we are normal server to our router as well. */
4002 silc_server_send_channel_key(server, NULL, channel,
4003 server->server_type == SILC_ROUTER ?
4004 FALSE : !server->standalone);
4008 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
4009 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
4010 /* HMAC to use protect the traffic */
4011 unsigned char hash[32];
4015 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4017 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4018 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4022 /* Delete old hmac and allocate the new one */
4023 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4024 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4025 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4029 silc_hmac_free(channel->hmac);
4030 channel->hmac = newhmac;
4032 /* Set the HMAC key out of current channel key. The client must do
4034 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4035 channel->key_len / 8, hash);
4036 silc_hmac_set_key(channel->hmac, hash,
4037 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4038 memset(hash, 0, sizeof(hash));
4041 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4042 /* Hmac mode is unset. Remove the hmac and revert back to
4045 unsigned char hash[32];
4046 hmac = channel->hmac_name;
4048 /* Delete old hmac and allocate default one */
4049 silc_hmac_free(channel->hmac);
4050 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4051 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4052 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4056 silc_hmac_free(channel->hmac);
4057 channel->hmac = newhmac;
4059 /* Set the HMAC key out of current channel key. The client must do
4061 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4062 channel->key_len / 8,
4064 silc_hmac_set_key(channel->hmac, hash,
4065 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4066 memset(hash, 0, sizeof(hash));
4070 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4071 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4072 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4073 /* Set the founder authentication */
4074 SilcAuthPayload auth;
4076 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4078 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4079 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4083 auth = silc_auth_payload_parse(tmp, tmp_len);
4085 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4086 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4090 /* Save the public key */
4091 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
4092 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
4095 channel->founder_method = silc_auth_get_method(auth);
4097 if (channel->founder_method == SILC_AUTH_PASSWORD) {
4098 tmp = silc_auth_get_data(auth, &tmp_len);
4099 channel->founder_passwd = silc_memdup(tmp, tmp_len);
4100 channel->founder_passwd_len = tmp_len;
4102 /* Verify the payload before setting the mode */
4103 if (!silc_auth_verify(auth, channel->founder_method,
4104 channel->founder_key, 0, idata->hash,
4105 client->id, SILC_ID_CLIENT)) {
4106 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4107 SILC_STATUS_ERR_AUTH_FAILED);
4112 silc_auth_payload_free(auth);
4116 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4117 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4118 if (channel->founder_key)
4119 silc_pkcs_public_key_free(channel->founder_key);
4120 if (channel->founder_passwd) {
4121 silc_free(channel->founder_passwd);
4122 channel->founder_passwd = NULL;
4128 /* Finally, set the mode */
4129 channel->mode = mode_mask;
4131 /* Send CMODE_CHANGE notify. */
4132 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4133 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4134 SILC_NOTIFY_TYPE_CMODE_CHANGE, 5,
4135 cidp->data, cidp->len,
4137 cipher, cipher ? strlen(cipher) : 0,
4138 hmac, hmac ? strlen(hmac) : 0,
4139 passphrase, passphrase ?
4140 strlen(passphrase) : 0);
4142 /* Set CMODE notify type to network */
4143 if (!server->standalone)
4144 silc_server_send_notify_cmode(server, server->router->connection,
4145 server->server_type == SILC_ROUTER ?
4146 TRUE : FALSE, channel,
4147 mode_mask, client->id, SILC_ID_CLIENT,
4148 cipher, hmac, passphrase);
4150 /* Send command reply to sender */
4151 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4152 SILC_STATUS_OK, ident, 2,
4153 2, tmp_id, tmp_len2,
4155 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4156 packet->data, packet->len, FALSE);
4158 silc_buffer_free(packet);
4159 silc_free(channel_id);
4160 silc_buffer_free(cidp);
4163 silc_server_command_free(cmd);
4166 /* Server side of CUMODE command. Changes client's mode on a channel. */
4168 SILC_SERVER_CMD_FUNC(cumode)
4170 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4171 SilcServer server = cmd->server;
4172 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4173 SilcIDListData idata = (SilcIDListData)client;
4174 SilcChannelID *channel_id;
4175 SilcClientID *client_id;
4176 SilcChannelEntry channel;
4177 SilcClientEntry target_client;
4178 SilcChannelClientEntry chl;
4179 SilcBuffer packet, idp;
4180 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4181 SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4183 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4185 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4187 /* Get Channel ID */
4188 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4190 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4191 SILC_STATUS_ERR_NO_CHANNEL_ID);
4194 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
4196 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4197 SILC_STATUS_ERR_NO_CHANNEL_ID);
4201 /* Get channel entry */
4202 channel = silc_idlist_find_channel_by_id(server->local_list,
4205 channel = silc_idlist_find_channel_by_id(server->global_list,
4208 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4209 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4214 /* Check whether sender is on the channel */
4215 if (!silc_server_client_on_channel(client, channel, &chl)) {
4216 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4217 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4220 sender_mask = chl->mode;
4222 /* Get the target client's channel mode mask */
4223 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4225 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4226 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4229 SILC_GET32_MSB(target_mask, tmp_mask);
4231 /* Get target Client ID */
4232 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4234 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4235 SILC_STATUS_ERR_NO_CLIENT_ID);
4238 client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
4240 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4241 SILC_STATUS_ERR_NO_CLIENT_ID);
4245 /* Get target client's entry */
4246 target_client = silc_idlist_find_client_by_id(server->local_list,
4247 client_id, TRUE, NULL);
4248 if (!target_client) {
4249 target_client = silc_idlist_find_client_by_id(server->global_list,
4250 client_id, TRUE, NULL);
4253 if (target_client != client &&
4254 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4255 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4256 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4257 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4261 /* Check whether target client is on the channel */
4262 if (target_client != client) {
4263 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4264 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4265 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4274 /* If the target client is founder, no one else can change their mode
4276 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4277 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4278 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4282 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4283 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4284 /* The client tries to claim the founder rights. */
4285 unsigned char *tmp_auth;
4286 SilcUInt32 tmp_auth_len, auth_len;
4289 if (target_client != client) {
4290 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4291 SILC_STATUS_ERR_NOT_YOU);
4295 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4296 !channel->founder_key || !idata->public_key ||
4297 !silc_pkcs_public_key_compare(channel->founder_key,
4298 idata->public_key)) {
4299 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4300 SILC_STATUS_ERR_NOT_YOU);
4304 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4306 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4307 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4311 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4312 (void *)channel->founder_passwd : (void *)channel->founder_key);
4313 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4314 channel->founder_passwd_len : 0);
4316 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4317 channel->founder_method, auth, auth_len,
4318 idata->hash, client->id, SILC_ID_CLIENT)) {
4319 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4320 SILC_STATUS_ERR_AUTH_FAILED);
4324 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4328 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4329 if (target_client == client) {
4330 /* Remove channel founder rights from itself */
4331 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4334 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4335 SILC_STATUS_ERR_NOT_YOU);
4341 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4342 /* Promote to operator */
4343 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4344 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4345 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4346 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4347 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4351 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4355 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4356 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4357 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4358 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4359 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4363 /* Demote to normal user */
4364 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4369 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4370 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4372 /* Send notify to channel, notify only if mode was actually changed. */
4374 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4375 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4376 idp->data, idp->len,
4380 /* Set CUMODE notify type to network */
4381 if (!server->standalone)
4382 silc_server_send_notify_cumode(server, server->router->connection,
4383 server->server_type == SILC_ROUTER ?
4384 TRUE : FALSE, channel,
4385 target_mask, client->id,
4390 /* Send command reply to sender */
4391 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4392 SILC_STATUS_OK, ident, 3,
4394 3, tmp_ch_id, tmp_ch_len,
4395 4, tmp_id, tmp_len);
4396 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4397 packet->data, packet->len, FALSE);
4399 silc_buffer_free(packet);
4400 silc_free(channel_id);
4401 silc_free(client_id);
4402 silc_buffer_free(idp);
4405 silc_server_command_free(cmd);
4408 /* Server side of KICK command. Kicks client out of channel. */
4410 SILC_SERVER_CMD_FUNC(kick)
4412 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4413 SilcServer server = cmd->server;
4414 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4415 SilcClientEntry target_client;
4416 SilcChannelID *channel_id;
4417 SilcClientID *client_id;
4418 SilcChannelEntry channel;
4419 SilcChannelClientEntry chl;
4421 SilcUInt32 tmp_len, target_idp_len;
4422 unsigned char *tmp, *comment, *target_idp;
4424 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4426 /* Get Channel ID */
4427 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4429 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4430 SILC_STATUS_ERR_NO_CHANNEL_ID);
4433 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4435 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4436 SILC_STATUS_ERR_NO_CHANNEL_ID);
4440 /* Get channel entry */
4441 channel = silc_idlist_find_channel_by_id(server->local_list,
4444 channel = silc_idlist_find_channel_by_id(server->local_list,
4447 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4448 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4453 /* Check whether sender is on the channel */
4454 if (!silc_server_client_on_channel(client, channel, &chl)) {
4455 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4456 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4460 /* Check that the kicker is channel operator or channel founder */
4461 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4462 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4463 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4467 /* Get target Client ID */
4468 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4470 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4471 SILC_STATUS_ERR_NO_CLIENT_ID);
4474 client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
4476 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4477 SILC_STATUS_ERR_NO_CLIENT_ID);
4481 /* Get target client's entry */
4482 target_client = silc_idlist_find_client_by_id(server->local_list,
4483 client_id, TRUE, NULL);
4484 if (!target_client) {
4485 target_client = silc_idlist_find_client_by_id(server->global_list,
4486 client_id, TRUE, NULL);
4489 /* Check whether target client is on the channel */
4490 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4491 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4492 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4496 /* Check that the target client is not channel founder. Channel founder
4497 cannot be kicked from the channel. */
4498 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4499 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4500 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4506 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4510 /* Send command reply to sender */
4511 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4514 /* Send KICKED notify to local clients on the channel */
4515 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4516 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4517 SILC_NOTIFY_TYPE_KICKED, 3,
4518 target_idp, target_idp_len,
4519 comment, comment ? strlen(comment) : 0,
4520 idp->data, idp->len);
4521 silc_buffer_free(idp);
4523 /* Remove the client from the channel. If the channel does not exist
4524 after removing the client then the client kicked itself off the channel
4525 and we don't have to send anything after that. */
4526 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4527 target_client, FALSE))
4530 /* Send KICKED notify to primary route */
4531 if (!server->standalone)
4532 silc_server_send_notify_kicked(server, server->router->connection,
4533 server->server_type == SILC_ROUTER ?
4534 TRUE : FALSE, channel,
4535 target_client->id, client->id, comment);
4537 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4538 /* Re-generate channel key */
4539 if (!silc_server_create_channel_key(server, channel, 0))
4542 /* Send the channel key to the channel. The key of course is not sent
4543 to the client who was kicked off the channel. */
4544 silc_server_send_channel_key(server, target_client->connection, channel,
4545 server->server_type == SILC_ROUTER ?
4546 FALSE : !server->standalone);
4550 silc_server_command_free(cmd);
4553 /* Server side of OPER command. Client uses this comand to obtain server
4554 operator privileges to this server/router. */
4556 SILC_SERVER_CMD_FUNC(oper)
4558 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4559 SilcServer server = cmd->server;
4560 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4561 unsigned char *username, *auth;
4563 SilcServerConfigAdmin *admin;
4564 SilcIDListData idata = (SilcIDListData)client;
4565 bool result = FALSE;
4566 SilcPublicKey cached_key;
4568 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4570 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4573 /* Get the username */
4574 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4576 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4577 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4581 /* Get the admin configuration */
4582 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4583 username, client->nickname);
4585 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4586 username, client->nickname);
4588 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4589 SILC_STATUS_ERR_AUTH_FAILED);
4594 /* Get the authentication payload */
4595 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4597 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4598 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4602 /* Verify the authentication data. If both passphrase and public key
4603 is set then try both of them. */
4604 if (admin->passphrase)
4605 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4606 admin->passphrase, admin->passphrase_len,
4607 idata->hash, client->id, SILC_ID_CLIENT);
4608 if (!result && admin->publickeys) {
4609 cached_key = silc_server_get_public_key(server, admin->publickeys);
4612 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4613 cached_key, 0, idata->hash,
4614 client->id, SILC_ID_CLIENT);
4617 /* Authentication failed */
4618 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4619 SILC_STATUS_ERR_AUTH_FAILED);
4623 /* Client is now server operator */
4624 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4626 /* Update statistics */
4627 if (client->connection)
4628 server->stat.my_server_ops++;
4629 if (server->server_type == SILC_ROUTER)
4630 server->stat.server_ops++;
4632 /* Send UMODE change to primary router */
4633 if (!server->standalone)
4634 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4635 client->id, client->mode);
4637 /* Send reply to the sender */
4638 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4642 silc_server_command_free(cmd);
4645 /* Server side of SILCOPER command. Client uses this comand to obtain router
4646 operator privileges to this router. */
4648 SILC_SERVER_CMD_FUNC(silcoper)
4650 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4651 SilcServer server = cmd->server;
4652 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4653 unsigned char *username, *auth;
4655 SilcServerConfigAdmin *admin;
4656 SilcIDListData idata = (SilcIDListData)client;
4657 bool result = FALSE;
4658 SilcPublicKey cached_key;
4660 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4662 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4665 if (server->server_type != SILC_ROUTER) {
4666 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4667 SILC_STATUS_ERR_AUTH_FAILED);
4671 /* Get the username */
4672 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4674 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4675 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4679 /* Get the admin configuration */
4680 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4681 username, client->nickname);
4683 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4684 username, client->nickname);
4686 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4687 SILC_STATUS_ERR_AUTH_FAILED);
4692 /* Get the authentication payload */
4693 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4695 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4696 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4700 /* Verify the authentication data. If both passphrase and public key
4701 is set then try both of them. */
4702 if (admin->passphrase)
4703 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4704 admin->passphrase, admin->passphrase_len,
4705 idata->hash, client->id, SILC_ID_CLIENT);
4706 if (!result && admin->publickeys) {
4707 cached_key = silc_server_get_public_key(server, admin->publickeys);
4710 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4711 cached_key, 0, idata->hash,
4712 client->id, SILC_ID_CLIENT);
4715 /* Authentication failed */
4716 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4717 SILC_STATUS_ERR_AUTH_FAILED);
4721 /* Client is now router operator */
4722 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4724 /* Update statistics */
4725 if (client->connection)
4726 server->stat.my_router_ops++;
4727 if (server->server_type == SILC_ROUTER)
4728 server->stat.router_ops++;
4730 /* Send UMODE change to primary router */
4731 if (!server->standalone)
4732 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4733 client->id, client->mode);
4735 /* Send reply to the sender */
4736 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4740 silc_server_command_free(cmd);
4743 /* Server side of command BAN. This is used to manage the ban list of the
4744 channel. To add clients and remove clients from the ban list. */
4746 SILC_SERVER_CMD_FUNC(ban)
4748 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4749 SilcServer server = cmd->server;
4750 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4752 SilcChannelEntry channel;
4753 SilcChannelClientEntry chl;
4754 SilcChannelID *channel_id = NULL;
4755 unsigned char *id, *add, *del;
4756 SilcUInt32 id_len, tmp_len;
4757 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4759 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4762 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4764 /* Get Channel ID */
4765 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4767 channel_id = silc_id_payload_parse_id(id, id_len, NULL);
4769 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4770 SILC_STATUS_ERR_NO_CHANNEL_ID);
4775 /* Get channel entry. The server must know about the channel since the
4776 client is expected to be on the channel. */
4777 channel = silc_idlist_find_channel_by_id(server->local_list,
4780 channel = silc_idlist_find_channel_by_id(server->global_list,
4783 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4784 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4789 /* Check whether this client is on the channel */
4790 if (!silc_server_client_on_channel(client, channel, &chl)) {
4791 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4792 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4796 /* The client must be at least channel operator. */
4797 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4798 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4799 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4803 /* Get the new ban and add it to the ban list */
4804 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4806 if (!channel->ban_list)
4807 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4809 channel->ban_list = silc_realloc(channel->ban_list,
4810 sizeof(*channel->ban_list) *
4812 strlen(channel->ban_list) + 2));
4813 if (add[tmp_len - 1] == ',')
4814 add[tmp_len - 1] = '\0';
4816 strncat(channel->ban_list, add, tmp_len);
4817 strncat(channel->ban_list, ",", 1);
4820 /* Get the ban to be removed and remove it from the list */
4821 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4822 if (del && channel->ban_list) {
4823 char *start, *end, *n;
4825 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4826 silc_free(channel->ban_list);
4827 channel->ban_list = NULL;
4829 start = strstr(channel->ban_list, del);
4830 if (start && strlen(start) >= tmp_len) {
4831 end = start + tmp_len;
4832 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4833 strncat(n, channel->ban_list, start - channel->ban_list);
4834 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4836 silc_free(channel->ban_list);
4837 channel->ban_list = n;
4842 /* Send the BAN notify type to our primary router. */
4843 if (!server->standalone && (add || del))
4844 silc_server_send_notify_ban(server, server->router->connection,
4845 server->server_type == SILC_ROUTER ?
4846 TRUE : FALSE, channel, add, del);
4848 /* Send the reply back to the client */
4850 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4851 SILC_STATUS_OK, ident, 2,
4853 3, channel->ban_list,
4855 strlen(channel->ban_list) -1 : 0);
4856 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4857 packet->data, packet->len, FALSE);
4859 silc_buffer_free(packet);
4862 silc_free(channel_id);
4863 silc_server_command_free(cmd);
4866 /* Server side command of LEAVE. Removes client from a channel. */
4868 SILC_SERVER_CMD_FUNC(leave)
4870 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4871 SilcServer server = cmd->server;
4872 SilcSocketConnection sock = cmd->sock;
4873 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4874 SilcChannelID *id = NULL;
4875 SilcChannelEntry channel;
4879 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4881 /* Get Channel ID */
4882 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4884 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4885 SILC_STATUS_ERR_NO_CHANNEL_ID);
4888 id = silc_id_payload_parse_id(tmp, len, NULL);
4890 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4891 SILC_STATUS_ERR_NO_CHANNEL_ID);
4895 /* Get channel entry */
4896 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4898 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4900 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4901 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4906 /* Check whether this client is on the channel */
4907 if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
4908 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4909 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4913 /* Notify routers that they should remove this client from their list
4914 of clients on the channel. Send LEAVE notify type. */
4915 if (!server->standalone)
4916 silc_server_send_notify_leave(server, server->router->connection,
4917 server->server_type == SILC_ROUTER ?
4918 TRUE : FALSE, channel, id_entry->id);
4920 silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4921 SILC_STATUS_OK, 2, tmp, len);
4923 /* Remove client from channel */
4924 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4926 /* If the channel does not exist anymore we won't send anything */
4929 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4930 /* Re-generate channel key */
4931 if (!silc_server_create_channel_key(server, channel, 0))
4934 /* Send the channel key */
4935 silc_server_send_channel_key(server, NULL, channel,
4936 server->server_type == SILC_ROUTER ?
4937 FALSE : !server->standalone);
4942 silc_server_command_free(cmd);
4945 /* Server side of command USERS. Resolves clients and their USERS currently
4946 joined on the requested channel. The list of Client ID's and their modes
4947 on the channel is sent back. */
4949 SILC_SERVER_CMD_FUNC(users)
4951 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4952 SilcServer server = cmd->server;
4953 SilcChannelEntry channel;
4954 SilcChannelID *id = NULL;
4955 SilcBuffer packet, idp;
4956 unsigned char *channel_id;
4957 SilcUInt32 channel_id_len;
4958 SilcBuffer client_id_list;
4959 SilcBuffer client_mode_list;
4960 unsigned char lc[4];
4961 SilcUInt32 list_count = 0;
4962 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4965 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
4967 /* Get Channel ID */
4968 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4970 /* Get channel name */
4971 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
4973 if (!channel_id && !channel_name) {
4974 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4975 SILC_STATUS_ERR_NO_CHANNEL_ID);
4980 id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
4982 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4983 SILC_STATUS_ERR_NO_CHANNEL_ID);
4988 /* If we are server and we don't know about this channel we will send
4989 the command to our router. If we know about the channel then we also
4990 have the list of users already. */
4992 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4994 channel = silc_idlist_find_channel_by_name(server->local_list,
4995 channel_name, NULL);
4997 if (!channel || channel->disabled) {
4998 if (server->server_type != SILC_ROUTER && !server->standalone &&
5002 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5003 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5005 /* Send USERS command */
5006 silc_server_packet_send(server, server->router->connection,
5007 SILC_PACKET_COMMAND, cmd->packet->flags,
5008 tmpbuf->data, tmpbuf->len, TRUE);
5010 /* Reprocess this packet after received reply */
5011 silc_server_command_pending(server, SILC_COMMAND_USERS,
5012 silc_command_get_ident(cmd->payload),
5013 silc_server_command_users,
5014 silc_server_command_dup(cmd));
5015 cmd->pending = TRUE;
5016 silc_command_set_ident(cmd->payload, ident);
5017 silc_buffer_free(tmpbuf);
5022 /* Check the global list as well. */
5024 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5026 channel = silc_idlist_find_channel_by_name(server->global_list,
5027 channel_name, NULL);
5029 /* Channel really does not exist */
5030 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5031 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5036 /* If the channel is private or secret do not send anything, unless the
5037 user requesting this command is on the channel. */
5038 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5039 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5040 && !silc_server_client_on_channel(cmd->sock->user_data, channel,
5042 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5043 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5048 (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
5049 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5050 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5055 /* Get the users list */
5056 silc_server_get_users_on_channel(server, channel, &client_id_list,
5057 &client_mode_list, &list_count);
5060 SILC_PUT32_MSB(list_count, lc);
5063 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5064 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5065 SILC_STATUS_OK, ident, 4,
5066 2, idp->data, idp->len,
5068 4, client_id_list->data,
5069 client_id_list->len,
5070 5, client_mode_list->data,
5071 client_mode_list->len);
5072 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5073 packet->data, packet->len, FALSE);
5075 silc_buffer_free(idp);
5076 silc_buffer_free(packet);
5077 silc_buffer_free(client_id_list);
5078 silc_buffer_free(client_mode_list);
5082 silc_server_command_free(cmd);
5085 /* Server side of command GETKEY. This fetches the client's public key
5086 from the server where to the client is connected. */
5088 SILC_SERVER_CMD_FUNC(getkey)
5090 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5091 SilcServer server = cmd->server;
5093 SilcClientEntry client;
5094 SilcServerEntry server_entry;
5095 SilcClientID *client_id = NULL;
5096 SilcServerID *server_id = NULL;
5097 SilcIDPayload idp = NULL;
5098 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5099 unsigned char *tmp, *pkdata;
5100 SilcUInt32 tmp_len, pklen;
5101 SilcBuffer pk = NULL;
5103 SilcPublicKey public_key;
5105 SILC_LOG_DEBUG(("Start"));
5107 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5109 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5110 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5113 idp = silc_id_payload_parse(tmp, tmp_len);
5115 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5116 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5120 id_type = silc_id_payload_get_type(idp);
5121 if (id_type == SILC_ID_CLIENT) {
5122 client_id = silc_id_payload_get_id(idp);
5124 /* If the client is not found from local list there is no chance it
5125 would be locally connected client so send the command further. */
5126 client = silc_idlist_find_client_by_id(server->local_list,
5127 client_id, TRUE, NULL);
5129 client = silc_idlist_find_client_by_id(server->global_list,
5130 client_id, TRUE, NULL);
5132 if ((!client && !cmd->pending && !server->standalone) ||
5133 (client && !client->connection && !cmd->pending) ||
5134 (client && !client->data.public_key && !cmd->pending)) {
5136 SilcUInt16 old_ident;
5137 SilcSocketConnection dest_sock;
5139 dest_sock = silc_server_get_client_route(server, NULL, 0,
5144 old_ident = silc_command_get_ident(cmd->payload);
5145 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5146 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5148 silc_server_packet_send(server, dest_sock,
5149 SILC_PACKET_COMMAND, cmd->packet->flags,
5150 tmpbuf->data, tmpbuf->len, TRUE);
5152 /* Reprocess this packet after received reply from router */
5153 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5154 silc_command_get_ident(cmd->payload),
5155 silc_server_command_getkey,
5156 silc_server_command_dup(cmd));
5157 cmd->pending = TRUE;
5158 silc_command_set_ident(cmd->payload, old_ident);
5159 silc_buffer_free(tmpbuf);
5164 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5165 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5169 /* The client is locally connected, just get the public key and
5170 send it back. If they key does not exist then do not send it,
5171 send just OK reply */
5172 public_key = client->data.public_key;
5177 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5178 pk = silc_buffer_alloc(4 + tmp_len);
5179 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5180 silc_buffer_format(pk,
5181 SILC_STR_UI_SHORT(tmp_len),
5182 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5183 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5189 } else if (id_type == SILC_ID_SERVER) {
5190 server_id = silc_id_payload_get_id(idp);
5192 /* If the server is not found from local list there is no chance it
5193 would be locally connected server so send the command further. */
5194 server_entry = silc_idlist_find_server_by_id(server->local_list,
5195 server_id, TRUE, NULL);
5197 server_entry = silc_idlist_find_server_by_id(server->global_list,
5198 server_id, TRUE, NULL);
5200 if (server_entry != server->id_entry &&
5201 ((!server_entry && !cmd->pending && !server->standalone) ||
5202 (server_entry && !server_entry->connection && !cmd->pending &&
5203 !server->standalone) ||
5204 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5205 !server->standalone))) {
5207 SilcUInt16 old_ident;
5209 old_ident = silc_command_get_ident(cmd->payload);
5210 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5211 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5213 silc_server_packet_send(server, server->router->connection,
5214 SILC_PACKET_COMMAND, cmd->packet->flags,
5215 tmpbuf->data, tmpbuf->len, TRUE);
5217 /* Reprocess this packet after received reply from router */
5218 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5219 silc_command_get_ident(cmd->payload),
5220 silc_server_command_getkey,
5221 silc_server_command_dup(cmd));
5222 cmd->pending = TRUE;
5223 silc_command_set_ident(cmd->payload, old_ident);
5224 silc_buffer_free(tmpbuf);
5228 if (!server_entry) {
5229 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5230 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5234 /* If they key does not exist then do not send it, send just OK reply */
5235 public_key = (!server_entry->data.public_key ?
5236 (server_entry == server->id_entry ? server->public_key :
5237 NULL) : server_entry->data.public_key);
5242 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5243 pk = silc_buffer_alloc(4 + tmp_len);
5244 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5245 silc_buffer_format(pk,
5246 SILC_STR_UI_SHORT(tmp_len),
5247 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5248 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5258 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5259 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5260 SILC_STATUS_OK, ident,
5264 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5265 packet->data, packet->len, FALSE);
5266 silc_buffer_free(packet);
5269 silc_buffer_free(pk);
5273 silc_id_payload_free(idp);
5274 silc_free(client_id);
5275 silc_free(server_id);
5276 silc_server_command_free(cmd);
5280 /* Private range commands, specific to this implementation */
5282 /* Server side command of CONNECT. Connects us to the specified remote
5283 server or router. */
5285 SILC_SERVER_CMD_FUNC(connect)
5287 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5288 SilcServer server = cmd->server;
5289 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5290 unsigned char *tmp, *host;
5292 SilcUInt32 port = SILC_PORT;
5294 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
5296 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5299 /* Check whether client has the permissions. */
5300 if (client->mode == SILC_UMODE_NONE) {
5301 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5302 SILC_STATUS_ERR_NO_SERVER_PRIV);
5306 if (server->server_type == SILC_ROUTER &&
5307 client->mode & SILC_UMODE_SERVER_OPERATOR) {
5308 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5309 SILC_STATUS_ERR_NO_ROUTER_PRIV);
5313 /* Get the remote server */
5314 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5316 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5317 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5322 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5324 SILC_GET32_MSB(port, tmp);
5326 /* Create the connection. It is done with timeout and is async. */
5327 silc_server_create_connection(server, host, port);
5329 /* Send reply to the sender */
5330 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5334 silc_server_command_free(cmd);
5337 /* Server side command of CLOSE. Closes connection to a specified server. */
5339 SILC_SERVER_CMD_FUNC(close)
5341 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5342 SilcServer server = cmd->server;
5343 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5344 SilcServerEntry server_entry;
5345 SilcSocketConnection sock;
5348 unsigned char *name;
5349 SilcUInt32 port = SILC_PORT;
5351 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
5353 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5356 /* Check whether client has the permissions. */
5357 if (client->mode == SILC_UMODE_NONE) {
5358 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5359 SILC_STATUS_ERR_NO_SERVER_PRIV);
5363 /* Get the remote server */
5364 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5366 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5367 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5372 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5374 SILC_GET32_MSB(port, tmp);
5376 server_entry = silc_idlist_find_server_by_conn(server->local_list,
5377 name, port, FALSE, NULL);
5379 server_entry = silc_idlist_find_server_by_conn(server->global_list,
5380 name, port, FALSE, NULL);
5381 if (!server_entry) {
5382 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5383 SILC_STATUS_ERR_NO_SERVER_ID);
5387 /* Send reply to the sender */
5388 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5391 /* Close the connection to the server */
5392 sock = (SilcSocketConnection)server_entry->connection;
5394 /* If we shutdown primary router connection manually then don't trigger
5395 any reconnect or backup router connections, by setting the router
5397 if (server->router == server_entry) {
5398 server->id_entry->router = NULL;
5399 server->router = NULL;
5400 server->standalone = TRUE;
5402 silc_server_free_sock_user_data(server, sock, NULL);
5403 silc_server_close_connection(server, sock);
5406 silc_server_command_free(cmd);
5409 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
5410 active connections. */
5412 SILC_SERVER_CMD_FUNC(shutdown)
5414 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5415 SilcServer server = cmd->server;
5416 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5418 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
5420 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5423 /* Check whether client has the permission. */
5424 if (client->mode == SILC_UMODE_NONE) {
5425 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5426 SILC_STATUS_ERR_NO_SERVER_PRIV);
5430 /* Send reply to the sender */
5431 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5434 /* Then, gracefully, or not, bring the server down. */
5435 silc_server_stop(server);
5439 silc_server_command_free(cmd);