5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2001 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(connect, CONNECT,
60 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
61 SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
62 SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
63 SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG_STRICT | SILC_CF_REG),
64 SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
65 SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
66 SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG_STRICT | SILC_CF_REG),
67 SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
68 SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
69 SILC_SERVER_CMD(ban, BAN, SILC_CF_LAG_STRICT | SILC_CF_REG),
70 SILC_SERVER_CMD(close, CLOSE,
71 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
72 SILC_SERVER_CMD(shutdown, SHUTDOWN, SILC_CF_LAG | SILC_CF_REG |
74 SILC_SERVER_CMD(silcoper, SILCOPER,
75 SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
76 SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
77 SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
78 SILC_SERVER_CMD(getkey, GETKEY, SILC_CF_LAG | SILC_CF_REG),
83 /* Performs several checks to the command. It first checks whether this
84 command was called as pending command callback. If it was then it checks
85 whether error occurred in the command reply where the pending command
88 It also checks that the requested command includes correct amount
90 #define SILC_SERVER_COMMAND_CHECK(command, context, min, max) \
94 SILC_LOG_DEBUG(("Start")); \
96 if (silc_server_command_pending_error_check(cmd, context2, command)) { \
97 silc_server_command_free(cmd); \
101 _argc = silc_argument_get_arg_num(cmd->args); \
103 silc_server_command_send_status_reply(cmd, command, \
104 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
105 silc_server_command_free(cmd); \
109 silc_server_command_send_status_reply(cmd, command, \
110 SILC_STATUS_ERR_TOO_MANY_PARAMS); \
111 silc_server_command_free(cmd); \
116 /* Returns TRUE if the connection is registered. Unregistered connections
117 usually cannot send commands hence the check. */
119 static int silc_server_is_registered(SilcServer server,
120 SilcSocketConnection sock,
121 SilcServerCommandContext cmd,
124 SilcIDListData idata = (SilcIDListData)sock->user_data;
129 if (idata->status & SILC_IDLIST_STATUS_REGISTERED)
132 silc_server_command_send_status_reply(cmd, command,
133 SILC_STATUS_ERR_NOT_REGISTERED);
137 /* Internal context to hold data when executed command with timeout. */
139 SilcServerCommandContext ctx;
140 SilcServerCommand *cmd;
141 } *SilcServerCommandTimeout;
143 /* Timeout callback to process commands with timeout for client. Client's
144 commands are always executed with timeout. */
146 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
148 SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
149 SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data;
152 silc_server_command_free(timeout->ctx);
156 /* Update access time */
157 client->last_command = time(NULL);
159 if (!(timeout->cmd->flags & SILC_CF_REG))
160 timeout->cmd->cb(timeout->ctx, NULL);
161 else if (silc_server_is_registered(timeout->ctx->server,
165 timeout->cmd->cb(timeout->ctx, NULL);
167 silc_server_command_free(timeout->ctx);
172 /* Processes received command packet. */
174 void silc_server_command_process(SilcServer server,
175 SilcSocketConnection sock,
176 SilcPacketContext *packet)
178 SilcServerCommandContext ctx;
179 SilcServerCommand *cmd;
182 /* Allocate command context. This must be free'd by the
183 command routine receiving it. */
184 ctx = silc_server_command_alloc();
185 ctx->server = server;
186 ctx->sock = silc_socket_dup(sock);
187 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
189 /* Parse the command payload in the packet */
190 ctx->payload = silc_command_payload_parse(packet->buffer->data,
191 packet->buffer->len);
193 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
194 silc_buffer_free(packet->buffer);
195 silc_packet_context_free(packet);
196 silc_socket_free(ctx->sock);
200 ctx->args = silc_command_get_args(ctx->payload);
202 /* Get the command */
203 command = silc_command_get(ctx->payload);
204 for (cmd = silc_command_list; cmd->cb; cmd++)
205 if (cmd->cmd == command)
209 silc_server_command_send_status_reply(ctx, command,
210 SILC_STATUS_ERR_UNKNOWN_COMMAND);
211 silc_server_command_free(ctx);
215 /* Execute client's commands always with timeout. Normally they are
216 executed with zero (0) timeout but if client is sending command more
217 frequently than once in 2 seconds, then the timeout may be 0 to 2
219 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
220 SilcClientEntry client = (SilcClientEntry)sock->user_data;
221 SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
227 if (client->last_command && (time(NULL) - client->last_command) < 2) {
228 client->fast_command++;
231 client->fast_command = ((client->fast_command - 1) <= 0 ? 0 :
232 client->fast_command--);
236 if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
237 (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
238 silc_schedule_task_add(server->schedule, sock->sock,
239 silc_server_command_process_timeout,
241 2 - (time(NULL) - client->last_command), 0,
242 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
244 silc_schedule_task_add(server->schedule, sock->sock,
245 silc_server_command_process_timeout,
246 (void *)timeout, 0, 1,
247 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
251 /* Execute for server */
253 if (!(cmd->flags & SILC_CF_REG))
255 else if (silc_server_is_registered(server, sock, ctx, cmd->cmd))
258 silc_server_command_free(ctx);
261 /* Allocate Command Context */
263 SilcServerCommandContext silc_server_command_alloc()
265 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
270 /* Free's the command context allocated before executing the command */
272 void silc_server_command_free(SilcServerCommandContext ctx)
275 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
277 if (ctx->users < 1) {
279 silc_command_payload_free(ctx->payload);
281 silc_packet_context_free(ctx->packet);
283 silc_socket_free(ctx->sock); /* Decrease reference counter */
288 /* Duplicate Command Context by adding reference counter. The context won't
289 be free'd untill it hits zero. */
291 SilcServerCommandContext
292 silc_server_command_dup(SilcServerCommandContext ctx)
295 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
300 /* Add new pending command to be executed when reply to a command has been
301 received. The `reply_cmd' is the command that will call the `callback'
302 with `context' when reply has been received. It can be SILC_COMMAND_NONE
303 to match any command with the `ident'. If `ident' is non-zero
304 the `callback' will be executed when received reply with command
305 identifier `ident'. If there already exists pending command for the
306 specified command, ident, callback and context this function has no
309 bool silc_server_command_pending(SilcServer server,
310 SilcCommand reply_cmd,
312 SilcCommandCb callback,
315 SilcServerCommandPending *reply;
317 /* Check whether identical pending already exists for same command,
318 ident, callback and callback context. If it does then it would be
319 error to register it again. */
320 silc_dlist_start(server->pending_commands);
321 while ((reply = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
322 if (reply->reply_cmd == reply_cmd && reply->ident == ident &&
323 reply->callback == callback && reply->context == context)
327 reply = silc_calloc(1, sizeof(*reply));
328 reply->reply_cmd = reply_cmd;
329 reply->ident = ident;
330 reply->context = context;
331 reply->callback = callback;
332 silc_dlist_add(server->pending_commands, reply);
337 /* Deletes pending command by reply command type. */
339 void silc_server_command_pending_del(SilcServer server,
340 SilcCommand reply_cmd,
343 SilcServerCommandPending *r;
345 silc_dlist_start(server->pending_commands);
346 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
347 if (r->reply_cmd == reply_cmd && r->ident == ident) {
348 silc_dlist_del(server->pending_commands, r);
354 /* Checks for pending commands and marks callbacks to be called from
355 the command reply function. Returns TRUE if there were pending command. */
357 SilcServerCommandPendingCallbacks
358 silc_server_command_pending_check(SilcServer server,
359 SilcServerCommandReplyContext ctx,
362 SilcUInt32 *callbacks_count)
364 SilcServerCommandPending *r;
365 SilcServerCommandPendingCallbacks callbacks = NULL;
368 silc_dlist_start(server->pending_commands);
369 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
370 if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE)
371 && r->ident == ident) {
372 callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
373 callbacks[i].context = r->context;
374 callbacks[i].callback = r->callback;
380 *callbacks_count = i;
384 /* Sends simple status message as command reply packet */
387 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
389 SilcCommandStatus status)
393 SILC_LOG_DEBUG(("Sending command status %d", status));
396 silc_command_reply_payload_encode_va(command, status,
397 silc_command_get_ident(cmd->payload),
399 silc_server_packet_send(cmd->server, cmd->sock,
400 SILC_PACKET_COMMAND_REPLY, 0,
401 buffer->data, buffer->len, FALSE);
402 silc_buffer_free(buffer);
405 /* Sends command status reply with one extra argument. The argument
406 type must be sent as argument. */
409 silc_server_command_send_status_data(SilcServerCommandContext cmd,
411 SilcCommandStatus status,
413 const unsigned char *arg,
418 SILC_LOG_DEBUG(("Sending command status %d", status));
421 silc_command_reply_payload_encode_va(command, status,
422 silc_command_get_ident(cmd->payload),
423 1, arg_type, arg, arg_len);
424 silc_server_packet_send(cmd->server, cmd->sock,
425 SILC_PACKET_COMMAND_REPLY, 0,
426 buffer->data, buffer->len, FALSE);
427 silc_buffer_free(buffer);
430 /* This function can be called to check whether in the command reply
431 an error occurred. This function has no effect if this is called
432 when the command function was not called as pending command callback.
433 This returns TRUE if error had occurred. */
436 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
437 SilcServerCommandReplyContext cmdr,
440 SilcCommandStatus status;
442 if (!cmd->pending || !cmdr)
445 SILC_GET16_MSB(status, silc_argument_get_arg_type(cmdr->args, 1, NULL));
446 if (status != SILC_STATUS_OK &&
447 status != SILC_STATUS_LIST_START &&
448 status != SILC_STATUS_LIST_ITEM &&
449 status != SILC_STATUS_LIST_END) {
452 /* Send the same command reply payload */
453 silc_command_set_ident(cmdr->payload,
454 silc_command_get_ident(cmd->payload));
455 buffer = silc_command_payload_encode_payload(cmdr->payload);
456 silc_server_packet_send(cmd->server, cmd->sock,
457 SILC_PACKET_COMMAND_REPLY, 0,
458 buffer->data, buffer->len, FALSE);
459 silc_buffer_free(buffer);
466 /******************************************************************************
470 ******************************************************************************/
473 silc_server_command_whois_parse(SilcServerCommandContext cmd,
474 SilcClientID ***client_id,
475 SilcUInt32 *client_id_count,
483 SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
486 /* If client ID is in the command it must be used instead of nickname */
487 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
489 /* No ID, get the nickname@server string and parse it. */
490 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
492 silc_parse_userfqdn(tmp, nickname, server_name);
494 silc_server_command_send_status_reply(cmd, command,
495 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
499 /* Command includes ID, we must use that. Also check whether the command
500 has more than one ID set - take them all. */
502 *client_id = silc_calloc(1, sizeof(**client_id));
503 (*client_id)[0] = silc_id_payload_parse_id(tmp, len, NULL);
504 if ((*client_id)[0] == NULL) {
505 silc_free(*client_id);
506 silc_server_command_send_status_reply(cmd, command,
507 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
510 *client_id_count = 1;
512 /* Take all ID's from the command packet */
514 for (k = 1, i = 1; i < argc; i++) {
515 tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
517 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
518 (*client_id_count + 1));
519 (*client_id)[k] = silc_id_payload_parse_id(tmp, len, NULL);
520 if ((*client_id)[k] == NULL) {
521 /* Cleanup all and fail */
522 for (i = 0; i < *client_id_count; i++)
523 silc_free((*client_id)[i]);
524 silc_free(*client_id);
525 silc_server_command_send_status_reply(
527 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
530 (*client_id_count)++;
537 /* Get the max count of reply messages allowed */
538 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
547 /* Resolve context used by both WHOIS and IDENTIFY commands */
549 SilcServerEntry router;
551 unsigned char **res_argv;
552 SilcUInt32 *res_argv_lens;
553 SilcUInt32 *res_argv_types;
555 } *SilcServerResolveContext;
558 silc_server_command_whois_check(SilcServerCommandContext cmd,
559 SilcClientEntry *clients,
560 SilcUInt32 clients_count)
562 SilcServer server = cmd->server;
563 SilcClientEntry entry;
564 SilcServerResolveContext resolve = NULL, r = NULL;
565 SilcUInt32 resolve_count = 0;
569 SILC_LOG_DEBUG(("Start"));
571 for (i = 0; i < clients_count; i++) {
576 if ((entry->nickname && entry->username && entry->userinfo) ||
577 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
581 /* If we are normal server, and we've not resolved this client from
582 router and it is global client, we'll check whether it is on some
583 channel. If not then we cannot be sure about its validity, and
584 we'll resolve it from router. */
585 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
586 entry->connection || silc_hash_table_count(entry->channels))
590 /* We need to resolve this entry since it is not complete */
592 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
593 /* The entry is being resolved (and we are not the resolver) so attach
594 to the command reply and we're done with this one. */
595 silc_server_command_pending(server, SILC_COMMAND_NONE,
596 entry->resolve_cmd_ident,
597 silc_server_command_whois,
598 silc_server_command_dup(cmd));
601 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
602 /* We've resolved this and it still is not ready. We'll return
603 and are that this will be handled again after it is resolved. */
604 for (i = 0; i < resolve_count; i++) {
605 for (k = 0; k < r->res_argc; k++)
606 silc_free(r->res_argv[k]);
607 silc_free(r->res_argv);
608 silc_free(r->res_argv_lens);
609 silc_free(r->res_argv_types);
614 /* We'll resolve this client */
618 for (k = 0; k < resolve_count; k++) {
619 if (resolve[k].router == entry->router) {
626 resolve = silc_realloc(resolve, sizeof(*resolve) *
627 (resolve_count + 1));
628 r = &resolve[resolve_count];
629 memset(r, 0, sizeof(*r));
630 r->router = entry->router;
631 r->ident = ++server->cmd_ident;
635 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
637 r->res_argv_lens = silc_realloc(r->res_argv_lens,
638 sizeof(*r->res_argv_lens) *
640 r->res_argv_types = silc_realloc(r->res_argv_types,
641 sizeof(*r->res_argv_types) *
643 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
644 r->res_argv[r->res_argc] = silc_calloc(idp->len,
645 sizeof(**r->res_argv));
646 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
647 r->res_argv_lens[r->res_argc] = idp->len;
648 r->res_argv_types[r->res_argc] = r->res_argc + 3;
650 silc_buffer_free(idp);
652 entry->resolve_cmd_ident = r->ident;
653 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
654 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
659 /* Do the resolving */
660 for (i = 0; i < resolve_count; i++) {
665 /* Send WHOIS request. We send WHOIS since we're doing the requesting
666 now anyway so make it a good one. */
667 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
668 r->res_argc, r->res_argv,
672 silc_server_packet_send(server, r->router->connection,
673 SILC_PACKET_COMMAND, cmd->packet->flags,
674 res_cmd->data, res_cmd->len, FALSE);
676 /* Reprocess this packet after received reply */
677 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
679 silc_server_command_whois,
680 silc_server_command_dup(cmd));
683 silc_buffer_free(res_cmd);
684 for (k = 0; k < r->res_argc; k++)
685 silc_free(r->res_argv[k]);
686 silc_free(r->res_argv);
687 silc_free(r->res_argv_lens);
688 silc_free(r->res_argv_types);
697 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
698 SilcClientEntry *clients,
699 SilcUInt32 clients_count,
701 const char *nickname,
702 SilcClientID **client_ids)
704 SilcServer server = cmd->server;
706 int i, k, len, valid_count;
707 SilcBuffer packet, idp, channels;
708 SilcClientEntry entry;
709 SilcCommandStatus status;
710 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
711 char nh[256], uh[256];
712 unsigned char idle[4], mode[4];
713 unsigned char *fingerprint;
714 SilcSocketConnection hsock;
716 /* Process only valid clients and ignore those that are not registered. */
718 for (i = 0; i < clients_count; i++) {
719 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
726 /* No valid clients found, send error reply */
728 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
729 SILC_STATUS_ERR_NO_SUCH_NICK,
730 3, nickname, strlen(nickname));
731 } else if (client_ids && client_ids[0]) {
732 SilcBuffer idp = silc_id_payload_encode(client_ids[0], SILC_ID_CLIENT);
733 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
734 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
735 2, idp->data, idp->len);
736 silc_buffer_free(idp);
741 /* Start processing found clients. */
743 status = SILC_STATUS_LIST_START;
745 status = SILC_STATUS_OK;
747 for (i = 0, k = 0; i < clients_count; i++) {
753 status = SILC_STATUS_LIST_ITEM;
754 if (valid_count > 1 && k == valid_count - 1)
755 status = SILC_STATUS_LIST_END;
756 if (count && k - 1 == count)
757 status = SILC_STATUS_LIST_END;
759 /* Send WHOIS reply */
760 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
761 tmp = silc_argument_get_first_arg(cmd->args, NULL);
763 memset(uh, 0, sizeof(uh));
764 memset(nh, 0, sizeof(nh));
765 memset(idle, 0, sizeof(idle));
767 strncat(nh, entry->nickname, strlen(entry->nickname));
768 if (!strchr(entry->nickname, '@')) {
770 if (entry->servername) {
771 strncat(nh, entry->servername, strlen(entry->servername));
773 len = entry->router ? strlen(entry->router->server_name) :
774 strlen(server->server_name);
775 strncat(nh, entry->router ? entry->router->server_name :
776 server->server_name, len);
780 strncat(uh, entry->username, strlen(entry->username));
781 if (!strchr(entry->username, '@')) {
783 hsock = (SilcSocketConnection)entry->connection;
784 len = strlen(hsock->hostname);
785 strncat(uh, hsock->hostname, len);
788 channels = silc_server_get_client_channel_list(server, entry);
790 if (entry->data.fingerprint[0] != 0 && entry->data.fingerprint[1] != 0)
791 fingerprint = entry->data.fingerprint;
795 SILC_PUT32_MSB(entry->mode, mode);
797 if (entry->connection) {
798 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
802 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
804 2, idp->data, idp->len,
808 strlen(entry->userinfo),
809 6, channels ? channels->data : NULL,
810 channels ? channels->len : 0,
814 fingerprint ? 20 : 0);
816 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
817 0, packet->data, packet->len, FALSE);
819 silc_buffer_free(packet);
820 silc_buffer_free(idp);
822 silc_buffer_free(channels);
829 silc_server_command_whois_send_router(SilcServerCommandContext cmd)
831 SilcServer server = cmd->server;
833 SilcUInt16 old_ident;
835 old_ident = silc_command_get_ident(cmd->payload);
836 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
837 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
839 /* Send WHOIS command to our router */
840 silc_server_packet_send(server, (SilcSocketConnection)
841 server->router->connection,
842 SILC_PACKET_COMMAND, cmd->packet->flags,
843 tmpbuf->data, tmpbuf->len, TRUE);
845 /* Reprocess this packet after received reply from router */
846 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
847 silc_command_get_ident(cmd->payload),
848 silc_server_command_whois,
849 silc_server_command_dup(cmd));
851 silc_command_set_ident(cmd->payload, old_ident);
852 silc_buffer_free(tmpbuf);
856 silc_server_command_whois_process(SilcServerCommandContext cmd)
858 SilcServer server = cmd->server;
859 char *nick = NULL, *server_name = NULL;
861 SilcClientEntry *clients = NULL, entry;
862 SilcClientID **client_id = NULL;
863 SilcUInt32 client_id_count = 0, clients_count = 0;
865 bool check_global = FALSE;
867 /* Parse the whois request */
868 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
869 &nick, &server_name, &count,
873 /* Send the WHOIS request to the router only if it included nickname.
874 Since nicknames can be expanded into many clients we need to send it
875 to router. If the WHOIS included only client ID's we will check them
876 first locally since we just might have them. */
877 if (nick && !client_id_count && cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
878 server->server_type == SILC_SERVER && !cmd->pending &&
879 !server->standalone) {
880 silc_server_command_whois_send_router(cmd);
885 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
887 else if (server->server_type != SILC_SERVER)
890 /* Get all clients matching that ID or nickname from local list */
891 if (client_id_count) {
892 /* Check all Client ID's received in the command packet */
893 for (i = 0; i < client_id_count; i++) {
894 entry = silc_idlist_find_client_by_id(server->local_list,
895 client_id[i], TRUE, NULL);
896 if (!entry && check_global)
897 entry = silc_idlist_find_client_by_id(server->global_list,
898 client_id[i], TRUE, NULL);
900 clients = silc_realloc(clients, sizeof(*clients) *
901 (clients_count + 1));
902 clients[clients_count++] = entry;
904 /* If we are normal server and did not send the request first to router
905 do it now, since we do not have the Client ID information. */
906 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
907 server->server_type == SILC_SERVER && !cmd->pending &&
908 !server->standalone) {
909 silc_server_command_whois_send_router(cmd);
916 /* Find by nickname */
917 if (!silc_idlist_get_clients_by_hash(server->local_list,
918 nick, server->md5hash,
919 &clients, &clients_count))
920 silc_idlist_get_clients_by_nickname(server->local_list,
922 &clients, &clients_count);
924 if (!silc_idlist_get_clients_by_hash(server->global_list,
925 nick, server->md5hash,
926 &clients, &clients_count))
927 silc_idlist_get_clients_by_nickname(server->global_list,
929 &clients, &clients_count);
934 /* If we are normal server and did not send the request first to router
935 do it now, since we do not have the information. */
936 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
937 server->server_type == SILC_SERVER && !cmd->pending &&
938 !server->standalone) {
939 silc_server_command_whois_send_router(cmd);
944 /* Such client(s) really does not exist in the SILC network. */
945 if (!client_id_count) {
946 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
947 SILC_STATUS_ERR_NO_SUCH_NICK,
948 3, nick, strlen(nick));
950 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
951 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
952 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
953 2, idp->data, idp->len);
954 silc_buffer_free(idp);
959 /* Router always finds the client entry if it exists in the SILC network.
960 However, it might be incomplete entry and does not include all the
961 mandatory fields that WHOIS command reply requires. Check for these and
962 make query from the server who owns the client if some fields are
964 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
969 /* Send the command reply */
970 silc_server_command_whois_send_reply(cmd, clients, clients_count,
971 count, nick, client_id);
974 if (client_id_count) {
975 for (i = 0; i < client_id_count; i++)
976 silc_free(client_id[i]);
977 silc_free(client_id);
981 silc_free(server_name);
986 /* Server side of command WHOIS. Processes user's query and sends found
987 results as command replies back to the client. */
989 SILC_SERVER_CMD_FUNC(whois)
991 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
994 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 3328);
996 ret = silc_server_command_whois_process(cmd);
997 silc_server_command_free(cmd);
1000 /******************************************************************************
1004 ******************************************************************************/
1007 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
1015 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1017 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
1018 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1022 /* Get the nickname@server string and parse it. */
1023 silc_parse_userfqdn(tmp, nickname, server_name);
1025 /* Get the max count of reply messages allowed */
1026 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1036 silc_server_command_whowas_check(SilcServerCommandContext cmd,
1037 SilcClientEntry *clients,
1038 SilcUInt32 clients_count)
1040 SilcServer server = cmd->server;
1042 SilcClientEntry entry;
1044 for (i = 0; i < clients_count; i++) {
1047 if (!entry->nickname || !entry->username) {
1049 SilcUInt16 old_ident;
1054 old_ident = silc_command_get_ident(cmd->payload);
1055 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1056 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1058 /* Send WHOWAS command */
1059 silc_server_packet_send(server, entry->router->connection,
1060 SILC_PACKET_COMMAND, cmd->packet->flags,
1061 tmpbuf->data, tmpbuf->len, TRUE);
1063 /* Reprocess this packet after received reply */
1064 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1065 silc_command_get_ident(cmd->payload),
1066 silc_server_command_whowas,
1067 silc_server_command_dup(cmd));
1068 cmd->pending = TRUE;
1069 silc_command_set_ident(cmd->payload, old_ident);
1071 silc_buffer_free(tmpbuf);
1080 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1081 SilcClientEntry *clients,
1082 SilcUInt32 clients_count)
1084 SilcServer server = cmd->server;
1086 int i, k, count = 0, len;
1087 SilcBuffer packet, idp;
1088 SilcClientEntry entry = NULL;
1089 SilcCommandStatus status;
1090 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1091 char nh[256], uh[256];
1094 status = SILC_STATUS_OK;
1096 /* Process only entries that are not registered anymore. */
1098 for (i = 0; i < clients_count; i++) {
1099 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1106 /* No valid entries found at all, just send error */
1109 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1111 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1112 SILC_STATUS_ERR_NO_SUCH_NICK,
1113 3, tmp, strlen(tmp));
1117 if (valid_count > 1)
1118 status = SILC_STATUS_LIST_START;
1120 for (i = 0, k = 0; i < clients_count; i++) {
1126 status = SILC_STATUS_LIST_ITEM;
1127 if (valid_count > 1 && k == valid_count - 1)
1128 status = SILC_STATUS_LIST_END;
1129 if (count && k - 1 == count)
1130 status = SILC_STATUS_LIST_END;
1131 if (count && k - 1 > count)
1134 /* Send WHOWAS reply */
1135 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1136 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1137 memset(uh, 0, sizeof(uh));
1138 memset(nh, 0, sizeof(nh));
1140 strncat(nh, entry->nickname, strlen(entry->nickname));
1141 if (!strchr(entry->nickname, '@')) {
1142 strncat(nh, "@", 1);
1143 if (entry->servername) {
1144 strncat(nh, entry->servername, strlen(entry->servername));
1146 len = entry->router ? strlen(entry->router->server_name) :
1147 strlen(server->server_name);
1148 strncat(nh, entry->router ? entry->router->server_name :
1149 server->server_name, len);
1153 strncat(uh, entry->username, strlen(entry->username));
1154 if (!strchr(entry->username, '@')) {
1155 strncat(uh, "@", 1);
1156 strcat(uh, "*private*");
1160 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1162 2, idp->data, idp->len,
1167 strlen(entry->userinfo) : 0);
1168 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1169 0, packet->data, packet->len, FALSE);
1171 silc_buffer_free(packet);
1172 silc_buffer_free(idp);
1179 silc_server_command_whowas_process(SilcServerCommandContext cmd)
1181 SilcServer server = cmd->server;
1182 char *nick = NULL, *server_name = NULL;
1184 SilcClientEntry *clients = NULL;
1185 SilcUInt32 clients_count = 0;
1187 bool check_global = FALSE;
1189 /* Protocol dictates that we must always send the received WHOWAS request
1190 to our router if we are normal server, so let's do it now unless we
1191 are standalone. We will not send any replies to the client until we
1192 have received reply from the router. */
1193 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1194 server->server_type == SILC_SERVER && !cmd->pending &&
1195 !server->standalone) {
1197 SilcUInt16 old_ident;
1199 old_ident = silc_command_get_ident(cmd->payload);
1200 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1201 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1203 /* Send WHOWAS command to our router */
1204 silc_server_packet_send(server, (SilcSocketConnection)
1205 server->router->connection,
1206 SILC_PACKET_COMMAND, cmd->packet->flags,
1207 tmpbuf->data, tmpbuf->len, TRUE);
1209 /* Reprocess this packet after received reply from router */
1210 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1211 silc_command_get_ident(cmd->payload),
1212 silc_server_command_whowas,
1213 silc_server_command_dup(cmd));
1214 cmd->pending = TRUE;
1215 silc_command_set_ident(cmd->payload, old_ident);
1217 silc_buffer_free(tmpbuf);
1222 /* We are ready to process the command request. Let's search for the
1223 requested client and send reply to the requesting client. */
1225 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1226 check_global = TRUE;
1227 else if (server->server_type != SILC_SERVER)
1228 check_global = TRUE;
1230 /* Parse the whowas request */
1231 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1234 /* Get all clients matching that nickname from local list */
1235 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1237 &clients, &clients_count))
1238 silc_idlist_get_clients_by_hash(server->local_list,
1239 nick, server->md5hash,
1240 &clients, &clients_count);
1242 /* Check global list as well */
1244 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1246 &clients, &clients_count))
1247 silc_idlist_get_clients_by_hash(server->global_list,
1248 nick, server->md5hash,
1249 &clients, &clients_count);
1253 /* Such a client really does not exist in the SILC network. */
1254 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1255 SILC_STATUS_ERR_NO_SUCH_NICK,
1256 3, nick, strlen(nick));
1260 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1265 /* Send the command reply to the client */
1266 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1271 silc_free(server_name);
1275 /* Server side of command WHOWAS. */
1277 SILC_SERVER_CMD_FUNC(whowas)
1279 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1282 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1284 ret = silc_server_command_whowas_process(cmd);
1285 silc_server_command_free(cmd);
1288 /******************************************************************************
1292 ******************************************************************************/
1295 silc_server_command_identify_send_router(SilcServerCommandContext cmd)
1297 SilcServer server = cmd->server;
1299 SilcUInt16 old_ident;
1301 old_ident = silc_command_get_ident(cmd->payload);
1302 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1303 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1305 /* Send IDENTIFY command to our router */
1306 silc_server_packet_send(server, (SilcSocketConnection)
1307 server->router->connection,
1308 SILC_PACKET_COMMAND, cmd->packet->flags,
1309 tmpbuf->data, tmpbuf->len, TRUE);
1311 /* Reprocess this packet after received reply from router */
1312 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1313 silc_command_get_ident(cmd->payload),
1314 silc_server_command_identify,
1315 silc_server_command_dup(cmd));
1316 cmd->pending = TRUE;
1317 silc_command_set_ident(cmd->payload, old_ident);
1318 silc_buffer_free(tmpbuf);
1322 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1323 SilcClientEntry **clients,
1324 SilcUInt32 *clients_count,
1325 SilcServerEntry **servers,
1326 SilcUInt32 *servers_count,
1327 SilcChannelEntry **channels,
1328 SilcUInt32 *channels_count,
1331 SilcServer server = cmd->server;
1334 SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
1336 bool check_global = FALSE;
1341 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1342 check_global = TRUE;
1343 else if (server->server_type != SILC_SERVER)
1344 check_global = TRUE;
1346 /* If ID Payload is in the command it must be used instead of names */
1347 tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1349 /* No ID, get the names. */
1351 /* If we are normal server and have not resolved information from
1352 router yet, do so now. */
1353 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1354 server->server_type == SILC_SERVER && !cmd->pending &&
1355 !server->standalone) {
1356 silc_server_command_identify_send_router(cmd);
1360 /* Try to get nickname@server. */
1361 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1364 char *nick_server = NULL;
1366 silc_parse_userfqdn(tmp, &nick, &nick_server);
1368 if (!silc_idlist_get_clients_by_hash(server->local_list,
1369 nick, server->md5hash,
1370 clients, clients_count))
1371 silc_idlist_get_clients_by_nickname(server->local_list,
1373 clients, clients_count);
1375 if (!silc_idlist_get_clients_by_hash(server->global_list,
1376 nick, server->md5hash,
1377 clients, clients_count))
1378 silc_idlist_get_clients_by_nickname(server->global_list,
1380 clients, clients_count);
1384 silc_free(nick_server);
1387 /* the nickname does not exist, send error reply */
1388 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1389 SILC_STATUS_ERR_NO_SUCH_NICK,
1390 3, tmp, strlen(tmp));
1395 /* Try to get server name */
1396 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1398 entry = silc_idlist_find_server_by_name(server->local_list,
1400 if (!entry && check_global)
1401 entry = silc_idlist_find_server_by_name(server->global_list,
1404 *servers = silc_realloc(*servers, sizeof(**servers) *
1405 (*servers_count + 1));
1406 (*servers)[(*servers_count)++] = entry;
1410 /* the server does not exist, send error reply */
1411 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1412 SILC_STATUS_ERR_NO_SUCH_SERVER,
1413 3, tmp, strlen(tmp));
1418 /* Try to get channel name */
1419 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1421 entry = silc_idlist_find_channel_by_name(server->local_list,
1423 if (!entry && check_global)
1424 entry = silc_idlist_find_channel_by_name(server->global_list,
1427 *channels = silc_realloc(*channels, sizeof(**channels) *
1428 (*channels_count + 1));
1429 (*channels)[(*channels_count)++] = entry;
1433 /* The channel does not exist, send error reply */
1434 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1435 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1436 3, tmp, strlen(tmp));
1441 if (!(*clients) && !(*servers) && !(*channels)) {
1442 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1443 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1447 /* Command includes ID, we must use that. Also check whether the command
1448 has more than one ID set - take them all. */
1450 /* Take all ID's from the command packet */
1451 for (i = 0; i < argc; i++) {
1454 tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
1458 idp = silc_id_payload_parse(tmp, len);
1460 silc_free(*clients);
1461 silc_free(*servers);
1462 silc_free(*channels);
1463 silc_server_command_send_status_reply(
1464 cmd, SILC_COMMAND_IDENTIFY,
1465 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1469 id = silc_id_payload_get_id(idp);
1471 switch (silc_id_payload_get_type(idp)) {
1473 case SILC_ID_CLIENT:
1474 entry = (void *)silc_idlist_find_client_by_id(server->local_list,
1476 if (!entry && check_global)
1477 entry = (void *)silc_idlist_find_client_by_id(server->global_list,
1480 *clients = silc_realloc(*clients, sizeof(**clients) *
1481 (*clients_count + 1));
1482 (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
1484 /* If we are normal server and have not resolved information from
1485 router yet, do so now. */
1486 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1487 server->server_type == SILC_SERVER && !cmd->pending &&
1488 !server->standalone) {
1489 silc_server_command_identify_send_router(cmd);
1490 silc_free(*clients);
1491 silc_free(*servers);
1492 silc_free(*channels);
1495 silc_server_command_send_status_data(
1496 cmd, SILC_COMMAND_IDENTIFY,
1497 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1505 case SILC_ID_SERVER:
1506 entry = (void *)silc_idlist_find_server_by_id(server->local_list,
1508 if (!entry && check_global)
1509 entry = (void *)silc_idlist_find_server_by_id(server->global_list,
1512 *servers = silc_realloc(*servers, sizeof(**servers) *
1513 (*servers_count + 1));
1514 (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
1516 /* If we are normal server and have not resolved information from
1517 router yet, do so now. */
1518 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1519 server->server_type == SILC_SERVER && !cmd->pending &&
1520 !server->standalone) {
1521 silc_server_command_identify_send_router(cmd);
1522 silc_free(*clients);
1523 silc_free(*servers);
1524 silc_free(*channels);
1527 silc_server_command_send_status_data(
1528 cmd, SILC_COMMAND_IDENTIFY,
1529 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
1536 case SILC_ID_CHANNEL:
1537 entry = (void *)silc_idlist_find_channel_by_id(server->local_list,
1539 if (!entry && check_global)
1540 entry = (void *)silc_idlist_find_channel_by_id(server->global_list,
1543 *channels = silc_realloc(*channels, sizeof(**channels) *
1544 (*channels_count + 1));
1545 (*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
1547 /* If we are normal server and have not resolved information from
1548 router yet, do so now. */
1549 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1550 server->server_type == SILC_SERVER && !cmd->pending &&
1551 !server->standalone) {
1552 silc_server_command_identify_send_router(cmd);
1553 silc_free(*clients);
1554 silc_free(*servers);
1555 silc_free(*channels);
1558 silc_server_command_send_status_data(
1559 cmd, SILC_COMMAND_IDENTIFY,
1560 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
1573 silc_free(*clients);
1574 silc_free(*servers);
1575 silc_free(*channels);
1579 /* Get the max count of reply messages allowed */
1580 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1589 /* Checks that all mandatory fields in client entry are present. If not
1590 then send WHOIS request to the server who owns the client. We use
1591 WHOIS because we want to get as much information as possible at once. */
1594 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1595 SilcClientEntry *clients,
1596 SilcUInt32 clients_count)
1598 SilcServer server = cmd->server;
1599 SilcClientEntry entry;
1600 SilcServerResolveContext resolve = NULL, r = NULL;
1601 SilcUInt32 resolve_count = 0;
1605 for (i = 0; i < clients_count; i++) {
1610 if (entry->nickname ||
1611 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1615 /* If we are normal server, and we've not resolved this client from
1616 router and it is global client, we'll check whether it is on some
1617 channel. If not then we cannot be sure about its validity, and
1618 we'll resolve it from router. */
1619 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
1620 entry->connection || silc_hash_table_count(entry->channels))
1624 /* We need to resolve this entry since it is not complete */
1626 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1627 /* The entry is being resolved (and we are not the resolver) so attach
1628 to the command reply and we're done with this one. */
1629 silc_server_command_pending(server, SILC_COMMAND_NONE,
1630 entry->resolve_cmd_ident,
1631 silc_server_command_identify,
1632 silc_server_command_dup(cmd));
1635 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1636 /* We've resolved this and it still is not ready. We'll return
1637 and are that this will be handled again after it is resolved. */
1638 for (i = 0; i < resolve_count; i++) {
1639 for (k = 0; k < r->res_argc; k++)
1640 silc_free(r->res_argv[k]);
1641 silc_free(r->res_argv);
1642 silc_free(r->res_argv_lens);
1643 silc_free(r->res_argv_types);
1648 /* We'll resolve this client */
1652 for (k = 0; k < resolve_count; k++) {
1653 if (resolve[k].router == entry->router) {
1660 resolve = silc_realloc(resolve, sizeof(*resolve) *
1661 (resolve_count + 1));
1662 r = &resolve[resolve_count];
1663 memset(r, 0, sizeof(*r));
1664 r->router = entry->router;
1665 r->ident = ++server->cmd_ident;
1669 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1671 r->res_argv_lens = silc_realloc(r->res_argv_lens,
1672 sizeof(*r->res_argv_lens) *
1674 r->res_argv_types = silc_realloc(r->res_argv_types,
1675 sizeof(*r->res_argv_types) *
1677 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1678 r->res_argv[r->res_argc] = silc_calloc(idp->len,
1679 sizeof(**r->res_argv));
1680 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1681 r->res_argv_lens[r->res_argc] = idp->len;
1682 r->res_argv_types[r->res_argc] = r->res_argc + 3;
1684 silc_buffer_free(idp);
1686 entry->resolve_cmd_ident = r->ident;
1687 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1688 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1693 /* Do the resolving */
1694 for (i = 0; i < resolve_count; i++) {
1699 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1700 now anyway so make it a good one. */
1701 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1702 r->res_argc, r->res_argv,
1706 silc_server_packet_send(server, r->router->connection,
1707 SILC_PACKET_COMMAND, cmd->packet->flags,
1708 res_cmd->data, res_cmd->len, FALSE);
1710 /* Reprocess this packet after received reply */
1711 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1713 silc_server_command_identify,
1714 silc_server_command_dup(cmd));
1715 cmd->pending = TRUE;
1717 silc_buffer_free(res_cmd);
1718 for (k = 0; k < r->res_argc; k++)
1719 silc_free(r->res_argv[k]);
1720 silc_free(r->res_argv);
1721 silc_free(r->res_argv_lens);
1722 silc_free(r->res_argv_types);
1731 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1732 SilcClientEntry *clients,
1733 SilcUInt32 clients_count,
1734 SilcServerEntry *servers,
1735 SilcUInt32 servers_count,
1736 SilcChannelEntry *channels,
1737 SilcUInt32 channels_count,
1740 SilcServer server = cmd->server;
1741 int i, k, len, valid_count;
1742 SilcBuffer packet, idp;
1743 SilcCommandStatus status;
1744 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1745 char nh[256], uh[256];
1746 SilcSocketConnection hsock;
1748 status = SILC_STATUS_OK;
1751 SilcClientEntry entry;
1753 /* Process only valid entries. */
1755 for (i = 0; i < clients_count; i++) {
1756 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1763 /* No valid entries found at all, just send error */
1766 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1768 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1769 SILC_STATUS_ERR_NO_SUCH_NICK,
1770 3, tmp, strlen(tmp));
1772 tmp = silc_argument_get_arg_type(cmd->args, 5, (SilcUInt32 *)&len);
1773 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1774 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1780 /* Process all valid client entries and send command replies */
1782 if (valid_count > 1)
1783 status = SILC_STATUS_LIST_START;
1785 for (i = 0, k = 0; i < clients_count; i++) {
1791 status = SILC_STATUS_LIST_ITEM;
1792 if (valid_count > 1 && k == valid_count - 1
1793 && !servers_count && !channels_count)
1794 status = SILC_STATUS_LIST_END;
1795 if (count && k - 1 == count)
1796 status = SILC_STATUS_LIST_END;
1797 if (count && k - 1 > count)
1800 /* Send IDENTIFY reply */
1802 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1803 memset(uh, 0, sizeof(uh));
1804 memset(nh, 0, sizeof(nh));
1805 strncat(nh, entry->nickname, strlen(entry->nickname));
1806 if (!strchr(entry->nickname, '@')) {
1807 strncat(nh, "@", 1);
1808 if (entry->servername) {
1809 strncat(nh, entry->servername, strlen(entry->servername));
1811 len = entry->router ? strlen(entry->router->server_name) :
1812 strlen(server->server_name);
1813 strncat(nh, entry->router ? entry->router->server_name :
1814 server->server_name, len);
1818 if (!entry->username) {
1819 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1821 2, idp->data, idp->len,
1824 strncat(uh, entry->username, strlen(entry->username));
1825 if (!strchr(entry->username, '@')) {
1826 strncat(uh, "@", 1);
1827 hsock = (SilcSocketConnection)entry->connection;
1828 len = strlen(hsock->hostname);
1829 strncat(uh, hsock->hostname, len);
1832 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1834 2, idp->data, idp->len,
1839 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1840 0, packet->data, packet->len, FALSE);
1842 silc_buffer_free(packet);
1843 silc_buffer_free(idp);
1850 SilcServerEntry entry;
1852 if (status == SILC_STATUS_OK && servers_count > 1)
1853 status = SILC_STATUS_LIST_START;
1855 for (i = 0, k = 0; i < servers_count; i++) {
1859 status = SILC_STATUS_LIST_ITEM;
1860 if (servers_count > 1 && k == servers_count - 1 && !channels_count)
1861 status = SILC_STATUS_LIST_END;
1862 if (count && k - 1 == count)
1863 status = SILC_STATUS_LIST_END;
1864 if (count && k - 1 > count)
1867 /* Send IDENTIFY reply */
1868 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1870 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1872 2, idp->data, idp->len,
1873 3, entry->server_name,
1874 entry->server_name ?
1875 strlen(entry->server_name) : 0);
1876 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1877 0, packet->data, packet->len, FALSE);
1879 silc_buffer_free(packet);
1880 silc_buffer_free(idp);
1887 SilcChannelEntry entry;
1889 if (status == SILC_STATUS_OK && channels_count > 1)
1890 status = SILC_STATUS_LIST_START;
1892 for (i = 0, k = 0; i < channels_count; i++) {
1893 entry = channels[i];
1896 status = SILC_STATUS_LIST_ITEM;
1897 if (channels_count > 1 && k == channels_count - 1)
1898 status = SILC_STATUS_LIST_END;
1899 if (count && k - 1 == count)
1900 status = SILC_STATUS_LIST_END;
1901 if (count && k - 1 > count)
1904 /* Send IDENTIFY reply */
1905 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1907 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1909 2, idp->data, idp->len,
1910 3, entry->channel_name,
1911 entry->channel_name ?
1912 strlen(entry->channel_name): 0);
1913 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1914 0, packet->data, packet->len, FALSE);
1916 silc_buffer_free(packet);
1917 silc_buffer_free(idp);
1925 silc_server_command_identify_process(SilcServerCommandContext cmd)
1927 SilcUInt32 count = 0;
1929 SilcClientEntry *clients = NULL;
1930 SilcServerEntry *servers = NULL;
1931 SilcChannelEntry *channels = NULL;
1932 SilcUInt32 clients_count = 0, servers_count = 0, channels_count = 0;
1934 /* Parse the IDENTIFY request */
1935 ret = silc_server_command_identify_parse(cmd,
1936 &clients, &clients_count,
1937 &servers, &servers_count,
1938 &channels, &channels_count,
1944 /* Check that all mandatory fields are present and request those data
1945 from the server who owns the client if necessary. */
1946 if (clients && !silc_server_command_identify_check_client(cmd, clients,
1952 /* Send the command reply to the client */
1953 silc_server_command_identify_send_reply(cmd,
1954 clients, clients_count,
1955 servers, servers_count,
1956 channels, channels_count,
1962 silc_free(channels);
1966 SILC_SERVER_CMD_FUNC(identify)
1968 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1971 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1973 ret = silc_server_command_identify_process(cmd);
1974 silc_server_command_free(cmd);
1977 /* Server side of command NICK. Sets nickname for user. Setting
1978 nickname causes generation of a new client ID for the client. The
1979 new client ID is sent to the client after changing the nickname. */
1981 SILC_SERVER_CMD_FUNC(nick)
1983 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1984 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1985 SilcServer server = cmd->server;
1986 SilcBuffer packet, nidp, oidp = NULL;
1987 SilcClientID *new_id;
1988 SilcUInt32 nick_len;
1990 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1993 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1996 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
1998 /* Check nickname */
1999 nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
2002 if (silc_server_name_bad_chars(nick, nick_len) == TRUE) {
2003 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2004 SILC_STATUS_ERR_BAD_NICKNAME);
2008 /* Check for same nickname */
2009 if (!strcmp(client->nickname, nick)) {
2010 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2014 /* Create new Client ID */
2015 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
2017 cmd->server->md5hash, nick,
2020 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2023 /* Send notify about nickname change to our router. We send the new
2024 ID and ask to replace it with the old one. If we are router the
2025 packet is broadcasted. Send NICK_CHANGE notify. */
2026 if (!server->standalone)
2027 silc_server_send_notify_nick_change(server, server->router->connection,
2028 server->server_type == SILC_SERVER ?
2029 FALSE : TRUE, client->id,
2032 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2034 /* Remove old cache entry */
2035 silc_idcache_del_by_context(server->local_list->clients, client);
2038 silc_free(client->id);
2040 /* Save the nickname as this client is our local client */
2041 silc_free(client->nickname);
2043 client->nickname = strdup(nick);
2044 client->id = new_id;
2046 /* Update client cache */
2047 silc_idcache_add(server->local_list->clients, client->nickname,
2048 client->id, (void *)client, 0, NULL);
2050 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2052 /* Send NICK_CHANGE notify to the client's channels */
2053 silc_server_send_notify_on_channels(server, NULL, client,
2054 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
2055 oidp->data, oidp->len,
2056 nidp->data, nidp->len);
2059 /* Send the new Client ID as reply command back to client */
2060 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
2061 SILC_STATUS_OK, ident, 1,
2062 2, nidp->data, nidp->len);
2063 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2064 0, packet->data, packet->len, FALSE);
2066 silc_buffer_free(packet);
2067 silc_buffer_free(nidp);
2069 silc_buffer_free(oidp);
2072 silc_server_command_free(cmd);
2075 /* Sends the LIST command reply */
2078 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2079 SilcChannelEntry *lch,
2080 SilcUInt32 lch_count,
2081 SilcChannelEntry *gch,
2082 SilcUInt32 gch_count)
2085 SilcBuffer packet, idp;
2086 SilcChannelEntry entry;
2087 SilcCommandStatus status;
2088 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2090 unsigned char usercount[4];
2092 int valid_lcount = 0, valid_rcount = 0;
2094 for (i = 0; i < lch_count; i++) {
2095 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2100 for (i = 0; i < gch_count; i++) {
2101 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2107 status = SILC_STATUS_OK;
2108 if ((lch_count + gch_count) > 1)
2109 status = SILC_STATUS_LIST_START;
2112 for (i = 0, k = 0; i < lch_count; i++) {
2118 status = SILC_STATUS_LIST_ITEM;
2119 if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
2120 status = SILC_STATUS_LIST_END;
2122 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2124 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2125 topic = "*private*";
2126 memset(usercount, 0, sizeof(usercount));
2128 topic = entry->topic;
2129 users = silc_hash_table_count(entry->user_list);
2130 SILC_PUT32_MSB(users, usercount);
2133 /* Send the reply */
2135 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2137 2, idp->data, idp->len,
2138 3, entry->channel_name,
2139 strlen(entry->channel_name),
2140 4, topic, topic ? strlen(topic) : 0,
2142 silc_server_packet_send(cmd->server, cmd->sock,
2143 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2144 packet->len, FALSE);
2145 silc_buffer_free(packet);
2146 silc_buffer_free(idp);
2151 for (i = 0, k = 0; i < gch_count; i++) {
2157 status = SILC_STATUS_LIST_ITEM;
2158 if (valid_rcount > 1 && k == valid_rcount - 1)
2159 status = SILC_STATUS_LIST_END;
2161 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2163 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2164 topic = "*private*";
2165 memset(usercount, 0, sizeof(usercount));
2167 topic = entry->topic;
2168 users = entry->user_count;
2169 SILC_PUT32_MSB(users, usercount);
2172 /* Send the reply */
2174 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2176 2, idp->data, idp->len,
2177 3, entry->channel_name,
2178 strlen(entry->channel_name),
2179 4, topic, topic ? strlen(topic) : 0,
2181 silc_server_packet_send(cmd->server, cmd->sock,
2182 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2183 packet->len, FALSE);
2184 silc_buffer_free(packet);
2185 silc_buffer_free(idp);
2190 /* Server side of LIST command. This lists the channel of the requested
2191 server. Secret channels are not listed. */
2193 SILC_SERVER_CMD_FUNC(list)
2195 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2196 SilcServer server = cmd->server;
2197 SilcChannelID *channel_id = NULL;
2200 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2201 SilcUInt32 lch_count = 0, gch_count = 0;
2203 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2205 /* If we are normal server, send the command to router, since we
2206 want to know all channels in the network. */
2207 if (!cmd->pending && server->server_type == SILC_SERVER &&
2208 !server->standalone) {
2210 SilcUInt16 old_ident;
2212 old_ident = silc_command_get_ident(cmd->payload);
2213 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2214 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2215 silc_server_packet_send(server, server->router->connection,
2216 SILC_PACKET_COMMAND, cmd->packet->flags,
2217 tmpbuf->data, tmpbuf->len, TRUE);
2219 /* Reprocess this packet after received reply from router */
2220 silc_server_command_pending(server, SILC_COMMAND_LIST,
2221 silc_command_get_ident(cmd->payload),
2222 silc_server_command_list,
2223 silc_server_command_dup(cmd));
2224 cmd->pending = TRUE;
2225 silc_command_set_ident(cmd->payload, old_ident);
2226 silc_buffer_free(tmpbuf);
2230 /* Get Channel ID */
2231 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2233 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2235 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2236 SILC_STATUS_ERR_NO_CHANNEL_ID);
2241 /* Get the channels from local list */
2242 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2245 /* Get the channels from global list */
2246 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2249 /* Send the reply */
2250 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2251 gchannels, gch_count);
2253 silc_free(lchannels);
2254 silc_free(gchannels);
2257 silc_server_command_free(cmd);
2260 /* Server side of TOPIC command. Sets topic for channel and/or returns
2261 current topic to client. */
2263 SILC_SERVER_CMD_FUNC(topic)
2265 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2266 SilcServer server = cmd->server;
2267 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2268 SilcChannelID *channel_id;
2269 SilcChannelEntry channel;
2270 SilcChannelClientEntry chl;
2271 SilcBuffer packet, idp;
2273 SilcUInt32 argc, tmp_len;
2274 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2276 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2278 argc = silc_argument_get_arg_num(cmd->args);
2280 /* Get Channel ID */
2281 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2283 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2284 SILC_STATUS_ERR_NO_CHANNEL_ID);
2287 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2289 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2290 SILC_STATUS_ERR_NO_CHANNEL_ID);
2294 /* Check whether the channel exists */
2295 channel = silc_idlist_find_channel_by_id(server->local_list,
2298 channel = silc_idlist_find_channel_by_id(server->global_list,
2301 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2302 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2309 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2311 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2312 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2316 if (strlen(tmp) > 256) {
2317 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2318 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2322 /* See whether the client is on channel and has rights to change topic */
2323 if (!silc_server_client_on_channel(client, channel, &chl)) {
2324 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2325 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2329 if (chl->mode == SILC_CHANNEL_UMODE_NONE &&
2330 channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2331 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2332 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2336 /* Set the topic for channel */
2337 silc_free(channel->topic);
2338 channel->topic = strdup(tmp);
2340 /* Send TOPIC_SET notify type to the network */
2341 if (!server->standalone)
2342 silc_server_send_notify_topic_set(server, server->router->connection,
2343 server->server_type == SILC_ROUTER ?
2344 TRUE : FALSE, channel,
2345 client->id, SILC_ID_CLIENT,
2348 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2350 /* Send notify about topic change to all clients on the channel */
2351 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2352 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2353 idp->data, idp->len,
2354 channel->topic, strlen(channel->topic));
2355 silc_buffer_free(idp);
2358 /* Send the topic to client as reply packet */
2359 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2360 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2361 SILC_STATUS_OK, ident, 2,
2362 2, idp->data, idp->len,
2365 strlen(channel->topic) : 0);
2366 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2367 0, packet->data, packet->len, FALSE);
2369 silc_buffer_free(packet);
2370 silc_buffer_free(idp);
2371 silc_free(channel_id);
2374 silc_server_command_free(cmd);
2377 /* Server side of INVITE command. Invites some client to join some channel.
2378 This command is also used to manage the invite list of the channel. */
2380 SILC_SERVER_CMD_FUNC(invite)
2382 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2383 SilcServer server = cmd->server;
2384 SilcSocketConnection sock = cmd->sock, dest_sock;
2385 SilcChannelClientEntry chl;
2386 SilcClientEntry sender, dest;
2387 SilcClientID *dest_id = NULL;
2388 SilcChannelEntry channel;
2389 SilcChannelID *channel_id = NULL;
2390 SilcIDListData idata;
2391 SilcBuffer idp, idp2, packet;
2392 unsigned char *tmp, *add, *del;
2394 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2396 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2398 /* Get Channel ID */
2399 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2401 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2402 SILC_STATUS_ERR_NO_CHANNEL_ID);
2405 channel_id = silc_id_payload_parse_id(tmp, len, NULL);
2407 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2408 SILC_STATUS_ERR_NO_CHANNEL_ID);
2412 /* Get the channel entry */
2413 channel = silc_idlist_find_channel_by_id(server->local_list,
2416 channel = silc_idlist_find_channel_by_id(server->global_list,
2419 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2420 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2425 /* Check whether the sender of this command is on the channel. */
2426 sender = (SilcClientEntry)sock->user_data;
2427 if (!silc_server_client_on_channel(sender, channel, &chl)) {
2428 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2429 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2433 /* Check whether the channel is invite-only channel. If yes then the
2434 sender of this command must be at least channel operator. */
2435 if (chl->mode == SILC_CHANNEL_UMODE_NONE &&
2436 channel->mode & SILC_CHANNEL_MODE_INVITE) {
2437 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2438 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2442 /* Get destination client ID */
2443 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2448 dest_id = silc_id_payload_parse_id(tmp, len, NULL);
2450 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2451 SILC_STATUS_ERR_NO_CLIENT_ID);
2455 /* Get the client entry */
2456 dest = silc_server_get_client_resolve(server, dest_id, &resolve);
2458 if (server->server_type != SILC_SERVER || !resolve) {
2459 silc_server_command_send_status_reply(
2460 cmd, SILC_COMMAND_INVITE,
2461 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2465 /* The client info is being resolved. Reprocess this packet after
2466 receiving the reply to the query. */
2467 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2469 silc_server_command_invite,
2470 silc_server_command_dup(cmd));
2471 cmd->pending = TRUE;
2472 silc_free(channel_id);
2477 /* Check whether the requested client is already on the channel. */
2478 if (silc_server_client_on_channel(dest, channel, NULL)) {
2479 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2480 SILC_STATUS_ERR_USER_ON_CHANNEL);
2484 /* Get route to the client */
2485 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2487 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2488 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2492 memset(invite, 0, sizeof(invite));
2493 strncat(invite, dest->nickname, strlen(dest->nickname));
2494 strncat(invite, "!", 1);
2495 strncat(invite, dest->username, strlen(dest->username));
2496 if (!strchr(dest->username, '@')) {
2497 strncat(invite, "@", 1);
2498 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2501 len = strlen(invite);
2502 if (!channel->invite_list)
2503 channel->invite_list = silc_calloc(len + 2,
2504 sizeof(*channel->invite_list));
2506 channel->invite_list = silc_realloc(channel->invite_list,
2507 sizeof(*channel->invite_list) *
2509 strlen(channel->invite_list) + 2));
2510 strncat(channel->invite_list, invite, len);
2511 strncat(channel->invite_list, ",", 1);
2513 /* Send notify to the client that is invited to the channel */
2514 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2515 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2516 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2518 SILC_NOTIFY_TYPE_INVITE, 3,
2519 idp->data, idp->len,
2520 channel->channel_name,
2521 strlen(channel->channel_name),
2522 idp2->data, idp2->len);
2523 silc_buffer_free(idp);
2524 silc_buffer_free(idp2);
2527 /* Add the client to the invite list of the channel */
2528 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2530 if (!channel->invite_list)
2531 channel->invite_list = silc_calloc(len + 2,
2532 sizeof(*channel->invite_list));
2534 channel->invite_list = silc_realloc(channel->invite_list,
2535 sizeof(*channel->invite_list) *
2537 strlen(channel->invite_list) + 2));
2538 if (add[len - 1] == ',')
2539 add[len - 1] = '\0';
2541 strncat(channel->invite_list, add, len);
2542 strncat(channel->invite_list, ",", 1);
2545 /* Get the invite to be removed and remove it from the list */
2546 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2547 if (del && channel->invite_list) {
2548 char *start, *end, *n;
2550 if (!strncmp(channel->invite_list, del,
2551 strlen(channel->invite_list) - 1)) {
2552 silc_free(channel->invite_list);
2553 channel->invite_list = NULL;
2555 start = strstr(channel->invite_list, del);
2556 if (start && strlen(start) >= len) {
2558 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2559 strncat(n, channel->invite_list, start - channel->invite_list);
2560 strncat(n, end + 1, ((channel->invite_list +
2561 strlen(channel->invite_list)) - end) - 1);
2562 silc_free(channel->invite_list);
2563 channel->invite_list = n;
2568 /* Send notify to the primary router */
2569 if (!server->standalone)
2570 silc_server_send_notify_invite(server, server->router->connection,
2571 server->server_type == SILC_ROUTER ?
2572 TRUE : FALSE, channel,
2573 sender->id, add, del);
2575 /* Send command reply */
2576 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2580 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2581 SILC_STATUS_OK, ident, 2,
2583 3, channel->invite_list,
2584 channel->invite_list ?
2585 strlen(channel->invite_list) : 0);
2588 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2589 SILC_STATUS_OK, ident, 1,
2591 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2592 packet->data, packet->len, FALSE);
2593 silc_buffer_free(packet);
2597 silc_free(channel_id);
2598 silc_server_command_free(cmd);
2603 SilcSocketConnection sock;
2607 /* Quits connection to client. This gets called if client won't
2608 close the connection even when it has issued QUIT command. */
2610 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2612 QuitInternal q = (QuitInternal)context;
2614 /* Free all client specific data, such as client entry and entires
2615 on channels this client may be on. */
2616 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2618 q->sock->user_data = NULL;
2620 /* Close the connection on our side */
2621 silc_server_close_connection(q->server, q->sock);
2623 silc_free(q->signoff);
2627 /* Quits SILC session. This is the normal way to disconnect client. */
2629 SILC_SERVER_CMD_FUNC(quit)
2631 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2632 SilcServer server = cmd->server;
2633 SilcSocketConnection sock = cmd->sock;
2635 unsigned char *tmp = NULL;
2638 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2640 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2643 /* Get destination ID */
2644 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2648 q = silc_calloc(1, sizeof(*q));
2651 q->signoff = tmp ? strdup(tmp) : NULL;
2653 /* We quit the connection with little timeout */
2654 silc_schedule_task_add(server->schedule, sock->sock,
2655 silc_server_command_quit_cb, (void *)q,
2656 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2659 silc_server_command_free(cmd);
2662 /* Server side of command KILL. This command is used by router operator
2663 to remove an client from the SILC Network temporarily. */
2665 SILC_SERVER_CMD_FUNC(kill)
2667 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2668 SilcServer server = cmd->server;
2669 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2670 SilcClientEntry remote_client;
2671 SilcClientID *client_id;
2672 unsigned char *tmp, *comment;
2673 SilcUInt32 tmp_len, tmp_len2;
2676 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2678 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2681 /* KILL command works only on router */
2682 if (server->server_type != SILC_ROUTER) {
2683 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2684 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2688 /* Check whether client has the permissions. */
2689 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2690 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2691 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2695 /* Get the client ID */
2696 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2698 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2699 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2702 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2704 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2705 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2709 /* Get the client entry */
2710 remote_client = silc_idlist_find_client_by_id(server->local_list,
2711 client_id, TRUE, NULL);
2713 if (!remote_client) {
2714 remote_client = silc_idlist_find_client_by_id(server->global_list,
2715 client_id, TRUE, NULL);
2717 if (!remote_client) {
2718 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2719 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2725 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2729 /* Send reply to the sender */
2730 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2733 /* Send the KILL notify packets. First send it to the channel, then
2734 to our primary router and then directly to the client who is being
2735 killed right now. */
2737 /* Send KILLED notify to the channels. It is not sent to the client
2738 as it will be sent differently destined directly to the client and not
2740 silc_server_send_notify_on_channels(server, remote_client,
2741 remote_client, SILC_NOTIFY_TYPE_KILLED,
2744 comment, comment ? tmp_len2 : 0);
2746 /* Send KILLED notify to primary route */
2747 if (!server->standalone)
2748 silc_server_send_notify_killed(server, server->router->connection, TRUE,
2749 remote_client->id, comment);
2751 /* Send KILLED notify to the client directly */
2752 silc_server_send_notify_killed(server, remote_client->connection ?
2753 remote_client->connection :
2754 remote_client->router->connection, FALSE,
2755 remote_client->id, comment);
2757 /* Remove the client from all channels. This generates new keys to the
2758 channels as well. */
2759 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2762 /* Remove the client entry, If it is locally connected then we will also
2763 disconnect the client here */
2764 if (remote_client->connection) {
2765 /* Remove locally conneted client */
2766 SilcSocketConnection sock = remote_client->connection;
2767 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2768 silc_server_close_connection(server, sock);
2770 /* Update statistics */
2771 if (remote_client->connection)
2772 server->stat.my_clients--;
2773 if (server->server_type == SILC_ROUTER)
2774 server->stat.cell_clients--;
2775 SILC_OPER_STATS_UPDATE(remote_client, server, SILC_UMODE_SERVER_OPERATOR);
2776 SILC_OPER_STATS_UPDATE(remote_client, router, SILC_UMODE_ROUTER_OPERATOR);
2778 /* Remove remote client */
2779 silc_idlist_del_client(local ? server->local_list :
2780 server->global_list, remote_client);
2784 silc_server_command_free(cmd);
2787 /* Server side of command INFO. This sends information about us to
2788 the client. If client requested specific server we will send the
2789 command to that server. */
2791 SILC_SERVER_CMD_FUNC(info)
2793 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2794 SilcServer server = cmd->server;
2795 SilcBuffer packet, idp;
2798 char *dest_server, *server_info = NULL, *server_name;
2799 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2800 SilcServerEntry entry = NULL;
2801 SilcServerID *server_id = NULL;
2803 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2805 /* Get server name */
2806 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2809 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2811 server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2813 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2814 SILC_STATUS_ERR_NO_SERVER_ID);
2820 /* Check whether we have this server cached */
2821 entry = silc_idlist_find_server_by_id(server->local_list,
2822 server_id, TRUE, NULL);
2824 entry = silc_idlist_find_server_by_id(server->global_list,
2825 server_id, TRUE, NULL);
2826 if (!entry && server->server_type != SILC_SERVER) {
2827 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2828 SILC_STATUS_ERR_NO_SUCH_SERVER);
2834 /* Some buggy servers has sent request to router about themselves. */
2835 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2838 if ((!dest_server && !server_id && !entry) || (entry &&
2839 entry == server->id_entry) ||
2840 (dest_server && !cmd->pending &&
2841 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2842 /* Send our reply */
2843 char info_string[256];
2845 memset(info_string, 0, sizeof(info_string));
2846 snprintf(info_string, sizeof(info_string),
2847 "location: %s server: %s admin: %s <%s>",
2848 server->config->server_info->location,
2849 server->config->server_info->server_type,
2850 server->config->server_info->admin,
2851 server->config->server_info->email);
2853 server_info = info_string;
2854 entry = server->id_entry;
2856 /* Check whether we have this server cached */
2857 if (!entry && dest_server) {
2858 entry = silc_idlist_find_server_by_name(server->global_list,
2859 dest_server, TRUE, NULL);
2861 entry = silc_idlist_find_server_by_name(server->local_list,
2862 dest_server, TRUE, NULL);
2866 if (!cmd->pending &&
2867 server->server_type != SILC_SERVER && entry && !entry->server_info) {
2868 /* Send to the server */
2870 SilcUInt16 old_ident;
2872 old_ident = silc_command_get_ident(cmd->payload);
2873 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2874 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2876 silc_server_packet_send(server, entry->connection,
2877 SILC_PACKET_COMMAND, cmd->packet->flags,
2878 tmpbuf->data, tmpbuf->len, TRUE);
2880 /* Reprocess this packet after received reply from router */
2881 silc_server_command_pending(server, SILC_COMMAND_INFO,
2882 silc_command_get_ident(cmd->payload),
2883 silc_server_command_info,
2884 silc_server_command_dup(cmd));
2885 cmd->pending = TRUE;
2886 silc_command_set_ident(cmd->payload, old_ident);
2887 silc_buffer_free(tmpbuf);
2891 if (!entry && !cmd->pending && !server->standalone) {
2892 /* Send to the primary router */
2894 SilcUInt16 old_ident;
2896 old_ident = silc_command_get_ident(cmd->payload);
2897 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2898 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2900 silc_server_packet_send(server, server->router->connection,
2901 SILC_PACKET_COMMAND, cmd->packet->flags,
2902 tmpbuf->data, tmpbuf->len, TRUE);
2904 /* Reprocess this packet after received reply from router */
2905 silc_server_command_pending(server, SILC_COMMAND_INFO,
2906 silc_command_get_ident(cmd->payload),
2907 silc_server_command_info,
2908 silc_server_command_dup(cmd));
2909 cmd->pending = TRUE;
2910 silc_command_set_ident(cmd->payload, old_ident);
2911 silc_buffer_free(tmpbuf);
2916 silc_free(server_id);
2919 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2920 SILC_STATUS_ERR_NO_SUCH_SERVER);
2924 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2926 server_info = entry->server_info;
2927 server_name = entry->server_name;
2929 /* Send the reply */
2930 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2931 SILC_STATUS_OK, ident, 3,
2932 2, idp->data, idp->len,
2934 strlen(server_name),
2937 strlen(server_info) : 0);
2938 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2939 packet->data, packet->len, FALSE);
2941 silc_buffer_free(packet);
2942 silc_buffer_free(idp);
2945 silc_server_command_free(cmd);
2948 /* Server side of command PING. This just replies to the ping. */
2950 SILC_SERVER_CMD_FUNC(ping)
2952 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2953 SilcServer server = cmd->server;
2958 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
2961 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2963 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2964 SILC_STATUS_ERR_NO_SERVER_ID);
2967 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2971 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2972 /* Send our reply */
2973 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2976 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2977 SILC_STATUS_ERR_NO_SUCH_SERVER);
2984 silc_server_command_free(cmd);
2987 /* Internal routine to join channel. The channel sent to this function
2988 has been either created or resolved from ID lists. This joins the sent
2989 client to the channel. */
2991 static void silc_server_command_join_channel(SilcServer server,
2992 SilcServerCommandContext cmd,
2993 SilcChannelEntry channel,
2994 SilcClientID *client_id,
2998 const unsigned char *auth,
2999 SilcUInt32 auth_len)
3001 SilcSocketConnection sock = cmd->sock;
3003 SilcUInt32 tmp_len, user_count;
3004 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
3005 SilcClientEntry client;
3006 SilcChannelClientEntry chl;
3007 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
3008 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3009 char check[512], check2[512];
3010 bool founder = FALSE;
3013 SILC_LOG_DEBUG(("Start"));
3018 /* Get the client entry */
3019 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3020 client = (SilcClientEntry)sock->user_data;
3022 client = silc_server_get_client_resolve(server, client_id, &resolve);
3028 silc_server_command_send_status_reply(
3029 cmd, SILC_COMMAND_JOIN,
3030 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3034 /* The client info is being resolved. Reprocess this packet after
3035 receiving the reply to the query. */
3036 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
3038 silc_server_command_join,
3039 silc_server_command_dup(cmd));
3040 cmd->pending = TRUE;
3044 cmd->pending = FALSE;
3048 * Check founder auth payload if provided. If client can gain founder
3049 * privileges it can override various conditions on joining the channel,
3050 * and can have directly the founder mode set on the channel.
3052 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3053 SilcIDListData idata = (SilcIDListData)client;
3055 if (channel->founder_key && idata->public_key &&
3056 silc_pkcs_public_key_compare(channel->founder_key,
3057 idata->public_key)) {
3058 void *auth_data = (channel->founder_method == SILC_AUTH_PASSWORD ?
3059 (void *)channel->founder_passwd :
3060 (void *)channel->founder_key);
3061 SilcUInt32 auth_data_len =
3062 (channel->founder_method == SILC_AUTH_PASSWORD ?
3063 channel->founder_passwd_len : 0);
3065 /* Check whether the client is to become founder */
3066 if (silc_auth_verify_data(auth, auth_len, channel->founder_method,
3067 auth_data, auth_data_len,
3068 idata->hash, client->id, SILC_ID_CLIENT)) {
3069 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3076 * Check channel modes
3080 memset(check, 0, sizeof(check));
3081 memset(check2, 0, sizeof(check2));
3082 strncat(check, client->nickname, strlen(client->nickname));
3083 strncat(check, "!", 1);
3084 strncat(check, client->username, strlen(client->username));
3085 if (!strchr(client->username, '@')) {
3086 strncat(check, "@", 1);
3087 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3090 strncat(check2, client->nickname, strlen(client->nickname));
3091 if (!strchr(client->nickname, '@')) {
3092 strncat(check2, "@", 1);
3093 strncat(check2, server->server_name, strlen(server->server_name));
3095 strncat(check2, "!", 1);
3096 strncat(check2, client->username, strlen(client->username));
3097 if (!strchr(client->username, '@')) {
3098 strncat(check2, "@", 1);
3099 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3102 /* Check invite list if channel is invite-only channel */
3103 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3104 if (!channel->invite_list ||
3105 (!silc_string_match(channel->invite_list, check) &&
3106 !silc_string_match(channel->invite_list, check2))) {
3107 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3108 SILC_STATUS_ERR_NOT_INVITED);
3113 /* Check ban list if it exists. If the client's nickname, server,
3114 username and/or hostname is in the ban list the access to the
3115 channel is denied. */
3116 if (channel->ban_list) {
3117 if (silc_string_match(channel->ban_list, check) ||
3118 silc_string_match(channel->ban_list, check2)) {
3119 silc_server_command_send_status_reply(
3120 cmd, SILC_COMMAND_JOIN,
3121 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
3126 /* Check user count limit if set. */
3127 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3128 if (silc_hash_table_count(channel->user_list) + 1 >
3129 channel->user_limit) {
3130 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3131 SILC_STATUS_ERR_CHANNEL_IS_FULL);
3137 /* Check the channel passphrase if set. */
3138 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3139 /* Get passphrase */
3140 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3142 passphrase = silc_memdup(tmp, tmp_len);
3144 if (!passphrase || !channel->passphrase ||
3145 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3146 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3147 SILC_STATUS_ERR_BAD_PASSWORD);
3153 * Client is allowed to join to the channel. Make it happen.
3156 /* Check whether the client already is on the channel */
3157 if (silc_server_client_on_channel(client, channel, NULL)) {
3158 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3159 SILC_STATUS_ERR_USER_ON_CHANNEL);
3163 /* Generate new channel key as protocol dictates */
3165 if (!silc_server_create_channel_key(server, channel, 0))
3168 /* Send the channel key. This is broadcasted to the channel but is not
3169 sent to the client who is joining to the channel. */
3170 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3171 silc_server_send_channel_key(server, NULL, channel,
3172 server->server_type == SILC_ROUTER ?
3173 FALSE : !server->standalone);
3176 /* Join the client to the channel by adding it to channel's user list.
3177 Add also the channel to client entry's channels list for fast cross-
3179 chl = silc_calloc(1, sizeof(*chl));
3181 chl->client = client;
3182 chl->channel = channel;
3183 silc_hash_table_add(channel->user_list, client, chl);
3184 silc_hash_table_add(client->channels, channel, chl);
3185 channel->user_count++;
3187 /* Get users on the channel */
3188 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3191 /* Encode Client ID Payload of the original client who wants to join */
3192 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3194 /* Encode command reply packet */
3195 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3196 SILC_PUT32_MSB(channel->mode, mode);
3197 SILC_PUT32_MSB(created, tmp2);
3198 SILC_PUT32_MSB(user_count, tmp3);
3200 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3201 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3202 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
3203 strlen(channel->channel_key->
3205 channel->channel_key->cipher->name,
3206 channel->key_len / 8, channel->key);
3211 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3212 SILC_STATUS_OK, ident, 13,
3213 2, channel->channel_name,
3214 strlen(channel->channel_name),
3215 3, chidp->data, chidp->len,
3216 4, clidp->data, clidp->len,
3219 7, keyp ? keyp->data : NULL,
3220 keyp ? keyp->len : 0,
3221 8, channel->ban_list,
3223 strlen(channel->ban_list) : 0,
3224 9, channel->invite_list,
3225 channel->invite_list ?
3226 strlen(channel->invite_list) : 0,
3229 strlen(channel->topic) : 0,
3230 11, silc_hmac_get_name(channel->hmac),
3231 strlen(silc_hmac_get_name(channel->
3234 13, user_list->data, user_list->len,
3235 14, mode_list->data,
3238 /* Send command reply */
3239 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3240 reply->data, reply->len, FALSE);
3242 /* Send JOIN notify to locally connected clients on the channel. If
3243 we are normal server then router will send or have sent JOIN notify
3244 already. However since we've added the client already to our channel
3245 we'll ignore it (in packet_receive.c) so we must send it here. If
3246 we are router then this will send it to local clients and local
3248 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3249 SILC_NOTIFY_TYPE_JOIN, 2,
3250 clidp->data, clidp->len,
3251 chidp->data, chidp->len);
3253 if (!cmd->pending) {
3254 /* Send JOIN notify packet to our primary router */
3255 if (!server->standalone)
3256 silc_server_send_notify_join(server, server->router->connection,
3257 server->server_type == SILC_ROUTER ?
3258 TRUE : FALSE, channel, client->id);
3261 /* Distribute the channel key to all backup routers. */
3262 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3263 keyp->data, keyp->len, FALSE, TRUE);
3266 /* If client became founder by providing correct founder auth data
3267 notify the mode change to the channel. */
3269 SILC_PUT32_MSB(chl->mode, mode);
3270 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3271 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3272 clidp->data, clidp->len,
3273 mode, 4, clidp->data, clidp->len);
3275 /* Set CUMODE notify type to network */
3276 if (!server->standalone)
3277 silc_server_send_notify_cumode(server, server->router->connection,
3278 server->server_type == SILC_ROUTER ?
3279 TRUE : FALSE, channel,
3280 chl->mode, client->id, SILC_ID_CLIENT,
3284 silc_buffer_free(reply);
3285 silc_buffer_free(clidp);
3286 silc_buffer_free(chidp);
3287 silc_buffer_free(keyp);
3288 silc_buffer_free(user_list);
3289 silc_buffer_free(mode_list);
3292 silc_free(passphrase);
3295 /* Server side of command JOIN. Joins client into requested channel. If
3296 the channel does not exist it will be created. */
3298 SILC_SERVER_CMD_FUNC(join)
3300 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3301 SilcServer server = cmd->server;
3302 unsigned char *auth;
3303 SilcUInt32 tmp_len, auth_len;
3304 char *tmp, *channel_name = NULL, *cipher, *hmac;
3305 SilcChannelEntry channel;
3306 SilcUInt32 umode = 0;
3307 bool created = FALSE, create_key = TRUE;
3308 SilcClientID *client_id;
3310 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3312 /* Get channel name */
3313 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3315 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3316 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3322 channel_name[255] = '\0';
3324 if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
3325 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3326 SILC_STATUS_ERR_BAD_CHANNEL);
3330 /* Get Client ID of the client who is joining to the channel */
3331 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3333 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3334 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3337 client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3339 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3340 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3344 /* Get cipher, hmac name and auth payload */
3345 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3346 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3347 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3349 /* See if the channel exists */
3350 channel = silc_idlist_find_channel_by_name(server->local_list,
3351 channel_name, NULL);
3353 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3354 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3355 client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
3357 if (!channel || channel->disabled) {
3358 /* Channel not found */
3360 /* If we are standalone server we don't have a router, we just create
3361 the channel by ourselves. */
3362 if (server->standalone) {
3363 channel = silc_server_create_new_channel(server, server->id, cipher,
3364 hmac, channel_name, TRUE);
3366 silc_server_command_send_status_reply(
3367 cmd, SILC_COMMAND_JOIN,
3368 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3372 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3378 /* The channel does not exist on our server. If we are normal server
3379 we will send JOIN command to our router which will handle the
3380 joining procedure (either creates the channel if it doesn't exist
3381 or joins the client to it). */
3382 if (server->server_type != SILC_ROUTER) {
3384 SilcUInt16 old_ident;
3386 /* If this is pending command callback then we've resolved
3387 it and it didn't work, return since we've notified the
3388 client already in the command reply callback. */
3392 old_ident = silc_command_get_ident(cmd->payload);
3393 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3394 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3396 /* Send JOIN command to our router */
3397 silc_server_packet_send(server, (SilcSocketConnection)
3398 server->router->connection,
3399 SILC_PACKET_COMMAND, cmd->packet->flags,
3400 tmpbuf->data, tmpbuf->len, TRUE);
3402 /* Reprocess this packet after received reply from router */
3403 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3404 silc_command_get_ident(cmd->payload),
3405 silc_server_command_join,
3406 silc_server_command_dup(cmd));
3407 cmd->pending = TRUE;
3408 silc_command_set_ident(cmd->payload, old_ident);
3409 silc_buffer_free(tmpbuf);
3413 /* We are router and the channel does not seem exist so we will check
3414 our global list as well for the channel. */
3415 channel = silc_idlist_find_channel_by_name(server->global_list,
3416 channel_name, NULL);
3418 /* Channel really does not exist, create it */
3419 channel = silc_server_create_new_channel(server, server->id, cipher,
3420 hmac, channel_name, TRUE);
3422 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3423 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3427 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3435 /* Channel not found */
3437 /* If the command came from router and we are normal server then
3438 something went wrong with the joining as the channel was not found.
3439 We can't do anything else but ignore this. */
3440 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3441 server->server_type != SILC_ROUTER)
3444 /* We are router and the channel does not seem exist so we will check
3445 our global list as well for the channel. */
3446 channel = silc_idlist_find_channel_by_name(server->global_list,
3447 channel_name, NULL);
3449 /* Channel really does not exist, create it */
3450 channel = silc_server_create_new_channel(server, server->id, cipher,
3451 hmac, channel_name, TRUE);
3453 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3454 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3458 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3465 /* Check whether the channel was created by our router */
3466 if (cmd->pending && context2) {
3467 SilcServerCommandReplyContext reply =
3468 (SilcServerCommandReplyContext)context2;
3470 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3471 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3472 SILC_GET32_MSB(created, tmp);
3473 if (silc_argument_get_arg_type(reply->args, 7, NULL))
3474 create_key = FALSE; /* Router returned the key already */
3477 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
3478 !silc_hash_table_count(channel->user_list))
3482 /* If the channel does not have global users and is also empty the client
3483 will be the channel founder and operator. */
3484 if (!channel->global_users && !silc_hash_table_count(channel->user_list))
3485 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3487 /* Join to the channel */
3488 silc_server_command_join_channel(server, cmd, channel, client_id,
3489 created, create_key, umode,
3492 silc_free(client_id);
3495 silc_server_command_free(cmd);
3498 /* Server side of command MOTD. Sends server's current "message of the
3499 day" to the client. */
3501 SILC_SERVER_CMD_FUNC(motd)
3503 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3504 SilcServer server = cmd->server;
3505 SilcBuffer packet, idp;
3506 char *motd, *dest_server;
3507 SilcUInt32 motd_len;
3508 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3510 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3512 /* Get server name */
3513 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3515 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3516 SILC_STATUS_ERR_NO_SUCH_SERVER);
3520 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3523 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3525 if (server->config && server->config->server_info &&
3526 server->config->server_info->motd_file) {
3528 motd = silc_file_readfile(server->config->server_info->motd_file, &motd_len);
3533 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3534 SILC_STATUS_OK, ident, 2,
3539 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3540 SILC_STATUS_OK, ident, 1,
3544 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3545 packet->data, packet->len, FALSE);
3546 silc_buffer_free(packet);
3547 silc_buffer_free(idp);
3549 SilcServerEntry entry;
3551 /* Check whether we have this server cached */
3552 entry = silc_idlist_find_server_by_name(server->global_list,
3553 dest_server, TRUE, NULL);
3555 entry = silc_idlist_find_server_by_name(server->local_list,
3556 dest_server, TRUE, NULL);
3559 if (server->server_type != SILC_SERVER && !cmd->pending &&
3560 entry && !entry->motd) {
3561 /* Send to the server */
3563 SilcUInt16 old_ident;
3565 old_ident = silc_command_get_ident(cmd->payload);
3566 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3567 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3569 silc_server_packet_send(server, entry->connection,
3570 SILC_PACKET_COMMAND, cmd->packet->flags,
3571 tmpbuf->data, tmpbuf->len, TRUE);
3573 /* Reprocess this packet after received reply from router */
3574 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3575 silc_command_get_ident(cmd->payload),
3576 silc_server_command_motd,
3577 silc_server_command_dup(cmd));
3578 cmd->pending = TRUE;
3579 silc_command_set_ident(cmd->payload, old_ident);
3580 silc_buffer_free(tmpbuf);
3584 if (!entry && !cmd->pending && !server->standalone) {
3585 /* Send to the primary router */
3587 SilcUInt16 old_ident;
3589 old_ident = silc_command_get_ident(cmd->payload);
3590 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3591 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3593 silc_server_packet_send(server, server->router->connection,
3594 SILC_PACKET_COMMAND, cmd->packet->flags,
3595 tmpbuf->data, tmpbuf->len, TRUE);
3597 /* Reprocess this packet after received reply from router */
3598 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3599 silc_command_get_ident(cmd->payload),
3600 silc_server_command_motd,
3601 silc_server_command_dup(cmd));
3602 cmd->pending = TRUE;
3603 silc_command_set_ident(cmd->payload, old_ident);
3604 silc_buffer_free(tmpbuf);
3609 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3610 SILC_STATUS_ERR_NO_SUCH_SERVER);
3614 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3615 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3616 SILC_STATUS_OK, ident, 2,
3620 strlen(entry->motd) : 0);
3621 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3622 packet->data, packet->len, FALSE);
3623 silc_buffer_free(packet);
3624 silc_buffer_free(idp);
3628 silc_server_command_free(cmd);
3631 /* Server side of command UMODE. Client can use this command to set/unset
3632 user mode. Client actually cannot set itself to be as server/router
3633 operator so this can be used only to unset the modes. */
3635 SILC_SERVER_CMD_FUNC(umode)
3637 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3638 SilcServer server = cmd->server;
3639 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3641 unsigned char *tmp_mask;
3643 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3645 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3648 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 2, 2);
3650 /* Get the client's mode mask */
3651 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3653 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3654 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3657 SILC_GET32_MSB(mask, tmp_mask);
3659 /* Check that mode changing is allowed. */
3660 if (!silc_server_check_umode_rights(server, client, mask)) {
3661 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3662 SILC_STATUS_ERR_PERM_DENIED);
3666 /* Change the mode */
3667 client->mode = mask;
3669 /* Send UMODE change to primary router */
3670 if (!server->standalone)
3671 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3672 client->id, client->mode);
3674 /* Send command reply to sender */
3675 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3676 SILC_STATUS_OK, ident, 1,
3678 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3679 packet->data, packet->len, FALSE);
3680 silc_buffer_free(packet);
3683 silc_server_command_free(cmd);
3686 /* Server side command of CMODE. Changes channel mode */
3688 SILC_SERVER_CMD_FUNC(cmode)
3690 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3691 SilcServer server = cmd->server;
3692 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3693 SilcIDListData idata = (SilcIDListData)client;
3694 SilcChannelID *channel_id;
3695 SilcChannelEntry channel;
3696 SilcChannelClientEntry chl;
3697 SilcBuffer packet, cidp;
3698 unsigned char *tmp, *tmp_id, *tmp_mask;
3699 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3700 SilcUInt32 mode_mask, tmp_len, tmp_len2;
3701 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3703 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 2, 7);
3705 /* Get Channel ID */
3706 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3708 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3709 SILC_STATUS_ERR_NO_CHANNEL_ID);
3712 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
3714 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3715 SILC_STATUS_ERR_NO_CHANNEL_ID);
3719 /* Get the channel mode mask */
3720 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3722 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3723 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3726 SILC_GET32_MSB(mode_mask, tmp_mask);
3728 /* Get channel entry */
3729 channel = silc_idlist_find_channel_by_id(server->local_list,
3732 channel = silc_idlist_find_channel_by_id(server->global_list,
3735 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3736 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3741 /* Check whether this client is on the channel */
3742 if (!silc_server_client_on_channel(client, channel, &chl)) {
3743 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3744 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3748 /* Check that client has rights to change any requested channel modes */
3749 if (!silc_server_check_cmode_rights(server, channel, chl, mode_mask)) {
3750 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3751 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3756 * Check the modes. Modes that requires nothing special operation are
3760 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3761 /* Channel uses private keys to protect traffic. Client(s) has set the
3762 key locally they want to use, server does not know that key. */
3763 /* Nothing interesting to do here */
3765 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3766 /* The mode is removed and we need to generate and distribute
3767 new channel key. Clients are not using private channel keys
3768 anymore after this. */
3770 /* Re-generate channel key */
3771 if (!silc_server_create_channel_key(server, channel, 0))
3774 /* Send the channel key. This sends it to our local clients and if
3775 we are normal server to our router as well. */
3776 silc_server_send_channel_key(server, NULL, channel,
3777 server->server_type == SILC_ROUTER ?
3778 FALSE : !server->standalone);
3780 cipher = channel->channel_key->cipher->name;
3781 hmac = (char *)silc_hmac_get_name(channel->hmac);
3785 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3786 /* User limit is set on channel */
3787 SilcUInt32 user_limit;
3789 /* Get user limit */
3790 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3792 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3793 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3794 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3798 SILC_GET32_MSB(user_limit, tmp);
3799 channel->user_limit = user_limit;
3802 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3803 /* User limit mode is unset. Remove user limit */
3804 channel->user_limit = 0;
3807 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3808 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3809 /* Passphrase has been set to channel */
3811 /* Get the passphrase */
3812 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3814 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3815 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3819 /* Save the passphrase */
3820 passphrase = channel->passphrase = strdup(tmp);
3823 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3824 /* Passphrase mode is unset. remove the passphrase */
3825 if (channel->passphrase) {
3826 silc_free(channel->passphrase);
3827 channel->passphrase = NULL;
3832 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3833 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3834 /* Cipher to use protect the traffic */
3835 SilcCipher newkey, oldkey;
3838 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3840 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3841 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3845 /* Delete old cipher and allocate the new one */
3846 if (!silc_cipher_alloc(cipher, &newkey)) {
3847 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3848 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3852 oldkey = channel->channel_key;
3853 channel->channel_key = newkey;
3855 /* Re-generate channel key */
3856 if (!silc_server_create_channel_key(server, channel, 0)) {
3857 /* We don't have new key, revert to old one */
3858 channel->channel_key = oldkey;
3862 /* Remove old channel key for good */
3863 silc_cipher_free(oldkey);
3865 /* Send the channel key. This sends it to our local clients and if
3866 we are normal server to our router as well. */
3867 silc_server_send_channel_key(server, NULL, channel,
3868 server->server_type == SILC_ROUTER ?
3869 FALSE : !server->standalone);
3872 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3873 /* Cipher mode is unset. Remove the cipher and revert back to
3875 SilcCipher newkey, oldkey;
3876 cipher = channel->cipher;
3878 /* Delete old cipher and allocate default one */
3879 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
3880 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3881 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3885 oldkey = channel->channel_key;
3886 channel->channel_key = newkey;
3888 /* Re-generate channel key */
3889 if (!silc_server_create_channel_key(server, channel, 0)) {
3890 /* We don't have new key, revert to old one */
3891 channel->channel_key = oldkey;
3895 /* Remove old channel key for good */
3896 silc_cipher_free(oldkey);
3898 /* Send the channel key. This sends it to our local clients and if
3899 we are normal server to our router as well. */
3900 silc_server_send_channel_key(server, NULL, channel,
3901 server->server_type == SILC_ROUTER ?
3902 FALSE : !server->standalone);
3906 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3907 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3908 /* HMAC to use protect the traffic */
3909 unsigned char hash[32];
3913 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3915 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3916 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3920 /* Delete old hmac and allocate the new one */
3921 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
3922 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3923 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3927 silc_hmac_free(channel->hmac);
3928 channel->hmac = newhmac;
3930 /* Set the HMAC key out of current channel key. The client must do
3932 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
3933 channel->key_len / 8, hash);
3934 silc_hmac_set_key(channel->hmac, hash,
3935 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3936 memset(hash, 0, sizeof(hash));
3939 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
3940 /* Hmac mode is unset. Remove the hmac and revert back to
3943 unsigned char hash[32];
3944 hmac = channel->hmac_name;
3946 /* Delete old hmac and allocate default one */
3947 silc_hmac_free(channel->hmac);
3948 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
3949 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3950 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3954 silc_hmac_free(channel->hmac);
3955 channel->hmac = newhmac;
3957 /* Set the HMAC key out of current channel key. The client must do
3959 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
3960 channel->key_len / 8,
3962 silc_hmac_set_key(channel->hmac, hash,
3963 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3964 memset(hash, 0, sizeof(hash));
3968 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3969 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3970 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
3971 /* Set the founder authentication */
3972 SilcAuthPayload auth;
3974 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
3976 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3977 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3981 auth = silc_auth_payload_parse(tmp, tmp_len);
3983 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3984 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3988 /* Save the public key */
3989 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
3990 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
3993 channel->founder_method = silc_auth_get_method(auth);
3995 if (channel->founder_method == SILC_AUTH_PASSWORD) {
3996 tmp = silc_auth_get_data(auth, &tmp_len);
3997 channel->founder_passwd = silc_memdup(tmp, tmp_len);
3998 channel->founder_passwd_len = tmp_len;
4000 /* Verify the payload before setting the mode */
4001 if (!silc_auth_verify(auth, channel->founder_method,
4002 channel->founder_key, 0, idata->hash,
4003 client->id, SILC_ID_CLIENT)) {
4004 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4005 SILC_STATUS_ERR_AUTH_FAILED);
4010 silc_auth_payload_free(auth);
4014 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4015 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4016 if (channel->founder_key)
4017 silc_pkcs_public_key_free(channel->founder_key);
4018 if (channel->founder_passwd) {
4019 silc_free(channel->founder_passwd);
4020 channel->founder_passwd = NULL;
4026 /* Finally, set the mode */
4027 channel->mode = mode_mask;
4029 /* Send CMODE_CHANGE notify. */
4030 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4031 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4032 SILC_NOTIFY_TYPE_CMODE_CHANGE, 5,
4033 cidp->data, cidp->len,
4035 cipher, cipher ? strlen(cipher) : 0,
4036 hmac, hmac ? strlen(hmac) : 0,
4037 passphrase, passphrase ?
4038 strlen(passphrase) : 0);
4040 /* Set CMODE notify type to network */
4041 if (!server->standalone)
4042 silc_server_send_notify_cmode(server, server->router->connection,
4043 server->server_type == SILC_ROUTER ?
4044 TRUE : FALSE, channel,
4045 mode_mask, client->id, SILC_ID_CLIENT,
4046 cipher, hmac, passphrase);
4048 /* Send command reply to sender */
4049 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4050 SILC_STATUS_OK, ident, 2,
4051 2, tmp_id, tmp_len2,
4053 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4054 packet->data, packet->len, FALSE);
4056 silc_buffer_free(packet);
4057 silc_free(channel_id);
4058 silc_buffer_free(cidp);
4061 silc_server_command_free(cmd);
4064 /* Server side of CUMODE command. Changes client's mode on a channel. */
4066 SILC_SERVER_CMD_FUNC(cumode)
4068 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4069 SilcServer server = cmd->server;
4070 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4071 SilcIDListData idata = (SilcIDListData)client;
4072 SilcChannelID *channel_id;
4073 SilcClientID *client_id;
4074 SilcChannelEntry channel;
4075 SilcClientEntry target_client;
4076 SilcChannelClientEntry chl;
4077 SilcBuffer packet, idp;
4078 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4079 SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4081 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4083 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4085 /* Get Channel ID */
4086 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4088 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4089 SILC_STATUS_ERR_NO_CHANNEL_ID);
4092 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
4094 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4095 SILC_STATUS_ERR_NO_CHANNEL_ID);
4099 /* Get channel entry */
4100 channel = silc_idlist_find_channel_by_id(server->local_list,
4103 channel = silc_idlist_find_channel_by_id(server->global_list,
4106 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4107 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4112 /* Check whether sender is on the channel */
4113 if (!silc_server_client_on_channel(client, channel, &chl)) {
4114 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4115 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4118 sender_mask = chl->mode;
4120 /* Get the target client's channel mode mask */
4121 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4123 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4124 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4127 SILC_GET32_MSB(target_mask, tmp_mask);
4129 /* Get target Client ID */
4130 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4132 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4133 SILC_STATUS_ERR_NO_CLIENT_ID);
4136 client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
4138 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4139 SILC_STATUS_ERR_NO_CLIENT_ID);
4143 /* Get target client's entry */
4144 target_client = silc_idlist_find_client_by_id(server->local_list,
4145 client_id, TRUE, NULL);
4146 if (!target_client) {
4147 target_client = silc_idlist_find_client_by_id(server->global_list,
4148 client_id, TRUE, NULL);
4151 if (target_client != client &&
4152 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4153 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4154 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4155 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4159 /* Check whether target client is on the channel */
4160 if (target_client != client) {
4161 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4162 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4163 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4172 /* If the target client is founder, no one else can change their mode
4174 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4175 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4176 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4180 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4181 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4182 /* The client tries to claim the founder rights. */
4183 unsigned char *tmp_auth;
4184 SilcUInt32 tmp_auth_len, auth_len;
4187 if (target_client != client) {
4188 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4189 SILC_STATUS_ERR_NOT_YOU);
4193 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4194 !channel->founder_key || !idata->public_key ||
4195 !silc_pkcs_public_key_compare(channel->founder_key,
4196 idata->public_key)) {
4197 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4198 SILC_STATUS_ERR_NOT_YOU);
4202 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4204 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4205 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4209 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4210 (void *)channel->founder_passwd : (void *)channel->founder_key);
4211 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4212 channel->founder_passwd_len : 0);
4214 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4215 channel->founder_method, auth, auth_len,
4216 idata->hash, client->id, SILC_ID_CLIENT)) {
4217 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4218 SILC_STATUS_ERR_AUTH_FAILED);
4222 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4226 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4227 if (target_client == client) {
4228 /* Remove channel founder rights from itself */
4229 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4232 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4233 SILC_STATUS_ERR_NOT_YOU);
4239 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4240 /* Promote to operator */
4241 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4242 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4243 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4244 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4245 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4249 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4253 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4254 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4255 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4256 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4257 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4261 /* Demote to normal user */
4262 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4267 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4268 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4270 /* Send notify to channel, notify only if mode was actually changed. */
4272 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4273 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4274 idp->data, idp->len,
4278 /* Set CUMODE notify type to network */
4279 if (!server->standalone)
4280 silc_server_send_notify_cumode(server, server->router->connection,
4281 server->server_type == SILC_ROUTER ?
4282 TRUE : FALSE, channel,
4283 target_mask, client->id,
4288 /* Send command reply to sender */
4289 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4290 SILC_STATUS_OK, ident, 3,
4292 3, tmp_ch_id, tmp_ch_len,
4293 4, tmp_id, tmp_len);
4294 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4295 packet->data, packet->len, FALSE);
4297 silc_buffer_free(packet);
4298 silc_free(channel_id);
4299 silc_free(client_id);
4300 silc_buffer_free(idp);
4303 silc_server_command_free(cmd);
4306 /* Server side of KICK command. Kicks client out of channel. */
4308 SILC_SERVER_CMD_FUNC(kick)
4310 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4311 SilcServer server = cmd->server;
4312 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4313 SilcClientEntry target_client;
4314 SilcChannelID *channel_id;
4315 SilcClientID *client_id;
4316 SilcChannelEntry channel;
4317 SilcChannelClientEntry chl;
4319 SilcUInt32 tmp_len, target_idp_len;
4320 unsigned char *tmp, *comment, *target_idp;
4322 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4324 /* Get Channel ID */
4325 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4327 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4328 SILC_STATUS_ERR_NO_CHANNEL_ID);
4331 channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4333 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4334 SILC_STATUS_ERR_NO_CHANNEL_ID);
4338 /* Get channel entry */
4339 channel = silc_idlist_find_channel_by_id(server->local_list,
4342 channel = silc_idlist_find_channel_by_id(server->local_list,
4345 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4346 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4351 /* Check whether sender is on the channel */
4352 if (!silc_server_client_on_channel(client, channel, &chl)) {
4353 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4354 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4358 /* Check that the kicker is channel operator or channel founder */
4359 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4360 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4361 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4365 /* Get target Client ID */
4366 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4368 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4369 SILC_STATUS_ERR_NO_CLIENT_ID);
4372 client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
4374 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4375 SILC_STATUS_ERR_NO_CLIENT_ID);
4379 /* Get target client's entry */
4380 target_client = silc_idlist_find_client_by_id(server->local_list,
4381 client_id, TRUE, NULL);
4382 if (!target_client) {
4383 target_client = silc_idlist_find_client_by_id(server->global_list,
4384 client_id, TRUE, NULL);
4387 /* Check whether target client is on the channel */
4388 if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4389 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4390 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4394 /* Check that the target client is not channel founder. Channel founder
4395 cannot be kicked from the channel. */
4396 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4397 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4398 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4404 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4408 /* Send command reply to sender */
4409 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4412 /* Send KICKED notify to local clients on the channel */
4413 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4414 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4415 SILC_NOTIFY_TYPE_KICKED, 3,
4416 target_idp, target_idp_len,
4417 comment, comment ? strlen(comment) : 0,
4418 idp->data, idp->len);
4419 silc_buffer_free(idp);
4421 /* Remove the client from the channel. If the channel does not exist
4422 after removing the client then the client kicked itself off the channel
4423 and we don't have to send anything after that. */
4424 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4425 target_client, FALSE))
4428 /* Send KICKED notify to primary route */
4429 if (!server->standalone)
4430 silc_server_send_notify_kicked(server, server->router->connection,
4431 server->server_type == SILC_ROUTER ?
4432 TRUE : FALSE, channel,
4433 target_client->id, client->id, comment);
4435 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4436 /* Re-generate channel key */
4437 if (!silc_server_create_channel_key(server, channel, 0))
4440 /* Send the channel key to the channel. The key of course is not sent
4441 to the client who was kicked off the channel. */
4442 silc_server_send_channel_key(server, target_client->connection, channel,
4443 server->server_type == SILC_ROUTER ?
4444 FALSE : !server->standalone);
4448 silc_server_command_free(cmd);
4451 /* Server side of OPER command. Client uses this comand to obtain server
4452 operator privileges to this server/router. */
4454 SILC_SERVER_CMD_FUNC(oper)
4456 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4457 SilcServer server = cmd->server;
4458 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4459 unsigned char *username, *auth;
4461 SilcServerConfigAdmin *admin;
4462 SilcIDListData idata = (SilcIDListData)client;
4463 bool result = FALSE;
4464 SilcPublicKey cached_key;
4466 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4468 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4471 /* Get the username */
4472 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4474 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4475 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4479 /* Get the admin configuration */
4480 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4481 username, client->nickname);
4483 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4484 username, client->nickname);
4486 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4487 SILC_STATUS_ERR_AUTH_FAILED);
4492 /* Get the authentication payload */
4493 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4495 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4496 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4500 /* Verify the authentication data. If both passphrase and public key
4501 is set then try both of them. */
4502 if (admin->passphrase)
4503 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4504 admin->passphrase, admin->passphrase_len,
4505 idata->hash, client->id, SILC_ID_CLIENT);
4506 if (!result && admin->publickeys) {
4507 cached_key = silc_server_get_public_key(server, admin->publickeys);
4510 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4511 cached_key, 0, idata->hash,
4512 client->id, SILC_ID_CLIENT);
4515 /* Authentication failed */
4516 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4517 SILC_STATUS_ERR_AUTH_FAILED);
4521 /* Client is now server operator */
4522 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4524 /* Update statistics */
4525 if (client->connection)
4526 server->stat.my_server_ops++;
4527 if (server->server_type == SILC_ROUTER)
4528 server->stat.server_ops++;
4530 /* Send UMODE change to primary router */
4531 if (!server->standalone)
4532 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4533 client->id, client->mode);
4535 /* Send reply to the sender */
4536 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4540 silc_server_command_free(cmd);
4543 /* Server side of SILCOPER command. Client uses this comand to obtain router
4544 operator privileges to this router. */
4546 SILC_SERVER_CMD_FUNC(silcoper)
4548 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4549 SilcServer server = cmd->server;
4550 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4551 unsigned char *username, *auth;
4553 SilcServerConfigAdmin *admin;
4554 SilcIDListData idata = (SilcIDListData)client;
4555 bool result = FALSE;
4556 SilcPublicKey cached_key;
4558 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4560 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4563 if (server->server_type != SILC_ROUTER) {
4564 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4565 SILC_STATUS_ERR_AUTH_FAILED);
4569 /* Get the username */
4570 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4572 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4573 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4577 /* Get the admin configuration */
4578 admin = silc_server_config_find_admin(server, cmd->sock->ip,
4579 username, client->nickname);
4581 admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4582 username, client->nickname);
4584 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4585 SILC_STATUS_ERR_AUTH_FAILED);
4590 /* Get the authentication payload */
4591 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4593 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4594 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4598 /* Verify the authentication data. If both passphrase and public key
4599 is set then try both of them. */
4600 if (admin->passphrase)
4601 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4602 admin->passphrase, admin->passphrase_len,
4603 idata->hash, client->id, SILC_ID_CLIENT);
4604 if (!result && admin->publickeys) {
4605 cached_key = silc_server_get_public_key(server, admin->publickeys);
4608 result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4609 cached_key, 0, idata->hash,
4610 client->id, SILC_ID_CLIENT);
4613 /* Authentication failed */
4614 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4615 SILC_STATUS_ERR_AUTH_FAILED);
4619 /* Client is now router operator */
4620 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4622 /* Update statistics */
4623 if (client->connection)
4624 server->stat.my_router_ops++;
4625 if (server->server_type == SILC_ROUTER)
4626 server->stat.router_ops++;
4628 /* Send UMODE change to primary router */
4629 if (!server->standalone)
4630 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4631 client->id, client->mode);
4633 /* Send reply to the sender */
4634 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4638 silc_server_command_free(cmd);
4641 /* Server side command of CONNECT. Connects us to the specified remote
4642 server or router. */
4644 SILC_SERVER_CMD_FUNC(connect)
4646 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4647 SilcServer server = cmd->server;
4648 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4649 unsigned char *tmp, *host;
4651 SilcUInt32 port = SILC_PORT;
4653 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CONNECT, cmd, 1, 2);
4655 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4658 /* Check whether client has the permissions. */
4659 if (client->mode == SILC_UMODE_NONE) {
4660 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4661 SILC_STATUS_ERR_NO_SERVER_PRIV);
4665 if (server->server_type == SILC_ROUTER &&
4666 client->mode & SILC_UMODE_SERVER_OPERATOR) {
4667 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4668 SILC_STATUS_ERR_NO_ROUTER_PRIV);
4672 /* Get the remote server */
4673 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4675 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4676 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4681 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4683 SILC_GET32_MSB(port, tmp);
4685 /* Create the connection. It is done with timeout and is async. */
4686 silc_server_create_connection(server, host, port);
4688 /* Send reply to the sender */
4689 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4693 silc_server_command_free(cmd);
4696 /* Server side of command BAN. This is used to manage the ban list of the
4697 channel. To add clients and remove clients from the ban list. */
4699 SILC_SERVER_CMD_FUNC(ban)
4701 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4702 SilcServer server = cmd->server;
4703 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4705 SilcChannelEntry channel;
4706 SilcChannelClientEntry chl;
4707 SilcChannelID *channel_id = NULL;
4708 unsigned char *id, *add, *del;
4709 SilcUInt32 id_len, tmp_len;
4710 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4712 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4715 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4717 /* Get Channel ID */
4718 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4720 channel_id = silc_id_payload_parse_id(id, id_len, NULL);
4722 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4723 SILC_STATUS_ERR_NO_CHANNEL_ID);
4728 /* Get channel entry. The server must know about the channel since the
4729 client is expected to be on the channel. */
4730 channel = silc_idlist_find_channel_by_id(server->local_list,
4733 channel = silc_idlist_find_channel_by_id(server->global_list,
4736 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4737 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4742 /* Check whether this client is on the channel */
4743 if (!silc_server_client_on_channel(client, channel, &chl)) {
4744 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4745 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4749 /* The client must be at least channel operator. */
4750 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4751 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4752 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4756 /* Get the new ban and add it to the ban list */
4757 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4759 if (!channel->ban_list)
4760 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4762 channel->ban_list = silc_realloc(channel->ban_list,
4763 sizeof(*channel->ban_list) *
4765 strlen(channel->ban_list) + 2));
4766 if (add[tmp_len - 1] == ',')
4767 add[tmp_len - 1] = '\0';
4769 strncat(channel->ban_list, add, tmp_len);
4770 strncat(channel->ban_list, ",", 1);
4773 /* Get the ban to be removed and remove it from the list */
4774 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4775 if (del && channel->ban_list) {
4776 char *start, *end, *n;
4778 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4779 silc_free(channel->ban_list);
4780 channel->ban_list = NULL;
4782 start = strstr(channel->ban_list, del);
4783 if (start && strlen(start) >= tmp_len) {
4784 end = start + tmp_len;
4785 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4786 strncat(n, channel->ban_list, start - channel->ban_list);
4787 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4789 silc_free(channel->ban_list);
4790 channel->ban_list = n;
4795 /* Send the BAN notify type to our primary router. */
4796 if (!server->standalone && (add || del))
4797 silc_server_send_notify_ban(server, server->router->connection,
4798 server->server_type == SILC_ROUTER ?
4799 TRUE : FALSE, channel, add, del);
4801 /* Send the reply back to the client */
4803 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4804 SILC_STATUS_OK, ident, 2,
4806 3, channel->ban_list,
4808 strlen(channel->ban_list) -1 : 0);
4809 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4810 packet->data, packet->len, FALSE);
4812 silc_buffer_free(packet);
4815 silc_free(channel_id);
4816 silc_server_command_free(cmd);
4819 /* Server side command of CLOSE. Closes connection to a specified server. */
4821 SILC_SERVER_CMD_FUNC(close)
4823 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4824 SilcServer server = cmd->server;
4825 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4826 SilcServerEntry server_entry;
4827 SilcSocketConnection sock;
4830 unsigned char *name;
4831 SilcUInt32 port = SILC_PORT;
4833 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CLOSE, cmd, 1, 2);
4835 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4838 /* Check whether client has the permissions. */
4839 if (client->mode == SILC_UMODE_NONE) {
4840 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4841 SILC_STATUS_ERR_NO_SERVER_PRIV);
4845 /* Get the remote server */
4846 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4848 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4849 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4854 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4856 SILC_GET32_MSB(port, tmp);
4858 server_entry = silc_idlist_find_server_by_conn(server->local_list,
4859 name, port, FALSE, NULL);
4861 server_entry = silc_idlist_find_server_by_conn(server->global_list,
4862 name, port, FALSE, NULL);
4863 if (!server_entry) {
4864 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4865 SILC_STATUS_ERR_NO_SERVER_ID);
4869 /* Send reply to the sender */
4870 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4873 /* Close the connection to the server */
4874 sock = (SilcSocketConnection)server_entry->connection;
4876 /* If we shutdown primary router connection manually then don't trigger
4877 any reconnect or backup router connections, by setting the router
4879 if (server->router == server_entry) {
4880 server->id_entry->router = NULL;
4881 server->router = NULL;
4882 server->standalone = TRUE;
4884 silc_server_free_sock_user_data(server, sock, NULL);
4885 silc_server_close_connection(server, sock);
4888 silc_server_command_free(cmd);
4891 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4892 active connections. */
4894 SILC_SERVER_CMD_FUNC(shutdown)
4896 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4897 SilcServer server = cmd->server;
4898 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4900 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4902 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4905 /* Check whether client has the permission. */
4906 if (client->mode == SILC_UMODE_NONE) {
4907 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4908 SILC_STATUS_ERR_NO_SERVER_PRIV);
4912 /* Send reply to the sender */
4913 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4916 /* Then, gracefully, or not, bring the server down. */
4917 silc_server_stop(server);
4921 silc_server_command_free(cmd);
4924 /* Server side command of LEAVE. Removes client from a channel. */
4926 SILC_SERVER_CMD_FUNC(leave)
4928 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4929 SilcServer server = cmd->server;
4930 SilcSocketConnection sock = cmd->sock;
4931 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4932 SilcChannelID *id = NULL;
4933 SilcChannelEntry channel;
4937 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4939 /* Get Channel ID */
4940 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4942 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4943 SILC_STATUS_ERR_NO_CHANNEL_ID);
4946 id = silc_id_payload_parse_id(tmp, len, NULL);
4948 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4949 SILC_STATUS_ERR_NO_CHANNEL_ID);
4953 /* Get channel entry */
4954 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4956 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4958 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4959 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4964 /* Check whether this client is on the channel */
4965 if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
4966 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4967 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4971 /* Notify routers that they should remove this client from their list
4972 of clients on the channel. Send LEAVE notify type. */
4973 if (!server->standalone)
4974 silc_server_send_notify_leave(server, server->router->connection,
4975 server->server_type == SILC_ROUTER ?
4976 TRUE : FALSE, channel, id_entry->id);
4978 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4981 /* Remove client from channel */
4982 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4984 /* If the channel does not exist anymore we won't send anything */
4987 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4988 /* Re-generate channel key */
4989 if (!silc_server_create_channel_key(server, channel, 0))
4992 /* Send the channel key */
4993 silc_server_send_channel_key(server, NULL, channel,
4994 server->server_type == SILC_ROUTER ?
4995 FALSE : !server->standalone);
5000 silc_server_command_free(cmd);
5003 /* Server side of command USERS. Resolves clients and their USERS currently
5004 joined on the requested channel. The list of Client ID's and their modes
5005 on the channel is sent back. */
5007 SILC_SERVER_CMD_FUNC(users)
5009 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5010 SilcServer server = cmd->server;
5011 SilcChannelEntry channel;
5012 SilcChannelID *id = NULL;
5013 SilcBuffer packet, idp;
5014 unsigned char *channel_id;
5015 SilcUInt32 channel_id_len;
5016 SilcBuffer client_id_list;
5017 SilcBuffer client_mode_list;
5018 unsigned char lc[4];
5019 SilcUInt32 list_count = 0;
5020 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5023 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5025 /* Get Channel ID */
5026 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5028 /* Get channel name */
5029 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5031 if (!channel_id && !channel_name) {
5032 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5033 SILC_STATUS_ERR_NO_CHANNEL_ID);
5038 id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
5040 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5041 SILC_STATUS_ERR_NO_CHANNEL_ID);
5046 /* If we are server and we don't know about this channel we will send
5047 the command to our router. If we know about the channel then we also
5048 have the list of users already. */
5050 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5052 channel = silc_idlist_find_channel_by_name(server->local_list,
5053 channel_name, NULL);
5055 if (!channel || channel->disabled) {
5056 if (server->server_type != SILC_ROUTER && !server->standalone &&
5060 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5061 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5063 /* Send USERS command */
5064 silc_server_packet_send(server, server->router->connection,
5065 SILC_PACKET_COMMAND, cmd->packet->flags,
5066 tmpbuf->data, tmpbuf->len, TRUE);
5068 /* Reprocess this packet after received reply */
5069 silc_server_command_pending(server, SILC_COMMAND_USERS,
5070 silc_command_get_ident(cmd->payload),
5071 silc_server_command_users,
5072 silc_server_command_dup(cmd));
5073 cmd->pending = TRUE;
5074 silc_command_set_ident(cmd->payload, ident);
5075 silc_buffer_free(tmpbuf);
5080 /* Check the global list as well. */
5082 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5084 channel = silc_idlist_find_channel_by_name(server->global_list,
5085 channel_name, NULL);
5087 /* Channel really does not exist */
5088 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5089 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5094 /* If the channel is private or secret do not send anything, unless the
5095 user requesting this command is on the channel. */
5096 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5097 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5098 && !silc_server_client_on_channel(cmd->sock->user_data, channel,
5100 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5101 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5106 (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
5107 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5108 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5113 /* Get the users list */
5114 silc_server_get_users_on_channel(server, channel, &client_id_list,
5115 &client_mode_list, &list_count);
5118 SILC_PUT32_MSB(list_count, lc);
5121 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5122 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5123 SILC_STATUS_OK, ident, 4,
5124 2, idp->data, idp->len,
5126 4, client_id_list->data,
5127 client_id_list->len,
5128 5, client_mode_list->data,
5129 client_mode_list->len);
5130 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5131 packet->data, packet->len, FALSE);
5133 silc_buffer_free(idp);
5134 silc_buffer_free(packet);
5135 silc_buffer_free(client_id_list);
5136 silc_buffer_free(client_mode_list);
5140 silc_server_command_free(cmd);
5143 /* Server side of command GETKEY. This fetches the client's public key
5144 from the server where to the client is connected. */
5146 SILC_SERVER_CMD_FUNC(getkey)
5148 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5149 SilcServer server = cmd->server;
5151 SilcClientEntry client;
5152 SilcServerEntry server_entry;
5153 SilcClientID *client_id = NULL;
5154 SilcServerID *server_id = NULL;
5155 SilcIDPayload idp = NULL;
5156 SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5157 unsigned char *tmp, *pkdata;
5158 SilcUInt32 tmp_len, pklen;
5159 SilcBuffer pk = NULL;
5161 SilcPublicKey public_key;
5163 SILC_LOG_DEBUG(("Start"));
5165 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5167 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5168 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5171 idp = silc_id_payload_parse(tmp, tmp_len);
5173 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5174 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5178 id_type = silc_id_payload_get_type(idp);
5179 if (id_type == SILC_ID_CLIENT) {
5180 client_id = silc_id_payload_get_id(idp);
5182 /* If the client is not found from local list there is no chance it
5183 would be locally connected client so send the command further. */
5184 client = silc_idlist_find_client_by_id(server->local_list,
5185 client_id, TRUE, NULL);
5187 client = silc_idlist_find_client_by_id(server->global_list,
5188 client_id, TRUE, NULL);
5190 if ((!client && !cmd->pending && !server->standalone) ||
5191 (client && !client->connection && !cmd->pending) ||
5192 (client && !client->data.public_key && !cmd->pending)) {
5194 SilcUInt16 old_ident;
5195 SilcSocketConnection dest_sock;
5197 dest_sock = silc_server_get_client_route(server, NULL, 0,
5202 old_ident = silc_command_get_ident(cmd->payload);
5203 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5204 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5206 silc_server_packet_send(server, dest_sock,
5207 SILC_PACKET_COMMAND, cmd->packet->flags,
5208 tmpbuf->data, tmpbuf->len, TRUE);
5210 /* Reprocess this packet after received reply from router */
5211 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5212 silc_command_get_ident(cmd->payload),
5213 silc_server_command_getkey,
5214 silc_server_command_dup(cmd));
5215 cmd->pending = TRUE;
5216 silc_command_set_ident(cmd->payload, old_ident);
5217 silc_buffer_free(tmpbuf);
5222 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5223 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5227 /* The client is locally connected, just get the public key and
5228 send it back. If they key does not exist then do not send it,
5229 send just OK reply */
5230 public_key = client->data.public_key;
5235 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5236 pk = silc_buffer_alloc(4 + tmp_len);
5237 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5238 silc_buffer_format(pk,
5239 SILC_STR_UI_SHORT(tmp_len),
5240 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5241 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5247 } else if (id_type == SILC_ID_SERVER) {
5248 server_id = silc_id_payload_get_id(idp);
5250 /* If the server is not found from local list there is no chance it
5251 would be locally connected server so send the command further. */
5252 server_entry = silc_idlist_find_server_by_id(server->local_list,
5253 server_id, TRUE, NULL);
5255 server_entry = silc_idlist_find_server_by_id(server->global_list,
5256 server_id, TRUE, NULL);
5258 if (server_entry != server->id_entry &&
5259 ((!server_entry && !cmd->pending && !server->standalone) ||
5260 (server_entry && !server_entry->connection && !cmd->pending &&
5261 !server->standalone) ||
5262 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5263 !server->standalone))) {
5265 SilcUInt16 old_ident;
5267 old_ident = silc_command_get_ident(cmd->payload);
5268 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5269 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5271 silc_server_packet_send(server, server->router->connection,
5272 SILC_PACKET_COMMAND, cmd->packet->flags,
5273 tmpbuf->data, tmpbuf->len, TRUE);
5275 /* Reprocess this packet after received reply from router */
5276 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5277 silc_command_get_ident(cmd->payload),
5278 silc_server_command_getkey,
5279 silc_server_command_dup(cmd));
5280 cmd->pending = TRUE;
5281 silc_command_set_ident(cmd->payload, old_ident);
5282 silc_buffer_free(tmpbuf);
5286 if (!server_entry) {
5287 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5288 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5292 /* If they key does not exist then do not send it, send just OK reply */
5293 public_key = (!server_entry->data.public_key ?
5294 (server_entry == server->id_entry ? server->public_key :
5295 NULL) : server_entry->data.public_key);
5300 tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5301 pk = silc_buffer_alloc(4 + tmp_len);
5302 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5303 silc_buffer_format(pk,
5304 SILC_STR_UI_SHORT(tmp_len),
5305 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5306 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5316 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5317 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5318 SILC_STATUS_OK, ident,
5322 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5323 packet->data, packet->len, FALSE);
5324 silc_buffer_free(packet);
5327 silc_buffer_free(pk);
5331 silc_id_payload_free(idp);
5332 silc_free(client_id);
5333 silc_free(server_id);
5334 silc_server_command_free(cmd);