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);
134 silc_server_command_free(cmd);
138 /* Internal context to hold data when executed command with timeout. */
140 SilcServerCommandContext ctx;
141 SilcServerCommand *cmd;
142 } *SilcServerCommandTimeout;
144 /* Timeout callback to process commands with timeout for client. Client's
145 commands are always executed with timeout. */
147 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
149 SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
150 SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data;
152 /* Update access time */
153 client->last_command = time(NULL);
155 if (!(timeout->cmd->flags & SILC_CF_REG))
156 timeout->cmd->cb(timeout->ctx, NULL);
157 else if (silc_server_is_registered(timeout->ctx->server,
161 timeout->cmd->cb(timeout->ctx, NULL);
166 /* Processes received command packet. */
168 void silc_server_command_process(SilcServer server,
169 SilcSocketConnection sock,
170 SilcPacketContext *packet)
172 SilcServerCommandContext ctx;
173 SilcServerCommand *cmd;
176 /* Allocate command context. This must be free'd by the
177 command routine receiving it. */
178 ctx = silc_server_command_alloc();
179 ctx->server = server;
180 ctx->sock = silc_socket_dup(sock);
181 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
183 /* Parse the command payload in the packet */
184 ctx->payload = silc_command_payload_parse(packet->buffer->data,
185 packet->buffer->len);
187 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
188 silc_buffer_free(packet->buffer);
189 silc_packet_context_free(packet);
190 silc_socket_free(ctx->sock);
194 ctx->args = silc_command_get_args(ctx->payload);
196 /* Get the command */
197 command = silc_command_get(ctx->payload);
198 for (cmd = silc_command_list; cmd->cb; cmd++)
199 if (cmd->cmd == command)
203 silc_server_command_send_status_reply(ctx, command,
204 SILC_STATUS_ERR_UNKNOWN_COMMAND);
205 silc_server_command_free(ctx);
209 /* Execute client's commands always with timeout. Normally they are
210 executed with zero (0) timeout but if client is sending command more
211 frequently than once in 2 seconds, then the timeout may be 0 to 2
213 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
214 SilcClientEntry client = (SilcClientEntry)sock->user_data;
215 SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
221 if (client->last_command && (time(NULL) - client->last_command) < 2) {
222 client->fast_command++;
225 client->fast_command = ((client->fast_command - 1) <= 0 ? 0 :
226 client->fast_command--);
230 if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
231 (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
232 silc_schedule_task_add(server->schedule, sock->sock,
233 silc_server_command_process_timeout,
235 2 - (time(NULL) - client->last_command), 0,
237 SILC_TASK_PRI_NORMAL);
239 silc_schedule_task_add(server->schedule, sock->sock,
240 silc_server_command_process_timeout,
244 SILC_TASK_PRI_NORMAL);
248 /* Execute for server */
250 if (!(cmd->flags & SILC_CF_REG))
252 else if (silc_server_is_registered(server, sock, ctx, cmd->cmd))
256 /* Allocate Command Context */
258 SilcServerCommandContext silc_server_command_alloc()
260 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
265 /* Free's the command context allocated before executing the command */
267 void silc_server_command_free(SilcServerCommandContext ctx)
270 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
272 if (ctx->users < 1) {
274 silc_command_payload_free(ctx->payload);
276 silc_packet_context_free(ctx->packet);
278 silc_socket_free(ctx->sock); /* Decrease reference counter */
283 /* Duplicate Command Context by adding reference counter. The context won't
284 be free'd untill it hits zero. */
286 SilcServerCommandContext
287 silc_server_command_dup(SilcServerCommandContext ctx)
290 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
295 /* Add new pending command to be executed when reply to a command has been
296 received. The `reply_cmd' is the command that will call the `callback'
297 with `context' when reply has been received. It can be SILC_COMMAND_NONE
298 to match any command with the `ident'. If `ident' is non-zero
299 the `callback' will be executed when received reply with command
300 identifier `ident'. If there already exists pending command for the
301 specified command, ident, callback and context this function has no
304 bool silc_server_command_pending(SilcServer server,
305 SilcCommand reply_cmd,
307 SilcCommandCb callback,
310 SilcServerCommandPending *reply;
312 /* Check whether identical pending already exists for same command,
313 ident, callback and callback context. If it does then it would be
314 error to register it again. */
315 silc_dlist_start(server->pending_commands);
316 while ((reply = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
317 if (reply->reply_cmd == reply_cmd && reply->ident == ident &&
318 reply->callback == callback && reply->context == context)
322 reply = silc_calloc(1, sizeof(*reply));
323 reply->reply_cmd = reply_cmd;
324 reply->ident = ident;
325 reply->context = context;
326 reply->callback = callback;
327 silc_dlist_add(server->pending_commands, reply);
332 /* Deletes pending command by reply command type. */
334 void silc_server_command_pending_del(SilcServer server,
335 SilcCommand reply_cmd,
338 SilcServerCommandPending *r;
340 silc_dlist_start(server->pending_commands);
341 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
342 if (r->reply_cmd == reply_cmd && r->ident == ident) {
343 silc_dlist_del(server->pending_commands, r);
349 /* Checks for pending commands and marks callbacks to be called from
350 the command reply function. Returns TRUE if there were pending command. */
352 SilcServerCommandPendingCallbacks
353 silc_server_command_pending_check(SilcServer server,
354 SilcServerCommandReplyContext ctx,
357 uint32 *callbacks_count)
359 SilcServerCommandPending *r;
360 SilcServerCommandPendingCallbacks callbacks = NULL;
363 silc_dlist_start(server->pending_commands);
364 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
365 if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE)
366 && r->ident == ident) {
367 callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
368 callbacks[i].context = r->context;
369 callbacks[i].callback = r->callback;
375 *callbacks_count = i;
379 /* Sends simple status message as command reply packet */
382 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
384 SilcCommandStatus status)
388 SILC_LOG_DEBUG(("Sending command status %d", status));
391 silc_command_reply_payload_encode_va(command, status,
392 silc_command_get_ident(cmd->payload),
394 silc_server_packet_send(cmd->server, cmd->sock,
395 SILC_PACKET_COMMAND_REPLY, 0,
396 buffer->data, buffer->len, FALSE);
397 silc_buffer_free(buffer);
400 /* Sends command status reply with one extra argument. The argument
401 type must be sent as argument. */
404 silc_server_command_send_status_data(SilcServerCommandContext cmd,
406 SilcCommandStatus status,
408 const unsigned char *arg,
413 SILC_LOG_DEBUG(("Sending command status %d", status));
416 silc_command_reply_payload_encode_va(command, status,
417 silc_command_get_ident(cmd->payload),
418 1, arg_type, arg, arg_len);
419 silc_server_packet_send(cmd->server, cmd->sock,
420 SILC_PACKET_COMMAND_REPLY, 0,
421 buffer->data, buffer->len, FALSE);
422 silc_buffer_free(buffer);
425 /* This function can be called to check whether in the command reply
426 an error occurred. This function has no effect if this is called
427 when the command function was not called as pending command callback.
428 This returns TRUE if error had occurred. */
431 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
432 SilcServerCommandReplyContext cmdr,
435 SilcCommandStatus status;
437 if (!cmd->pending || !cmdr)
440 SILC_GET16_MSB(status, silc_argument_get_arg_type(cmdr->args, 1, NULL));
441 if (status != SILC_STATUS_OK &&
442 status != SILC_STATUS_LIST_START &&
443 status != SILC_STATUS_LIST_ITEM &&
444 status != SILC_STATUS_LIST_END) {
447 /* Send the same command reply payload */
448 silc_command_set_ident(cmdr->payload,
449 silc_command_get_ident(cmd->payload));
450 buffer = silc_command_payload_encode_payload(cmdr->payload);
451 silc_server_packet_send(cmd->server, cmd->sock,
452 SILC_PACKET_COMMAND_REPLY, 0,
453 buffer->data, buffer->len, FALSE);
454 silc_buffer_free(buffer);
461 /******************************************************************************
465 ******************************************************************************/
468 silc_server_command_whois_parse(SilcServerCommandContext cmd,
469 SilcClientID ***client_id,
470 uint32 *client_id_count,
478 uint32 argc = silc_argument_get_arg_num(cmd->args);
481 /* If client ID is in the command it must be used instead of nickname */
482 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
484 /* No ID, get the nickname@server string and parse it. */
485 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
487 silc_parse_userfqdn(tmp, nickname, server_name);
489 silc_server_command_send_status_reply(cmd, command,
490 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
494 /* Command includes ID, we must use that. Also check whether the command
495 has more than one ID set - take them all. */
497 *client_id = silc_calloc(1, sizeof(**client_id));
498 (*client_id)[0] = silc_id_payload_parse_id(tmp, len);
499 if ((*client_id)[0] == NULL) {
500 silc_free(*client_id);
503 *client_id_count = 1;
505 /* Take all ID's from the command packet */
507 for (k = 1, i = 1; i < argc; i++) {
508 tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
510 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
511 (*client_id_count + 1));
512 (*client_id)[k] = silc_id_payload_parse_id(tmp, len);
513 if ((*client_id)[k] == NULL) {
514 /* Cleanup all and fail */
515 for (i = 0; i < *client_id_count; i++)
516 silc_free((*client_id)[i]);
517 silc_free(*client_id);
520 (*client_id_count)++;
527 /* Get the max count of reply messages allowed */
528 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
537 /* Resolve context used by both WHOIS and IDENTIFY commands */
539 SilcServerEntry router;
541 unsigned char **res_argv;
542 uint32 *res_argv_lens;
543 uint32 *res_argv_types;
545 } *SilcServerResolveContext;
548 silc_server_command_whois_check(SilcServerCommandContext cmd,
549 SilcClientEntry *clients,
550 uint32 clients_count)
552 SilcServer server = cmd->server;
553 SilcClientEntry entry;
554 SilcServerResolveContext resolve = NULL, r = NULL;
555 uint32 resolve_count = 0;
559 for (i = 0; i < clients_count; i++) {
564 if ((entry->nickname && entry->username && entry->userinfo) ||
565 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
569 /* If we are normal server, and we've not resolved this client from
570 router and it is global client, we'll check whether it is on some
571 channel. If not then we cannot be sure about its validity, and
572 we'll resolve it from router. */
573 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
574 entry->connection || silc_hash_table_count(entry->channels))
578 /* We need to resolve this entry since it is not complete */
580 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
581 /* The entry is being resolved (and we are not the resolver) so attach
582 to the command reply and we're done with this one. */
583 silc_server_command_pending(server, SILC_COMMAND_NONE,
584 entry->resolve_cmd_ident,
585 silc_server_command_whois,
586 silc_server_command_dup(cmd));
589 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
590 /* We've resolved this and it still is not ready. We'll return
591 and are that this will be handled again after it is resolved. */
592 for (i = 0; i < resolve_count; i++) {
593 for (k = 0; k < r->res_argc; k++)
594 silc_free(r->res_argv[k]);
595 silc_free(r->res_argv);
596 silc_free(r->res_argv_lens);
597 silc_free(r->res_argv_types);
602 /* We'll resolve this client */
606 for (k = 0; k < resolve_count; k++) {
607 if (resolve[k].router == entry->router) {
614 resolve = silc_realloc(resolve, sizeof(*resolve) *
615 (resolve_count + 1));
616 r = &resolve[resolve_count];
617 memset(r, 0, sizeof(*r));
618 r->router = entry->router;
619 r->ident = ++server->cmd_ident;
623 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
625 r->res_argv_lens = silc_realloc(r->res_argv_lens,
626 sizeof(*r->res_argv_lens) *
628 r->res_argv_types = silc_realloc(r->res_argv_types,
629 sizeof(*r->res_argv_types) *
631 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
632 r->res_argv[r->res_argc] = silc_calloc(idp->len,
633 sizeof(**r->res_argv));
634 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
635 r->res_argv_lens[r->res_argc] = idp->len;
636 r->res_argv_types[r->res_argc] = r->res_argc + 3;
638 silc_buffer_free(idp);
640 entry->resolve_cmd_ident = r->ident;
641 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
642 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
647 /* Do the resolving */
648 for (i = 0; i < resolve_count; i++) {
653 /* Send WHOIS request. We send WHOIS since we're doing the requesting
654 now anyway so make it a good one. */
655 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
656 r->res_argc, r->res_argv,
660 silc_server_packet_send(server, r->router->connection,
661 SILC_PACKET_COMMAND, cmd->packet->flags,
662 res_cmd->data, res_cmd->len, FALSE);
664 /* Reprocess this packet after received reply */
665 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
667 silc_server_command_whois,
668 silc_server_command_dup(cmd));
671 silc_buffer_free(res_cmd);
672 for (k = 0; k < r->res_argc; k++)
673 silc_free(r->res_argv[k]);
674 silc_free(r->res_argv);
675 silc_free(r->res_argv_lens);
676 silc_free(r->res_argv_types);
685 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
686 SilcClientEntry *clients,
687 uint32 clients_count,
689 const char *nickname,
690 SilcClientID **client_ids)
692 SilcServer server = cmd->server;
694 int i, k, len, valid_count;
695 SilcBuffer packet, idp, channels;
696 SilcClientEntry entry;
697 SilcCommandStatus status;
698 uint16 ident = silc_command_get_ident(cmd->payload);
699 char nh[256], uh[256];
700 unsigned char idle[4], mode[4];
701 unsigned char *fingerprint;
702 SilcSocketConnection hsock;
704 /* Process only valid clients and ignore those that are not registered. */
706 for (i = 0; i < clients_count; i++) {
707 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
714 /* No valid clients found, send error reply */
716 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
717 SILC_STATUS_ERR_NO_SUCH_NICK,
718 3, nickname, strlen(nickname));
719 } else if (client_ids && client_ids[0]) {
720 SilcBuffer idp = silc_id_payload_encode(client_ids[0], SILC_ID_CLIENT);
721 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
722 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
723 2, idp->data, idp->len);
724 silc_buffer_free(idp);
729 /* Start processing found clients. */
731 status = SILC_STATUS_LIST_START;
733 status = SILC_STATUS_OK;
735 for (i = 0, k = 0; i < clients_count; i++) {
741 status = SILC_STATUS_LIST_ITEM;
742 if (valid_count > 1 && k == valid_count - 1)
743 status = SILC_STATUS_LIST_END;
744 if (count && k - 1 == count)
745 status = SILC_STATUS_LIST_END;
747 /* Send WHOIS reply */
748 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
749 tmp = silc_argument_get_first_arg(cmd->args, NULL);
751 memset(uh, 0, sizeof(uh));
752 memset(nh, 0, sizeof(nh));
753 memset(idle, 0, sizeof(idle));
755 strncat(nh, entry->nickname, strlen(entry->nickname));
756 if (!strchr(entry->nickname, '@')) {
758 if (entry->servername) {
759 strncat(nh, entry->servername, strlen(entry->servername));
761 len = entry->router ? strlen(entry->router->server_name) :
762 strlen(server->server_name);
763 strncat(nh, entry->router ? entry->router->server_name :
764 server->server_name, len);
768 strncat(uh, entry->username, strlen(entry->username));
769 if (!strchr(entry->username, '@')) {
771 hsock = (SilcSocketConnection)entry->connection;
772 len = strlen(hsock->hostname);
773 strncat(uh, hsock->hostname, len);
776 channels = silc_server_get_client_channel_list(server, entry);
778 if (entry->data.fingerprint[0] != 0 && entry->data.fingerprint[1] != 0)
779 fingerprint = entry->data.fingerprint;
783 SILC_PUT32_MSB(entry->mode, mode);
785 if (entry->connection) {
786 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
790 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
792 2, idp->data, idp->len,
796 strlen(entry->userinfo),
797 6, channels ? channels->data : NULL,
798 channels ? channels->len : 0,
802 fingerprint ? 20 : 0);
804 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
805 0, packet->data, packet->len, FALSE);
807 silc_buffer_free(packet);
808 silc_buffer_free(idp);
810 silc_buffer_free(channels);
817 silc_server_command_whois_send_router(SilcServerCommandContext cmd)
819 SilcServer server = cmd->server;
823 old_ident = silc_command_get_ident(cmd->payload);
824 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
825 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
827 /* Send WHOIS command to our router */
828 silc_server_packet_send(server, (SilcSocketConnection)
829 server->router->connection,
830 SILC_PACKET_COMMAND, cmd->packet->flags,
831 tmpbuf->data, tmpbuf->len, TRUE);
833 /* Reprocess this packet after received reply from router */
834 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
835 silc_command_get_ident(cmd->payload),
836 silc_server_command_whois,
837 silc_server_command_dup(cmd));
839 silc_command_set_ident(cmd->payload, old_ident);
840 silc_buffer_free(tmpbuf);
844 silc_server_command_whois_process(SilcServerCommandContext cmd)
846 SilcServer server = cmd->server;
847 char *nick = NULL, *server_name = NULL;
849 SilcClientEntry *clients = NULL, entry;
850 SilcClientID **client_id = NULL;
851 uint32 client_id_count = 0, clients_count = 0;
853 bool check_global = FALSE;
855 /* Parse the whois request */
856 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
857 &nick, &server_name, &count,
861 /* Send the WHOIS request to the router only if it included nickname.
862 Since nicknames can be expanded into many clients we need to send it
863 to router. If the WHOIS included only client ID's we will check them
864 first locally since we just might have them. */
865 if (nick && !client_id_count && cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
866 server->server_type == SILC_SERVER && !cmd->pending &&
867 !server->standalone) {
868 silc_server_command_whois_send_router(cmd);
873 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
875 else if (server->server_type != SILC_SERVER)
878 /* Get all clients matching that ID or nickname from local list */
879 if (client_id_count) {
880 /* Check all Client ID's received in the command packet */
881 for (i = 0; i < client_id_count; i++) {
882 entry = silc_idlist_find_client_by_id(server->local_list,
883 client_id[i], TRUE, NULL);
884 if (!entry && check_global)
885 entry = silc_idlist_find_client_by_id(server->global_list,
886 client_id[i], TRUE, NULL);
888 clients = silc_realloc(clients, sizeof(*clients) *
889 (clients_count + 1));
890 clients[clients_count++] = entry;
892 /* If we are normal server and did not send the request first to router
893 do it now, since we do not have the Client ID information. */
894 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
895 server->server_type == SILC_SERVER && !cmd->pending &&
896 !server->standalone) {
897 silc_server_command_whois_send_router(cmd);
904 /* Find by nickname */
905 if (!silc_idlist_get_clients_by_hash(server->local_list,
906 nick, server->md5hash,
907 &clients, &clients_count))
908 silc_idlist_get_clients_by_nickname(server->local_list,
910 &clients, &clients_count);
912 if (!silc_idlist_get_clients_by_hash(server->global_list,
913 nick, server->md5hash,
914 &clients, &clients_count))
915 silc_idlist_get_clients_by_nickname(server->global_list,
917 &clients, &clients_count);
922 /* If we are normal server and did not send the request first to router
923 do it now, since we do not have the information. */
924 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
925 server->server_type == SILC_SERVER && !cmd->pending &&
926 !server->standalone) {
927 silc_server_command_whois_send_router(cmd);
932 /* Such client(s) really does not exist in the SILC network. */
933 if (!client_id_count) {
934 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
935 SILC_STATUS_ERR_NO_SUCH_NICK,
936 3, nick, strlen(nick));
938 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
939 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
940 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
941 2, idp->data, idp->len);
942 silc_buffer_free(idp);
947 /* Router always finds the client entry if it exists in the SILC network.
948 However, it might be incomplete entry and does not include all the
949 mandatory fields that WHOIS command reply requires. Check for these and
950 make query from the server who owns the client if some fields are
952 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
957 /* Send the command reply */
958 silc_server_command_whois_send_reply(cmd, clients, clients_count,
959 count, nick, client_id);
962 if (client_id_count) {
963 for (i = 0; i < client_id_count; i++)
964 silc_free(client_id[i]);
965 silc_free(client_id);
969 silc_free(server_name);
974 /* Server side of command WHOIS. Processes user's query and sends found
975 results as command replies back to the client. */
977 SILC_SERVER_CMD_FUNC(whois)
979 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
982 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 3328);
984 ret = silc_server_command_whois_process(cmd);
985 silc_server_command_free(cmd);
988 /******************************************************************************
992 ******************************************************************************/
995 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
1003 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1005 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
1006 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1010 /* Get the nickname@server string and parse it. */
1011 silc_parse_userfqdn(tmp, nickname, server_name);
1013 /* Get the max count of reply messages allowed */
1014 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1024 silc_server_command_whowas_check(SilcServerCommandContext cmd,
1025 SilcClientEntry *clients,
1026 uint32 clients_count)
1028 SilcServer server = cmd->server;
1030 SilcClientEntry entry;
1032 for (i = 0; i < clients_count; i++) {
1035 if (!entry->nickname || !entry->username) {
1042 old_ident = silc_command_get_ident(cmd->payload);
1043 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1044 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1046 /* Send WHOWAS command */
1047 silc_server_packet_send(server, entry->router->connection,
1048 SILC_PACKET_COMMAND, cmd->packet->flags,
1049 tmpbuf->data, tmpbuf->len, TRUE);
1051 /* Reprocess this packet after received reply */
1052 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1053 silc_command_get_ident(cmd->payload),
1054 silc_server_command_whowas,
1055 silc_server_command_dup(cmd));
1056 cmd->pending = TRUE;
1058 silc_command_set_ident(cmd->payload, old_ident);
1060 silc_buffer_free(tmpbuf);
1069 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1070 SilcClientEntry *clients,
1071 uint32 clients_count)
1073 SilcServer server = cmd->server;
1075 int i, count = 0, len;
1076 SilcBuffer packet, idp;
1077 SilcClientEntry entry = NULL;
1078 SilcCommandStatus status;
1079 uint16 ident = silc_command_get_ident(cmd->payload);
1081 char nh[256], uh[256];
1083 status = SILC_STATUS_OK;
1084 if (clients_count > 1)
1085 status = SILC_STATUS_LIST_START;
1087 for (i = 0; i < clients_count; i++) {
1090 /* We will take only clients that are not valid anymore. They are the
1091 ones that are not registered anymore but still have a ID. They
1092 have disconnected us, and thus valid for WHOWAS. */
1093 if (entry->data.status & SILC_IDLIST_STATUS_REGISTERED || !entry->id)
1096 if (count && i - 1 == count)
1101 if (clients_count > 2)
1102 status = SILC_STATUS_LIST_ITEM;
1103 if (clients_count > 1 && i == clients_count - 1)
1104 status = SILC_STATUS_LIST_END;
1106 /* Send WHOWAS reply */
1107 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1108 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1109 memset(uh, 0, sizeof(uh));
1110 memset(nh, 0, sizeof(nh));
1112 strncat(nh, entry->nickname, strlen(entry->nickname));
1113 if (!strchr(entry->nickname, '@')) {
1114 strncat(nh, "@", 1);
1115 if (entry->servername) {
1116 strncat(nh, entry->servername, strlen(entry->servername));
1118 len = entry->router ? strlen(entry->router->server_name) :
1119 strlen(server->server_name);
1120 strncat(nh, entry->router ? entry->router->server_name :
1121 server->server_name, len);
1125 strncat(uh, entry->username, strlen(entry->username));
1126 if (!strchr(entry->username, '@')) {
1127 strncat(uh, "@", 1);
1128 strcat(uh, "*private*");
1132 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1134 2, idp->data, idp->len,
1139 strlen(entry->userinfo) : 0);
1140 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1141 0, packet->data, packet->len, FALSE);
1143 silc_buffer_free(packet);
1144 silc_buffer_free(idp);
1147 if (found == FALSE && entry)
1148 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1149 SILC_STATUS_ERR_NO_SUCH_NICK,
1151 strlen(entry->nickname));
1155 silc_server_command_whowas_process(SilcServerCommandContext cmd)
1157 SilcServer server = cmd->server;
1158 char *nick = NULL, *server_name = NULL;
1160 SilcClientEntry *clients = NULL;
1161 uint32 clients_count = 0;
1163 bool check_global = FALSE;
1165 /* Protocol dictates that we must always send the received WHOWAS request
1166 to our router if we are normal server, so let's do it now unless we
1167 are standalone. We will not send any replies to the client until we
1168 have received reply from the router. */
1169 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1170 server->server_type == SILC_SERVER && !cmd->pending &&
1171 !server->standalone) {
1175 old_ident = silc_command_get_ident(cmd->payload);
1176 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1177 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1179 /* Send WHOWAS command to our router */
1180 silc_server_packet_send(server, (SilcSocketConnection)
1181 server->router->connection,
1182 SILC_PACKET_COMMAND, cmd->packet->flags,
1183 tmpbuf->data, tmpbuf->len, TRUE);
1185 /* Reprocess this packet after received reply from router */
1186 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1187 silc_command_get_ident(cmd->payload),
1188 silc_server_command_whowas,
1189 silc_server_command_dup(cmd));
1190 cmd->pending = TRUE;
1192 silc_command_set_ident(cmd->payload, old_ident);
1194 silc_buffer_free(tmpbuf);
1199 /* We are ready to process the command request. Let's search for the
1200 requested client and send reply to the requesting client. */
1202 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1203 check_global = TRUE;
1204 else if (server->server_type != SILC_SERVER)
1205 check_global = TRUE;
1207 /* Parse the whowas request */
1208 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1211 /* Get all clients matching that nickname from local list */
1212 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1214 &clients, &clients_count))
1215 silc_idlist_get_clients_by_hash(server->local_list,
1216 nick, server->md5hash,
1217 &clients, &clients_count);
1219 /* Check global list as well */
1221 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1223 &clients, &clients_count))
1224 silc_idlist_get_clients_by_hash(server->global_list,
1225 nick, server->md5hash,
1226 &clients, &clients_count);
1230 /* Such a client really does not exist in the SILC network. */
1231 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1232 SILC_STATUS_ERR_NO_SUCH_NICK,
1233 3, nick, strlen(nick));
1237 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1242 /* Send the command reply to the client */
1243 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1248 silc_free(server_name);
1252 /* Server side of command WHOWAS. */
1254 SILC_SERVER_CMD_FUNC(whowas)
1256 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1259 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1261 ret = silc_server_command_whowas_process(cmd);
1262 silc_server_command_free(cmd);
1265 /******************************************************************************
1269 ******************************************************************************/
1272 silc_server_command_identify_send_router(SilcServerCommandContext cmd)
1274 SilcServer server = cmd->server;
1278 old_ident = silc_command_get_ident(cmd->payload);
1279 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1280 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1282 /* Send IDENTIFY command to our router */
1283 silc_server_packet_send(server, (SilcSocketConnection)
1284 server->router->connection,
1285 SILC_PACKET_COMMAND, cmd->packet->flags,
1286 tmpbuf->data, tmpbuf->len, TRUE);
1288 /* Reprocess this packet after received reply from router */
1289 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1290 silc_command_get_ident(cmd->payload),
1291 silc_server_command_identify,
1292 silc_server_command_dup(cmd));
1293 cmd->pending = TRUE;
1294 silc_command_set_ident(cmd->payload, old_ident);
1295 silc_buffer_free(tmpbuf);
1299 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1300 SilcClientEntry **clients,
1301 uint32 *clients_count,
1302 SilcServerEntry **servers,
1303 uint32 *servers_count,
1304 SilcChannelEntry **channels,
1305 uint32 *channels_count,
1308 SilcServer server = cmd->server;
1311 uint32 argc = silc_argument_get_arg_num(cmd->args);
1313 bool check_global = FALSE;
1318 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1319 check_global = TRUE;
1320 else if (server->server_type != SILC_SERVER)
1321 check_global = TRUE;
1323 /* If ID Payload is in the command it must be used instead of names */
1324 tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1326 /* No ID, get the names. */
1328 /* If we are normal server and have not resolved information from
1329 router yet, do so now. */
1330 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1331 server->server_type == SILC_SERVER && !cmd->pending &&
1332 !server->standalone) {
1333 silc_server_command_identify_send_router(cmd);
1337 /* Try to get nickname@server. */
1338 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1341 char *nick_server = NULL;
1343 silc_parse_userfqdn(tmp, &nick, &nick_server);
1345 if (!silc_idlist_get_clients_by_hash(server->local_list,
1346 nick, server->md5hash,
1347 clients, clients_count))
1348 silc_idlist_get_clients_by_nickname(server->local_list,
1350 clients, clients_count);
1352 if (!silc_idlist_get_clients_by_hash(server->global_list,
1353 nick, server->md5hash,
1354 clients, clients_count))
1355 silc_idlist_get_clients_by_nickname(server->global_list,
1357 clients, clients_count);
1361 silc_free(nick_server);
1364 /* the nickname does not exist, send error reply */
1365 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1366 SILC_STATUS_ERR_NO_SUCH_NICK,
1367 3, tmp, strlen(tmp));
1372 /* Try to get server name */
1373 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1375 entry = silc_idlist_find_server_by_name(server->local_list,
1377 if (!entry && check_global)
1378 entry = silc_idlist_find_server_by_name(server->global_list,
1381 *servers = silc_realloc(*servers, sizeof(**servers) *
1382 (*servers_count + 1));
1383 (*servers)[(*servers_count)++] = entry;
1387 /* the server does not exist, send error reply */
1388 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1389 SILC_STATUS_ERR_NO_SUCH_SERVER,
1390 3, tmp, strlen(tmp));
1395 /* Try to get channel name */
1396 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1398 entry = silc_idlist_find_channel_by_name(server->local_list,
1400 if (!entry && check_global)
1401 entry = silc_idlist_find_channel_by_name(server->global_list,
1404 *channels = silc_realloc(*channels, sizeof(**channels) *
1405 (*channels_count + 1));
1406 (*channels)[(*channels_count)++] = entry;
1410 /* The channel does not exist, send error reply */
1411 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1412 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1413 3, tmp, strlen(tmp));
1418 if (!(*clients) && !(*servers) && !(*channels)) {
1419 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1420 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1424 /* Command includes ID, we must use that. Also check whether the command
1425 has more than one ID set - take them all. */
1427 /* Take all ID's from the command packet */
1428 for (i = 0; i < argc; i++) {
1431 tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
1435 idp = silc_id_payload_parse(tmp, len);
1437 silc_free(*clients);
1438 silc_free(*servers);
1439 silc_free(*channels);
1440 silc_server_command_send_status_reply(
1441 cmd, SILC_COMMAND_IDENTIFY,
1442 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1446 id = silc_id_payload_get_id(idp);
1448 switch (silc_id_payload_get_type(idp)) {
1450 case SILC_ID_CLIENT:
1451 entry = (void *)silc_idlist_find_client_by_id(server->local_list,
1453 if (!entry && check_global)
1454 entry = (void *)silc_idlist_find_client_by_id(server->global_list,
1457 *clients = silc_realloc(*clients, sizeof(**clients) *
1458 (*clients_count + 1));
1459 (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
1461 /* If we are normal server and have not resolved information from
1462 router yet, do so now. */
1463 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1464 server->server_type == SILC_SERVER && !cmd->pending &&
1465 !server->standalone) {
1466 silc_server_command_identify_send_router(cmd);
1467 silc_free(*clients);
1468 silc_free(*servers);
1469 silc_free(*channels);
1472 silc_server_command_send_status_data(
1473 cmd, SILC_COMMAND_IDENTIFY,
1474 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1482 case SILC_ID_SERVER:
1483 entry = (void *)silc_idlist_find_server_by_id(server->local_list,
1485 if (!entry && check_global)
1486 entry = (void *)silc_idlist_find_server_by_id(server->global_list,
1489 *servers = silc_realloc(*servers, sizeof(**servers) *
1490 (*servers_count + 1));
1491 (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
1493 /* If we are normal server and have not resolved information from
1494 router yet, do so now. */
1495 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1496 server->server_type == SILC_SERVER && !cmd->pending &&
1497 !server->standalone) {
1498 silc_server_command_identify_send_router(cmd);
1499 silc_free(*clients);
1500 silc_free(*servers);
1501 silc_free(*channels);
1504 silc_server_command_send_status_data(
1505 cmd, SILC_COMMAND_IDENTIFY,
1506 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
1513 case SILC_ID_CHANNEL:
1514 entry = (void *)silc_idlist_find_channel_by_id(server->local_list,
1516 if (!entry && check_global)
1517 entry = (void *)silc_idlist_find_channel_by_id(server->global_list,
1520 *channels = silc_realloc(*channels, sizeof(**channels) *
1521 (*channels_count + 1));
1522 (*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
1524 /* If we are normal server and have not resolved information from
1525 router yet, do so now. */
1526 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1527 server->server_type == SILC_SERVER && !cmd->pending &&
1528 !server->standalone) {
1529 silc_server_command_identify_send_router(cmd);
1530 silc_free(*clients);
1531 silc_free(*servers);
1532 silc_free(*channels);
1535 silc_server_command_send_status_data(
1536 cmd, SILC_COMMAND_IDENTIFY,
1537 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
1550 silc_free(*clients);
1551 silc_free(*servers);
1552 silc_free(*channels);
1556 /* Get the max count of reply messages allowed */
1557 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1566 /* Checks that all mandatory fields in client entry are present. If not
1567 then send WHOIS request to the server who owns the client. We use
1568 WHOIS because we want to get as much information as possible at once. */
1571 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1572 SilcClientEntry *clients,
1573 uint32 clients_count)
1575 SilcServer server = cmd->server;
1576 SilcClientEntry entry;
1577 SilcServerResolveContext resolve = NULL, r = NULL;
1578 uint32 resolve_count = 0;
1582 for (i = 0; i < clients_count; i++) {
1587 if (entry->nickname ||
1588 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1592 /* If we are normal server, and we've not resolved this client from
1593 router and it is global client, we'll check whether it is on some
1594 channel. If not then we cannot be sure about its validity, and
1595 we'll resolve it from router. */
1596 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
1597 entry->connection || silc_hash_table_count(entry->channels))
1601 /* We need to resolve this entry since it is not complete */
1603 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1604 /* The entry is being resolved (and we are not the resolver) so attach
1605 to the command reply and we're done with this one. */
1606 silc_server_command_pending(server, SILC_COMMAND_NONE,
1607 entry->resolve_cmd_ident,
1608 silc_server_command_identify,
1609 silc_server_command_dup(cmd));
1612 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1613 /* We've resolved this and it still is not ready. We'll return
1614 and are that this will be handled again after it is resolved. */
1615 for (i = 0; i < resolve_count; i++) {
1616 for (k = 0; k < r->res_argc; k++)
1617 silc_free(r->res_argv[k]);
1618 silc_free(r->res_argv);
1619 silc_free(r->res_argv_lens);
1620 silc_free(r->res_argv_types);
1625 /* We'll resolve this client */
1629 for (k = 0; k < resolve_count; k++) {
1630 if (resolve[k].router == entry->router) {
1637 resolve = silc_realloc(resolve, sizeof(*resolve) *
1638 (resolve_count + 1));
1639 r = &resolve[resolve_count];
1640 memset(r, 0, sizeof(*r));
1641 r->router = entry->router;
1642 r->ident = ++server->cmd_ident;
1646 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1648 r->res_argv_lens = silc_realloc(r->res_argv_lens,
1649 sizeof(*r->res_argv_lens) *
1651 r->res_argv_types = silc_realloc(r->res_argv_types,
1652 sizeof(*r->res_argv_types) *
1654 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1655 r->res_argv[r->res_argc] = silc_calloc(idp->len,
1656 sizeof(**r->res_argv));
1657 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1658 r->res_argv_lens[r->res_argc] = idp->len;
1659 r->res_argv_types[r->res_argc] = r->res_argc + 3;
1661 silc_buffer_free(idp);
1663 entry->resolve_cmd_ident = r->ident;
1664 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1665 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1670 /* Do the resolving */
1671 for (i = 0; i < resolve_count; i++) {
1676 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1677 now anyway so make it a good one. */
1678 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1679 r->res_argc, r->res_argv,
1683 silc_server_packet_send(server, r->router->connection,
1684 SILC_PACKET_COMMAND, cmd->packet->flags,
1685 res_cmd->data, res_cmd->len, FALSE);
1687 /* Reprocess this packet after received reply */
1688 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1690 silc_server_command_identify,
1691 silc_server_command_dup(cmd));
1692 cmd->pending = TRUE;
1694 silc_buffer_free(res_cmd);
1695 for (k = 0; k < r->res_argc; k++)
1696 silc_free(r->res_argv[k]);
1697 silc_free(r->res_argv);
1698 silc_free(r->res_argv_lens);
1699 silc_free(r->res_argv_types);
1708 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1709 SilcClientEntry *clients,
1710 uint32 clients_count,
1711 SilcServerEntry *servers,
1712 uint32 servers_count,
1713 SilcChannelEntry *channels,
1714 uint32 channels_count,
1717 SilcServer server = cmd->server;
1718 int i, k, len, valid_count;
1719 SilcBuffer packet, idp;
1720 SilcCommandStatus status;
1721 uint16 ident = silc_command_get_ident(cmd->payload);
1722 char nh[256], uh[256];
1723 SilcSocketConnection hsock;
1725 status = SILC_STATUS_OK;
1728 SilcClientEntry entry;
1730 /* Process only valid entries. */
1732 for (i = 0; i < clients_count; i++) {
1733 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1740 /* No valid entries found at all, just send error */
1743 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1745 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1746 SILC_STATUS_ERR_NO_SUCH_NICK,
1747 3, tmp, strlen(tmp));
1749 tmp = silc_argument_get_arg_type(cmd->args, 5, (uint32 *)&len);
1750 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1751 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1757 /* Process all valid client entries and send command replies */
1759 if (valid_count > 1)
1760 status = SILC_STATUS_LIST_START;
1762 for (i = 0, k = 0; i < clients_count; i++) {
1768 status = SILC_STATUS_LIST_ITEM;
1769 if (valid_count > 1 && k == valid_count - 1
1770 && !servers_count && !channels_count)
1771 status = SILC_STATUS_LIST_END;
1772 if (count && k - 1 == count)
1773 status = SILC_STATUS_LIST_END;
1774 if (count && k - 1 > count)
1777 /* Send IDENTIFY reply */
1779 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1780 memset(uh, 0, sizeof(uh));
1781 memset(nh, 0, sizeof(nh));
1782 strncat(nh, entry->nickname, strlen(entry->nickname));
1783 if (!strchr(entry->nickname, '@')) {
1784 strncat(nh, "@", 1);
1785 if (entry->servername) {
1786 strncat(nh, entry->servername, strlen(entry->servername));
1788 len = entry->router ? strlen(entry->router->server_name) :
1789 strlen(server->server_name);
1790 strncat(nh, entry->router ? entry->router->server_name :
1791 server->server_name, len);
1795 if (!entry->username) {
1796 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1798 2, idp->data, idp->len,
1801 strncat(uh, entry->username, strlen(entry->username));
1802 if (!strchr(entry->username, '@')) {
1803 strncat(uh, "@", 1);
1804 hsock = (SilcSocketConnection)entry->connection;
1805 len = strlen(hsock->hostname);
1806 strncat(uh, hsock->hostname, len);
1809 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1811 2, idp->data, idp->len,
1816 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1817 0, packet->data, packet->len, FALSE);
1819 silc_buffer_free(packet);
1820 silc_buffer_free(idp);
1827 SilcServerEntry entry;
1829 if (status == SILC_STATUS_OK && servers_count > 1)
1830 status = SILC_STATUS_LIST_START;
1832 for (i = 0, k = 0; i < servers_count; i++) {
1836 status = SILC_STATUS_LIST_ITEM;
1837 if (servers_count > 1 && k == servers_count - 1 && !channels_count)
1838 status = SILC_STATUS_LIST_END;
1839 if (count && k - 1 == count)
1840 status = SILC_STATUS_LIST_END;
1841 if (count && k - 1 > count)
1844 /* Send IDENTIFY reply */
1845 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1847 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1849 2, idp->data, idp->len,
1850 3, entry->server_name,
1851 entry->server_name ?
1852 strlen(entry->server_name) : 0);
1853 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1854 0, packet->data, packet->len, FALSE);
1856 silc_buffer_free(packet);
1857 silc_buffer_free(idp);
1864 SilcChannelEntry entry;
1866 if (status == SILC_STATUS_OK && channels_count > 1)
1867 status = SILC_STATUS_LIST_START;
1869 for (i = 0, k = 0; i < channels_count; i++) {
1870 entry = channels[i];
1873 status = SILC_STATUS_LIST_ITEM;
1874 if (channels_count > 1 && k == channels_count - 1)
1875 status = SILC_STATUS_LIST_END;
1876 if (count && k - 1 == count)
1877 status = SILC_STATUS_LIST_END;
1878 if (count && k - 1 > count)
1881 /* Send IDENTIFY reply */
1882 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1884 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1886 2, idp->data, idp->len,
1887 3, entry->channel_name,
1888 entry->channel_name ?
1889 strlen(entry->channel_name): 0);
1890 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1891 0, packet->data, packet->len, FALSE);
1893 silc_buffer_free(packet);
1894 silc_buffer_free(idp);
1902 silc_server_command_identify_process(SilcServerCommandContext cmd)
1906 SilcClientEntry *clients = NULL;
1907 SilcServerEntry *servers = NULL;
1908 SilcChannelEntry *channels = NULL;
1909 uint32 clients_count = 0, servers_count = 0, channels_count = 0;
1911 /* Parse the IDENTIFY request */
1912 ret = silc_server_command_identify_parse(cmd,
1913 &clients, &clients_count,
1914 &servers, &servers_count,
1915 &channels, &channels_count,
1921 /* Check that all mandatory fields are present and request those data
1922 from the server who owns the client if necessary. */
1923 if (clients && !silc_server_command_identify_check_client(cmd, clients,
1929 /* Send the command reply to the client */
1930 silc_server_command_identify_send_reply(cmd,
1931 clients, clients_count,
1932 servers, servers_count,
1933 channels, channels_count,
1939 silc_free(channels);
1943 SILC_SERVER_CMD_FUNC(identify)
1945 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1948 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1950 ret = silc_server_command_identify_process(cmd);
1951 silc_server_command_free(cmd);
1954 /* Checks string for bad characters and returns TRUE if they are found. */
1956 static int silc_server_command_bad_chars(char *nick)
1960 for (i = 0; i < strlen(nick); i++) {
1961 if (!isascii(nick[i]))
1963 if (nick[i] <= 32) return TRUE;
1964 if (nick[i] == ' ') return TRUE;
1965 if (nick[i] == '*') return TRUE;
1966 if (nick[i] == '?') return TRUE;
1967 if (nick[i] == ',') return TRUE;
1973 /* Server side of command NICK. Sets nickname for user. Setting
1974 nickname causes generation of a new client ID for the client. The
1975 new client ID is sent to the client after changing the nickname. */
1977 SILC_SERVER_CMD_FUNC(nick)
1979 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1980 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1981 SilcServer server = cmd->server;
1982 SilcBuffer packet, nidp, oidp = NULL;
1983 SilcClientID *new_id;
1985 uint16 ident = silc_command_get_ident(cmd->payload);
1988 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1991 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
1993 /* Check nickname */
1994 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1995 if (silc_server_command_bad_chars(nick) == TRUE) {
1996 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1997 SILC_STATUS_ERR_BAD_NICKNAME);
2001 if (strlen(nick) > 128)
2004 /* Check for same nickname */
2005 if (!strcmp(client->nickname, nick)) {
2006 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2010 /* Create new Client ID */
2011 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
2013 cmd->server->md5hash, nick,
2016 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2019 /* Send notify about nickname change to our router. We send the new
2020 ID and ask to replace it with the old one. If we are router the
2021 packet is broadcasted. Send NICK_CHANGE notify. */
2022 if (!server->standalone)
2023 silc_server_send_notify_nick_change(server, server->router->connection,
2024 server->server_type == SILC_SERVER ?
2025 FALSE : TRUE, client->id,
2028 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2030 /* Remove old cache entry */
2031 silc_idcache_del_by_context(server->local_list->clients, client);
2034 silc_free(client->id);
2036 /* Save the nickname as this client is our local client */
2037 silc_free(client->nickname);
2039 client->nickname = strdup(nick);
2040 client->id = new_id;
2042 /* Update client cache */
2043 silc_idcache_add(server->local_list->clients, client->nickname,
2044 client->id, (void *)client, 0, NULL);
2046 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2048 /* Send NICK_CHANGE notify to the client's channels */
2049 silc_server_send_notify_on_channels(server, NULL, client,
2050 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
2051 oidp->data, oidp->len,
2052 nidp->data, nidp->len);
2055 /* Send the new Client ID as reply command back to client */
2056 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
2057 SILC_STATUS_OK, ident, 1,
2058 2, nidp->data, nidp->len);
2059 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2060 0, packet->data, packet->len, FALSE);
2062 silc_buffer_free(packet);
2063 silc_buffer_free(nidp);
2065 silc_buffer_free(oidp);
2068 silc_server_command_free(cmd);
2071 /* Sends the LIST command reply */
2074 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2075 SilcChannelEntry *lch,
2077 SilcChannelEntry *gch,
2081 SilcBuffer packet, idp;
2082 SilcChannelEntry entry;
2083 SilcCommandStatus status;
2084 uint16 ident = silc_command_get_ident(cmd->payload);
2086 unsigned char usercount[4];
2088 int valid_lcount = 0, valid_rcount = 0;
2090 for (i = 0; i < lch_count; i++) {
2091 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2096 for (i = 0; i < gch_count; i++) {
2097 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2103 status = SILC_STATUS_OK;
2104 if ((lch_count + gch_count) > 1)
2105 status = SILC_STATUS_LIST_START;
2108 for (i = 0, k = 0; i < lch_count; i++) {
2114 status = SILC_STATUS_LIST_ITEM;
2115 if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
2116 status = SILC_STATUS_LIST_END;
2118 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2120 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2121 topic = "*private*";
2122 memset(usercount, 0, sizeof(usercount));
2124 topic = entry->topic;
2125 users = silc_hash_table_count(entry->user_list);
2126 SILC_PUT32_MSB(users, usercount);
2129 /* Send the reply */
2131 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2133 2, idp->data, idp->len,
2134 3, entry->channel_name,
2135 strlen(entry->channel_name),
2136 4, topic, topic ? strlen(topic) : 0,
2138 silc_server_packet_send(cmd->server, cmd->sock,
2139 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2140 packet->len, FALSE);
2141 silc_buffer_free(packet);
2142 silc_buffer_free(idp);
2147 for (i = 0, k = 0; i < gch_count; i++) {
2153 status = SILC_STATUS_LIST_ITEM;
2154 if (valid_rcount > 1 && k == valid_rcount - 1)
2155 status = SILC_STATUS_LIST_END;
2157 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2159 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2160 topic = "*private*";
2161 memset(usercount, 0, sizeof(usercount));
2163 topic = entry->topic;
2164 users = silc_hash_table_count(entry->user_list);
2165 SILC_PUT32_MSB(users, usercount);
2168 /* Send the reply */
2170 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2172 2, idp->data, idp->len,
2173 3, entry->channel_name,
2174 strlen(entry->channel_name),
2175 4, topic, topic ? strlen(topic) : 0,
2177 silc_server_packet_send(cmd->server, cmd->sock,
2178 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2179 packet->len, FALSE);
2180 silc_buffer_free(packet);
2181 silc_buffer_free(idp);
2186 /* Server side of LIST command. This lists the channel of the requested
2187 server. Secret channels are not listed. */
2189 SILC_SERVER_CMD_FUNC(list)
2191 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2192 SilcServer server = cmd->server;
2193 SilcChannelID *channel_id = NULL;
2196 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2197 uint32 lch_count = 0, gch_count = 0;
2199 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2201 /* If we are normal server, send the command to router, since we
2202 want to know all channels in the network. */
2203 if (!cmd->pending && server->server_type == SILC_SERVER &&
2204 !server->standalone) {
2208 old_ident = silc_command_get_ident(cmd->payload);
2209 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2210 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2211 silc_server_packet_send(server, server->router->connection,
2212 SILC_PACKET_COMMAND, cmd->packet->flags,
2213 tmpbuf->data, tmpbuf->len, TRUE);
2215 /* Reprocess this packet after received reply from router */
2216 silc_server_command_pending(server, SILC_COMMAND_LIST,
2217 silc_command_get_ident(cmd->payload),
2218 silc_server_command_list,
2219 silc_server_command_dup(cmd));
2220 cmd->pending = TRUE;
2221 silc_command_set_ident(cmd->payload, old_ident);
2222 silc_buffer_free(tmpbuf);
2226 /* Get Channel ID */
2227 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2229 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2231 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2232 SILC_STATUS_ERR_NO_CHANNEL_ID);
2237 /* Get the channels from local list */
2238 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2241 /* Get the channels from global list */
2242 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2245 /* Send the reply */
2246 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2247 gchannels, gch_count);
2249 silc_free(lchannels);
2250 silc_free(gchannels);
2253 silc_server_command_free(cmd);
2256 /* Server side of TOPIC command. Sets topic for channel and/or returns
2257 current topic to client. */
2259 SILC_SERVER_CMD_FUNC(topic)
2261 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2262 SilcServer server = cmd->server;
2263 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2264 SilcChannelID *channel_id;
2265 SilcChannelEntry channel;
2266 SilcChannelClientEntry chl;
2267 SilcBuffer packet, idp;
2269 uint32 argc, tmp_len;
2270 uint16 ident = silc_command_get_ident(cmd->payload);
2272 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2274 argc = silc_argument_get_arg_num(cmd->args);
2276 /* Get Channel ID */
2277 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2279 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2280 SILC_STATUS_ERR_NO_CHANNEL_ID);
2283 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2285 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2286 SILC_STATUS_ERR_NO_CHANNEL_ID);
2290 /* Check whether the channel exists */
2291 channel = silc_idlist_find_channel_by_id(server->local_list,
2294 channel = silc_idlist_find_channel_by_id(server->global_list,
2297 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2298 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2305 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2307 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2308 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2312 if (strlen(tmp) > 256) {
2313 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2314 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2318 /* See whether the client is on channel and has rights to change topic */
2319 if (!silc_hash_table_find(channel->user_list, client, NULL,
2321 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2322 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2326 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2327 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2328 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2329 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2334 /* Set the topic for channel */
2335 silc_free(channel->topic);
2336 channel->topic = strdup(tmp);
2338 /* Send TOPIC_SET notify type to the network */
2339 if (!server->standalone)
2340 silc_server_send_notify_topic_set(server, server->router->connection,
2341 server->server_type == SILC_ROUTER ?
2342 TRUE : FALSE, channel,
2343 client->id, SILC_ID_CLIENT,
2346 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2348 /* Send notify about topic change to all clients on the channel */
2349 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2350 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2351 idp->data, idp->len,
2352 channel->topic, strlen(channel->topic));
2353 silc_buffer_free(idp);
2356 /* Send the topic to client as reply packet */
2357 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2358 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2359 SILC_STATUS_OK, ident, 2,
2360 2, idp->data, idp->len,
2363 strlen(channel->topic) : 0);
2364 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2365 0, packet->data, packet->len, FALSE);
2367 silc_buffer_free(packet);
2368 silc_buffer_free(idp);
2369 silc_free(channel_id);
2372 silc_server_command_free(cmd);
2375 /* Server side of INVITE command. Invites some client to join some channel.
2376 This command is also used to manage the invite list of the channel. */
2378 SILC_SERVER_CMD_FUNC(invite)
2380 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2381 SilcServer server = cmd->server;
2382 SilcSocketConnection sock = cmd->sock, dest_sock;
2383 SilcChannelClientEntry chl;
2384 SilcClientEntry sender, dest;
2385 SilcClientID *dest_id = NULL;
2386 SilcChannelEntry channel;
2387 SilcChannelID *channel_id = NULL;
2388 SilcIDListData idata;
2389 SilcBuffer idp, idp2, packet;
2390 unsigned char *tmp, *add, *del;
2392 uint16 ident = silc_command_get_ident(cmd->payload);
2394 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2396 /* Get Channel ID */
2397 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2399 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2400 SILC_STATUS_ERR_NO_CHANNEL_ID);
2403 channel_id = silc_id_payload_parse_id(tmp, len);
2405 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2406 SILC_STATUS_ERR_NO_CHANNEL_ID);
2410 /* Get the channel entry */
2411 channel = silc_idlist_find_channel_by_id(server->local_list,
2414 channel = silc_idlist_find_channel_by_id(server->global_list,
2417 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2418 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2423 /* Check whether the sender of this command is on the channel. */
2424 sender = (SilcClientEntry)sock->user_data;
2425 if (!silc_server_client_on_channel(sender, channel)) {
2426 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2427 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2431 /* Check whether the channel is invite-only channel. If yes then the
2432 sender of this command must be at least channel operator. */
2433 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2434 silc_hash_table_find(channel->user_list, sender, NULL, (void *)&chl);
2435 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2436 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2437 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2442 /* Get destination client ID */
2443 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2447 dest_id = silc_id_payload_parse_id(tmp, len);
2449 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2450 SILC_STATUS_ERR_NO_CLIENT_ID);
2454 /* Get the client entry */
2455 dest = silc_server_get_client_resolve(server, dest_id);
2457 if (server->server_type != SILC_SERVER) {
2458 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2459 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2463 /* The client info is being resolved. Reprocess this packet after
2464 receiving the reply to the query. */
2465 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2467 silc_server_command_invite,
2468 silc_server_command_dup(cmd));
2469 cmd->pending = TRUE;
2470 silc_free(channel_id);
2475 /* Check whether the requested client is already on the channel. */
2476 if (silc_server_client_on_channel(dest, channel)) {
2477 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2478 SILC_STATUS_ERR_USER_ON_CHANNEL);
2482 /* Get route to the client */
2483 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2485 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2486 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2490 memset(invite, 0, sizeof(invite));
2491 strncat(invite, dest->nickname, strlen(dest->nickname));
2492 strncat(invite, "!", 1);
2493 strncat(invite, dest->username, strlen(dest->username));
2494 if (!strchr(dest->username, '@')) {
2495 strncat(invite, "@", 1);
2496 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2499 len = strlen(invite);
2500 if (!channel->invite_list)
2501 channel->invite_list = silc_calloc(len + 2,
2502 sizeof(*channel->invite_list));
2504 channel->invite_list = silc_realloc(channel->invite_list,
2505 sizeof(*channel->invite_list) *
2507 strlen(channel->invite_list) + 2));
2508 strncat(channel->invite_list, invite, len);
2509 strncat(channel->invite_list, ",", 1);
2511 /* Send notify to the client that is invited to the channel */
2512 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2513 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2514 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2516 SILC_NOTIFY_TYPE_INVITE, 3,
2517 idp->data, idp->len,
2518 channel->channel_name,
2519 strlen(channel->channel_name),
2520 idp2->data, idp2->len);
2521 silc_buffer_free(idp);
2522 silc_buffer_free(idp2);
2525 /* Add the client to the invite list of the channel */
2526 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2528 if (!channel->invite_list)
2529 channel->invite_list = silc_calloc(len + 2,
2530 sizeof(*channel->invite_list));
2532 channel->invite_list = silc_realloc(channel->invite_list,
2533 sizeof(*channel->invite_list) *
2535 strlen(channel->invite_list) + 2));
2536 if (add[len - 1] == ',')
2537 add[len - 1] = '\0';
2539 strncat(channel->invite_list, add, len);
2540 strncat(channel->invite_list, ",", 1);
2543 /* Get the invite to be removed and remove it from the list */
2544 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2545 if (del && channel->invite_list) {
2546 char *start, *end, *n;
2548 if (!strncmp(channel->invite_list, del,
2549 strlen(channel->invite_list) - 1)) {
2550 silc_free(channel->invite_list);
2551 channel->invite_list = NULL;
2553 start = strstr(channel->invite_list, del);
2554 if (start && strlen(start) >= len) {
2556 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2557 strncat(n, channel->invite_list, start - channel->invite_list);
2558 strncat(n, end + 1, ((channel->invite_list +
2559 strlen(channel->invite_list)) - end) - 1);
2560 silc_free(channel->invite_list);
2561 channel->invite_list = n;
2566 /* Send notify to the primary router */
2567 if (!server->standalone)
2568 silc_server_send_notify_invite(server, server->router->connection,
2569 server->server_type == SILC_ROUTER ?
2570 TRUE : FALSE, channel,
2571 sender->id, add, del);
2573 /* Send command reply */
2574 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2578 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2579 SILC_STATUS_OK, ident, 2,
2581 3, channel->invite_list,
2582 channel->invite_list ?
2583 strlen(channel->invite_list) : 0);
2586 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2587 SILC_STATUS_OK, ident, 1,
2589 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2590 packet->data, packet->len, FALSE);
2591 silc_buffer_free(packet);
2595 silc_free(channel_id);
2596 silc_server_command_free(cmd);
2601 SilcSocketConnection sock;
2605 /* Quits connection to client. This gets called if client won't
2606 close the connection even when it has issued QUIT command. */
2608 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2610 QuitInternal q = (QuitInternal)context;
2612 /* Free all client specific data, such as client entry and entires
2613 on channels this client may be on. */
2614 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2616 q->sock->user_data = NULL;
2618 /* Close the connection on our side */
2619 silc_server_close_connection(q->server, q->sock);
2621 silc_free(q->signoff);
2625 /* Quits SILC session. This is the normal way to disconnect client. */
2627 SILC_SERVER_CMD_FUNC(quit)
2629 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2630 SilcServer server = cmd->server;
2631 SilcSocketConnection sock = cmd->sock;
2633 unsigned char *tmp = NULL;
2636 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2638 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2641 /* Get destination ID */
2642 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2646 q = silc_calloc(1, sizeof(*q));
2649 q->signoff = tmp ? strdup(tmp) : NULL;
2651 /* We quit the connection with little timeout */
2652 silc_schedule_task_add(server->schedule, sock->sock,
2653 silc_server_command_quit_cb, (void *)q,
2654 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2657 silc_server_command_free(cmd);
2660 /* Server side of command KILL. This command is used by router operator
2661 to remove an client from the SILC Network temporarily. */
2663 SILC_SERVER_CMD_FUNC(kill)
2665 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2666 SilcServer server = cmd->server;
2667 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2668 SilcClientEntry remote_client;
2669 SilcClientID *client_id;
2670 unsigned char *tmp, *comment;
2671 uint32 tmp_len, tmp_len2;
2673 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2675 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2678 /* KILL command works only on router */
2679 if (server->server_type != SILC_ROUTER) {
2680 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2681 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2685 /* Check whether client has the permissions. */
2686 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2687 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2688 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2692 /* Get the client ID */
2693 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2695 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2696 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2699 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2701 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2702 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2706 /* Get the client entry */
2707 remote_client = silc_idlist_find_client_by_id(server->local_list,
2708 client_id, TRUE, NULL);
2709 if (!remote_client) {
2710 remote_client = silc_idlist_find_client_by_id(server->global_list,
2711 client_id, TRUE, NULL);
2712 if (!remote_client) {
2713 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2714 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2720 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2724 /* Send reply to the sender */
2725 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2728 /* Send the KILL notify packets. First send it to the channel, then
2729 to our primary router and then directly to the client who is being
2730 killed right now. */
2732 /* Send KILLED notify to the channels. It is not sent to the client
2733 as it will be sent differently destined directly to the client and not
2735 silc_server_send_notify_on_channels(server, remote_client,
2736 remote_client, SILC_NOTIFY_TYPE_KILLED,
2739 comment, comment ? tmp_len2 : 0);
2741 /* Send KILLED notify to primary route */
2742 if (!server->standalone)
2743 silc_server_send_notify_killed(server, server->router->connection, TRUE,
2744 remote_client->id, comment);
2746 /* Send KILLED notify to the client directly */
2747 silc_server_send_notify_killed(server, remote_client->connection ?
2748 remote_client->connection :
2749 remote_client->router->connection, FALSE,
2750 remote_client->id, comment);
2752 /* Remove the client from all channels. This generates new keys to the
2753 channels as well. */
2754 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2757 /* Remove the client entry, If it is locally connected then we will also
2758 disconnect the client here */
2759 if (remote_client->connection) {
2760 /* Remove locally conneted client */
2761 SilcSocketConnection sock = remote_client->connection;
2762 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2763 silc_server_close_connection(server, sock);
2765 /* Remove remote client */
2766 if (!silc_idlist_del_client(server->global_list, remote_client))
2767 silc_idlist_del_client(server->local_list, remote_client);
2771 silc_server_command_free(cmd);
2774 /* Server side of command INFO. This sends information about us to
2775 the client. If client requested specific server we will send the
2776 command to that server. */
2778 SILC_SERVER_CMD_FUNC(info)
2780 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2781 SilcServer server = cmd->server;
2782 SilcBuffer packet, idp;
2785 char *dest_server, *server_info = NULL, *server_name;
2786 uint16 ident = silc_command_get_ident(cmd->payload);
2787 SilcServerEntry entry = NULL;
2788 SilcServerID *server_id = NULL;
2790 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2792 /* Get server name */
2793 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2796 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2798 server_id = silc_id_payload_parse_id(tmp, tmp_len);
2800 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2801 SILC_STATUS_ERR_NO_SERVER_ID);
2807 /* Check whether we have this server cached */
2808 entry = silc_idlist_find_server_by_id(server->local_list,
2809 server_id, TRUE, NULL);
2811 entry = silc_idlist_find_server_by_id(server->global_list,
2812 server_id, TRUE, NULL);
2813 if (!entry && server->server_type != SILC_SERVER) {
2814 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2815 SILC_STATUS_ERR_NO_SUCH_SERVER);
2821 /* Some buggy servers has sent request to router about themselves. */
2822 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2825 if ((!dest_server && !server_id && !entry) || (entry &&
2826 entry == server->id_entry) ||
2827 (dest_server && !cmd->pending &&
2828 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2829 /* Send our reply */
2830 char info_string[256];
2832 memset(info_string, 0, sizeof(info_string));
2833 snprintf(info_string, sizeof(info_string),
2834 "location: %s server: %s admin: %s <%s>",
2835 server->config->admin_info->location,
2836 server->config->admin_info->server_type,
2837 server->config->admin_info->admin_name,
2838 server->config->admin_info->admin_email);
2840 server_info = info_string;
2841 entry = server->id_entry;
2843 /* Check whether we have this server cached */
2844 if (!entry && dest_server) {
2845 entry = silc_idlist_find_server_by_name(server->global_list,
2846 dest_server, TRUE, NULL);
2848 entry = silc_idlist_find_server_by_name(server->local_list,
2849 dest_server, TRUE, NULL);
2853 if (!cmd->pending &&
2854 server->server_type != SILC_SERVER && entry && !entry->server_info) {
2855 /* Send to the server */
2859 old_ident = silc_command_get_ident(cmd->payload);
2860 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2861 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2863 silc_server_packet_send(server, entry->connection,
2864 SILC_PACKET_COMMAND, cmd->packet->flags,
2865 tmpbuf->data, tmpbuf->len, TRUE);
2867 /* Reprocess this packet after received reply from router */
2868 silc_server_command_pending(server, SILC_COMMAND_INFO,
2869 silc_command_get_ident(cmd->payload),
2870 silc_server_command_info,
2871 silc_server_command_dup(cmd));
2872 cmd->pending = TRUE;
2873 silc_command_set_ident(cmd->payload, old_ident);
2874 silc_buffer_free(tmpbuf);
2878 if (!entry && !cmd->pending && !server->standalone) {
2879 /* Send to the primary router */
2883 old_ident = silc_command_get_ident(cmd->payload);
2884 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2885 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2887 silc_server_packet_send(server, server->router->connection,
2888 SILC_PACKET_COMMAND, cmd->packet->flags,
2889 tmpbuf->data, tmpbuf->len, TRUE);
2891 /* Reprocess this packet after received reply from router */
2892 silc_server_command_pending(server, SILC_COMMAND_INFO,
2893 silc_command_get_ident(cmd->payload),
2894 silc_server_command_info,
2895 silc_server_command_dup(cmd));
2896 cmd->pending = TRUE;
2897 silc_command_set_ident(cmd->payload, old_ident);
2898 silc_buffer_free(tmpbuf);
2903 silc_free(server_id);
2906 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2907 SILC_STATUS_ERR_NO_SUCH_SERVER);
2911 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2913 server_info = entry->server_info;
2914 server_name = entry->server_name;
2916 /* Send the reply */
2917 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2918 SILC_STATUS_OK, ident, 3,
2919 2, idp->data, idp->len,
2921 strlen(server_name),
2924 strlen(server_info) : 0);
2925 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2926 packet->data, packet->len, FALSE);
2928 silc_buffer_free(packet);
2929 silc_buffer_free(idp);
2932 silc_server_command_free(cmd);
2935 /* Server side of command PING. This just replies to the ping. */
2937 SILC_SERVER_CMD_FUNC(ping)
2939 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2940 SilcServer server = cmd->server;
2945 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
2948 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2950 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2951 SILC_STATUS_ERR_NO_SERVER_ID);
2954 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2958 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2959 /* Send our reply */
2960 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2963 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2964 SILC_STATUS_ERR_NO_SUCH_SERVER);
2971 silc_server_command_free(cmd);
2974 /* Internal routine to join channel. The channel sent to this function
2975 has been either created or resolved from ID lists. This joins the sent
2976 client to the channel. */
2978 static void silc_server_command_join_channel(SilcServer server,
2979 SilcServerCommandContext cmd,
2980 SilcChannelEntry channel,
2981 SilcClientID *client_id,
2985 const unsigned char *auth,
2988 SilcSocketConnection sock = cmd->sock;
2990 uint32 tmp_len, user_count;
2991 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
2992 SilcClientEntry client;
2993 SilcChannelClientEntry chl;
2994 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
2995 uint16 ident = silc_command_get_ident(cmd->payload);
2996 char check[512], check2[512];
2997 bool founder = FALSE;
2999 SILC_LOG_DEBUG(("Start"));
3004 /* Get the client entry */
3005 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3006 client = (SilcClientEntry)sock->user_data;
3008 client = silc_server_get_client_resolve(server, client_id);
3013 /* The client info is being resolved. Reprocess this packet after
3014 receiving the reply to the query. */
3015 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
3017 silc_server_command_join,
3018 silc_server_command_dup(cmd));
3019 cmd->pending = TRUE;
3023 cmd->pending = FALSE;
3027 * Check founder auth payload if provided. If client can gain founder
3028 * privileges it can override various conditions on joining the channel,
3029 * and can have directly the founder mode set on the channel.
3031 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3032 SilcIDListData idata = (SilcIDListData)client;
3034 if (channel->founder_key && idata->public_key &&
3035 silc_pkcs_public_key_compare(channel->founder_key,
3036 idata->public_key)) {
3037 void *auth_data = (channel->founder_method == SILC_AUTH_PASSWORD ?
3038 (void *)channel->founder_passwd :
3039 (void *)channel->founder_key);
3040 uint32 auth_data_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
3041 channel->founder_passwd_len : 0);
3043 /* Check whether the client is to become founder */
3044 if (silc_auth_verify_data(auth, auth_len, channel->founder_method,
3045 auth_data, auth_data_len,
3046 idata->hash, client->id, SILC_ID_CLIENT)) {
3047 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3054 * Check channel modes
3058 memset(check, 0, sizeof(check));
3059 memset(check2, 0, sizeof(check2));
3060 strncat(check, client->nickname, strlen(client->nickname));
3061 strncat(check, "!", 1);
3062 strncat(check, client->username, strlen(client->username));
3063 if (!strchr(client->username, '@')) {
3064 strncat(check, "@", 1);
3065 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3068 strncat(check2, client->nickname, strlen(client->nickname));
3069 if (!strchr(client->nickname, '@')) {
3070 strncat(check2, "@", 1);
3071 strncat(check2, server->server_name, strlen(server->server_name));
3073 strncat(check2, "!", 1);
3074 strncat(check2, client->username, strlen(client->username));
3075 if (!strchr(client->username, '@')) {
3076 strncat(check2, "@", 1);
3077 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3080 /* Check invite list if channel is invite-only channel */
3081 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3082 if (!channel->invite_list ||
3083 (!silc_string_match(channel->invite_list, check) &&
3084 !silc_string_match(channel->invite_list, check2))) {
3085 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3086 SILC_STATUS_ERR_NOT_INVITED);
3091 /* Check ban list if it exists. If the client's nickname, server,
3092 username and/or hostname is in the ban list the access to the
3093 channel is denied. */
3094 if (channel->ban_list) {
3095 if (!channel->ban_list ||
3096 silc_string_match(channel->ban_list, check) ||
3097 silc_string_match(channel->ban_list, check2)) {
3098 silc_server_command_send_status_reply(
3099 cmd, SILC_COMMAND_JOIN,
3100 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
3105 /* Check user count limit if set. */
3106 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3107 if (silc_hash_table_count(channel->user_list) + 1 >
3108 channel->user_limit) {
3109 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3110 SILC_STATUS_ERR_CHANNEL_IS_FULL);
3116 /* Check the channel passphrase if set. */
3117 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3118 /* Get passphrase */
3119 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3121 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
3122 memcpy(passphrase, tmp, tmp_len);
3125 if (!passphrase || !channel->passphrase ||
3126 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3127 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3128 SILC_STATUS_ERR_BAD_PASSWORD);
3134 * Client is allowed to join to the channel. Make it happen.
3137 /* Check whether the client already is on the channel */
3138 if (silc_server_client_on_channel(client, channel)) {
3139 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3140 SILC_STATUS_ERR_USER_ON_CHANNEL);
3144 /* Generate new channel key as protocol dictates */
3146 if (!silc_server_create_channel_key(server, channel, 0))
3149 /* Send the channel key. This is broadcasted to the channel but is not
3150 sent to the client who is joining to the channel. */
3151 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3152 silc_server_send_channel_key(server, NULL, channel,
3153 server->server_type == SILC_ROUTER ?
3154 FALSE : !server->standalone);
3157 /* Join the client to the channel by adding it to channel's user list.
3158 Add also the channel to client entry's channels list for fast cross-
3160 chl = silc_calloc(1, sizeof(*chl));
3162 chl->client = client;
3163 chl->channel = channel;
3164 silc_hash_table_add(channel->user_list, client, chl);
3165 silc_hash_table_add(client->channels, channel, chl);
3167 /* Get users on the channel */
3168 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3171 /* Encode Client ID Payload of the original client who wants to join */
3172 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3174 /* Encode command reply packet */
3175 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3176 SILC_PUT32_MSB(channel->mode, mode);
3177 SILC_PUT32_MSB(created, tmp2);
3178 SILC_PUT32_MSB(user_count, tmp3);
3180 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3181 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3182 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
3183 strlen(channel->channel_key->
3185 channel->channel_key->cipher->name,
3186 channel->key_len / 8, channel->key);
3191 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3192 SILC_STATUS_OK, ident, 13,
3193 2, channel->channel_name,
3194 strlen(channel->channel_name),
3195 3, chidp->data, chidp->len,
3196 4, clidp->data, clidp->len,
3199 7, keyp ? keyp->data : NULL,
3200 keyp ? keyp->len : 0,
3201 8, channel->ban_list,
3203 strlen(channel->ban_list) : 0,
3204 9, channel->invite_list,
3205 channel->invite_list ?
3206 strlen(channel->invite_list) : 0,
3209 strlen(channel->topic) : 0,
3210 11, silc_hmac_get_name(channel->hmac),
3211 strlen(silc_hmac_get_name(channel->
3214 13, user_list->data, user_list->len,
3215 14, mode_list->data,
3218 /* Send command reply */
3219 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3220 reply->data, reply->len, FALSE);
3222 /* Send JOIN notify to locally connected clients on the channel. If
3223 we are normal server then router will send or have sent JOIN notify
3224 already. However since we've added the client already to our channel
3225 we'll ignore it (in packet_receive.c) so we must send it here. If
3226 we are router then this will send it to local clients and local
3228 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3229 SILC_NOTIFY_TYPE_JOIN, 2,
3230 clidp->data, clidp->len,
3231 chidp->data, chidp->len);
3233 if (!cmd->pending) {
3234 /* Send JOIN notify packet to our primary router */
3235 if (!server->standalone)
3236 silc_server_send_notify_join(server, server->router->connection,
3237 server->server_type == SILC_ROUTER ?
3238 TRUE : FALSE, channel, client->id);
3241 /* Distribute the channel key to all backup routers. */
3242 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3243 keyp->data, keyp->len, FALSE, TRUE);
3245 /* If client became founder by providing correct founder auth data
3246 notify the mode change to the channel. */
3248 SILC_PUT32_MSB(chl->mode, mode);
3249 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3250 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3251 clidp->data, clidp->len,
3252 mode, 4, clidp->data, clidp->len);
3254 /* Set CUMODE notify type to network */
3255 if (!server->standalone)
3256 silc_server_send_notify_cumode(server, server->router->connection,
3257 server->server_type == SILC_ROUTER ?
3258 TRUE : FALSE, channel,
3259 chl->mode, client->id, SILC_ID_CLIENT,
3264 silc_buffer_free(reply);
3265 silc_buffer_free(clidp);
3266 silc_buffer_free(chidp);
3267 silc_buffer_free(keyp);
3268 silc_buffer_free(user_list);
3269 silc_buffer_free(mode_list);
3272 silc_free(passphrase);
3275 /* Server side of command JOIN. Joins client into requested channel. If
3276 the channel does not exist it will be created. */
3278 SILC_SERVER_CMD_FUNC(join)
3280 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3281 SilcServer server = cmd->server;
3282 unsigned char *auth;
3283 uint32 tmp_len, auth_len;
3284 char *tmp, *channel_name = NULL, *cipher, *hmac;
3285 SilcChannelEntry channel;
3287 bool created = FALSE, create_key = TRUE;
3288 SilcClientID *client_id;
3290 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3292 /* Get channel name */
3293 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3295 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3296 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3301 if (strlen(channel_name) > 256)
3302 channel_name[255] = '\0';
3304 if (silc_server_command_bad_chars(channel_name) == TRUE) {
3305 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3306 SILC_STATUS_ERR_BAD_CHANNEL);
3310 /* Get Client ID of the client who is joining to the channel */
3311 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3313 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3314 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3317 client_id = silc_id_payload_parse_id(tmp, tmp_len);
3319 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3320 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3324 /* Get cipher, hmac name and auth payload */
3325 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3326 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3327 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3329 /* See if the channel exists */
3330 channel = silc_idlist_find_channel_by_name(server->local_list,
3331 channel_name, NULL);
3333 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3334 /* If this is coming from client the Client ID in the command packet must
3335 be same as the client's ID. */
3336 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3337 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3338 if (!SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
3339 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3340 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3345 if (!channel || channel->disabled) {
3346 /* Channel not found */
3348 /* If we are standalone server we don't have a router, we just create
3349 the channel by ourselves. */
3350 if (server->standalone) {
3351 channel = silc_server_create_new_channel(server, server->id, cipher,
3352 hmac, channel_name, TRUE);
3354 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3355 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3359 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3365 /* The channel does not exist on our server. If we are normal server
3366 we will send JOIN command to our router which will handle the
3367 joining procedure (either creates the channel if it doesn't exist
3368 or joins the client to it). */
3369 if (server->server_type != SILC_ROUTER) {
3373 /* If this is pending command callback then we've resolved
3374 it and it didn't work, return since we've notified the
3375 client already in the command reply callback. */
3379 old_ident = silc_command_get_ident(cmd->payload);
3380 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3381 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3383 /* Send JOIN command to our router */
3384 silc_server_packet_send(server, (SilcSocketConnection)
3385 server->router->connection,
3386 SILC_PACKET_COMMAND, cmd->packet->flags,
3387 tmpbuf->data, tmpbuf->len, TRUE);
3389 /* Reprocess this packet after received reply from router */
3390 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3391 silc_command_get_ident(cmd->payload),
3392 silc_server_command_join,
3393 silc_server_command_dup(cmd));
3394 cmd->pending = TRUE;
3398 /* We are router and the channel does not seem exist so we will check
3399 our global list as well for the channel. */
3400 channel = silc_idlist_find_channel_by_name(server->global_list,
3401 channel_name, NULL);
3403 /* Channel really does not exist, create it */
3404 channel = silc_server_create_new_channel(server, server->id, cipher,
3405 hmac, channel_name, TRUE);
3407 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3408 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3412 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3420 /* Channel not found */
3422 /* If the command came from router and we are normal server then
3423 something went wrong with the joining as the channel was not found.
3424 We can't do anything else but ignore this. */
3425 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3426 server->server_type != SILC_ROUTER)
3429 /* We are router and the channel does not seem exist so we will check
3430 our global list as well for the channel. */
3431 channel = silc_idlist_find_channel_by_name(server->global_list,
3432 channel_name, NULL);
3434 /* Channel really does not exist, create it */
3435 channel = silc_server_create_new_channel(server, server->id, cipher,
3436 hmac, channel_name, TRUE);
3438 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3439 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3443 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3450 /* Check whether the channel was created by our router */
3451 if (cmd->pending && context2) {
3452 SilcServerCommandReplyContext reply =
3453 (SilcServerCommandReplyContext)context2;
3455 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3456 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3457 SILC_GET32_MSB(created, tmp);
3458 create_key = FALSE; /* Router returned the key already */
3461 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS)
3465 /* If the channel does not have global users and is also empty the client
3466 will be the channel founder and operator. */
3467 if (!channel->global_users && !silc_hash_table_count(channel->user_list))
3468 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3470 /* Join to the channel */
3471 silc_server_command_join_channel(server, cmd, channel, client_id,
3472 created, create_key, umode,
3475 silc_free(client_id);
3478 silc_server_command_free(cmd);
3481 /* Server side of command MOTD. Sends server's current "message of the
3482 day" to the client. */
3484 SILC_SERVER_CMD_FUNC(motd)
3486 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3487 SilcServer server = cmd->server;
3488 SilcBuffer packet, idp;
3489 char *motd, *dest_server;
3491 uint16 ident = silc_command_get_ident(cmd->payload);
3493 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3495 /* Get server name */
3496 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3498 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3499 SILC_STATUS_ERR_NO_SUCH_SERVER);
3503 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3506 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3508 if (server->config && server->config->motd &&
3509 server->config->motd->motd_file) {
3511 motd = silc_file_readfile(server->config->motd->motd_file, &motd_len);
3516 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3517 SILC_STATUS_OK, ident, 2,
3522 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3523 SILC_STATUS_OK, ident, 1,
3527 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3528 packet->data, packet->len, FALSE);
3529 silc_buffer_free(packet);
3530 silc_buffer_free(idp);
3532 SilcServerEntry entry;
3534 /* Check whether we have this server cached */
3535 entry = silc_idlist_find_server_by_name(server->global_list,
3536 dest_server, TRUE, NULL);
3538 entry = silc_idlist_find_server_by_name(server->local_list,
3539 dest_server, TRUE, NULL);
3542 if (server->server_type != SILC_SERVER && !cmd->pending &&
3543 entry && !entry->motd) {
3544 /* Send to the server */
3548 old_ident = silc_command_get_ident(cmd->payload);
3549 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3550 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3552 silc_server_packet_send(server, entry->connection,
3553 SILC_PACKET_COMMAND, cmd->packet->flags,
3554 tmpbuf->data, tmpbuf->len, TRUE);
3556 /* Reprocess this packet after received reply from router */
3557 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3558 silc_command_get_ident(cmd->payload),
3559 silc_server_command_motd,
3560 silc_server_command_dup(cmd));
3561 cmd->pending = TRUE;
3562 silc_command_set_ident(cmd->payload, old_ident);
3563 silc_buffer_free(tmpbuf);
3567 if (!entry && !cmd->pending && !server->standalone) {
3568 /* Send to the primary router */
3572 old_ident = silc_command_get_ident(cmd->payload);
3573 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3574 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3576 silc_server_packet_send(server, server->router->connection,
3577 SILC_PACKET_COMMAND, cmd->packet->flags,
3578 tmpbuf->data, tmpbuf->len, TRUE);
3580 /* Reprocess this packet after received reply from router */
3581 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3582 silc_command_get_ident(cmd->payload),
3583 silc_server_command_motd,
3584 silc_server_command_dup(cmd));
3585 cmd->pending = TRUE;
3586 silc_command_set_ident(cmd->payload, old_ident);
3587 silc_buffer_free(tmpbuf);
3592 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3593 SILC_STATUS_ERR_NO_SUCH_SERVER);
3597 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3598 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3599 SILC_STATUS_OK, ident, 2,
3603 strlen(entry->motd) : 0);
3604 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3605 packet->data, packet->len, FALSE);
3606 silc_buffer_free(packet);
3607 silc_buffer_free(idp);
3611 silc_server_command_free(cmd);
3614 /* Server side of command UMODE. Client can use this command to set/unset
3615 user mode. Client actually cannot set itself to be as server/router
3616 operator so this can be used only to unset the modes. */
3618 SILC_SERVER_CMD_FUNC(umode)
3620 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3621 SilcServer server = cmd->server;
3622 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3624 unsigned char *tmp_mask;
3626 uint16 ident = silc_command_get_ident(cmd->payload);
3628 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3631 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 2, 2);
3633 /* Get the client's mode mask */
3634 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3636 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3637 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3640 SILC_GET32_MSB(mask, tmp_mask);
3646 if (mask & SILC_UMODE_SERVER_OPERATOR) {
3647 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR)) {
3648 /* Cannot operator mode */
3649 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3650 SILC_STATUS_ERR_PERM_DENIED);
3654 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
3655 /* Remove the server operator rights */
3656 client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3659 if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3660 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
3661 /* Cannot operator mode */
3662 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3663 SILC_STATUS_ERR_PERM_DENIED);
3667 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
3668 /* Remove the router operator rights */
3669 client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3672 if (mask & SILC_UMODE_GONE) {
3673 client->mode |= SILC_UMODE_GONE;
3675 if (client->mode & SILC_UMODE_GONE)
3676 /* Remove the gone status */
3677 client->mode &= ~SILC_UMODE_GONE;
3680 /* Send UMODE change to primary router */
3681 if (!server->standalone)
3682 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3683 client->id, client->mode);
3685 /* Send command reply to sender */
3686 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3687 SILC_STATUS_OK, ident, 1,
3689 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3690 packet->data, packet->len, FALSE);
3691 silc_buffer_free(packet);
3694 silc_server_command_free(cmd);
3697 /* Checks that client has rights to add or remove channel modes. If any
3698 of the checks fails FALSE is returned. */
3700 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3701 SilcChannelClientEntry client,
3704 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3705 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3707 /* Check whether has rights to change anything */
3708 if (!is_op && !is_fo)
3711 /* Check whether has rights to change everything */
3715 /* We know that client is channel operator, check that they are not
3716 changing anything that requires channel founder rights. Rest of the
3717 modes are available automatically for channel operator. */
3719 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3720 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3721 if (is_op && !is_fo)
3724 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3725 if (is_op && !is_fo)
3730 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3731 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE))
3732 if (is_op && !is_fo)
3735 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3736 if (is_op && !is_fo)
3741 if (mode & SILC_CHANNEL_MODE_CIPHER) {
3742 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER))
3743 if (is_op && !is_fo)
3746 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3747 if (is_op && !is_fo)
3752 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3753 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH))
3754 if (is_op && !is_fo)
3757 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3758 if (is_op && !is_fo)
3766 /* Server side command of CMODE. Changes channel mode */
3768 SILC_SERVER_CMD_FUNC(cmode)
3770 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3771 SilcServer server = cmd->server;
3772 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3773 SilcIDListData idata = (SilcIDListData)client;
3774 SilcChannelID *channel_id;
3775 SilcChannelEntry channel;
3776 SilcChannelClientEntry chl;
3777 SilcBuffer packet, cidp;
3778 unsigned char *tmp, *tmp_id, *tmp_mask;
3779 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3780 uint32 mode_mask, tmp_len, tmp_len2;
3781 uint16 ident = silc_command_get_ident(cmd->payload);
3783 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 2, 7);
3785 /* Get Channel ID */
3786 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3788 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3789 SILC_STATUS_ERR_NO_CHANNEL_ID);
3792 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3794 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3795 SILC_STATUS_ERR_NO_CHANNEL_ID);
3799 /* Get the channel mode mask */
3800 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3802 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3803 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3806 SILC_GET32_MSB(mode_mask, tmp_mask);
3808 /* Get channel entry */
3809 channel = silc_idlist_find_channel_by_id(server->local_list,
3812 channel = silc_idlist_find_channel_by_id(server->global_list,
3815 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3816 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3821 /* Check whether this client is on the channel */
3822 if (!silc_server_client_on_channel(client, channel)) {
3823 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3824 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3828 /* Get entry to the channel user list */
3829 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
3831 /* Check that client has rights to change any requested channel modes */
3832 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3833 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3834 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3839 * Check the modes. Modes that requires nothing special operation are
3843 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3844 /* Channel uses private keys to protect traffic. Client(s) has set the
3845 key locally they want to use, server does not know that key. */
3846 /* Nothing interesting to do here */
3848 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3849 /* The mode is removed and we need to generate and distribute
3850 new channel key. Clients are not using private channel keys
3851 anymore after this. */
3853 /* Re-generate channel key */
3854 if (!silc_server_create_channel_key(server, channel, 0))
3857 /* Send the channel key. This sends it to our local clients and if
3858 we are normal server to our router as well. */
3859 silc_server_send_channel_key(server, NULL, channel,
3860 server->server_type == SILC_ROUTER ?
3861 FALSE : !server->standalone);
3863 cipher = channel->channel_key->cipher->name;
3864 hmac = (char *)silc_hmac_get_name(channel->hmac);
3868 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3869 /* User limit is set on channel */
3872 /* Get user limit */
3873 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3875 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3876 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3877 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3881 SILC_GET32_MSB(user_limit, tmp);
3882 channel->user_limit = user_limit;
3885 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3886 /* User limit mode is unset. Remove user limit */
3887 channel->user_limit = 0;
3890 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3891 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3892 /* Passphrase has been set to channel */
3894 /* Get the passphrase */
3895 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3897 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3898 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3902 /* Save the passphrase */
3903 passphrase = channel->passphrase = strdup(tmp);
3906 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3907 /* Passphrase mode is unset. remove the passphrase */
3908 if (channel->passphrase) {
3909 silc_free(channel->passphrase);
3910 channel->passphrase = NULL;
3915 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3916 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3917 /* Cipher to use protect the traffic */
3918 SilcCipher newkey, oldkey;
3921 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3923 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3924 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3928 /* Delete old cipher and allocate the new one */
3929 if (!silc_cipher_alloc(cipher, &newkey)) {
3930 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3931 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3935 oldkey = channel->channel_key;
3936 channel->channel_key = newkey;
3938 /* Re-generate channel key */
3939 if (!silc_server_create_channel_key(server, channel, 0)) {
3940 /* We don't have new key, revert to old one */
3941 channel->channel_key = oldkey;
3945 /* Remove old channel key for good */
3946 silc_cipher_free(oldkey);
3948 /* Send the channel key. This sends it to our local clients and if
3949 we are normal server to our router as well. */
3950 silc_server_send_channel_key(server, NULL, channel,
3951 server->server_type == SILC_ROUTER ?
3952 FALSE : !server->standalone);
3955 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3956 /* Cipher mode is unset. Remove the cipher and revert back to
3958 SilcCipher newkey, oldkey;
3959 cipher = channel->cipher;
3961 /* Delete old cipher and allocate default one */
3962 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
3963 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3964 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3968 oldkey = channel->channel_key;
3969 channel->channel_key = newkey;
3971 /* Re-generate channel key */
3972 if (!silc_server_create_channel_key(server, channel, 0)) {
3973 /* We don't have new key, revert to old one */
3974 channel->channel_key = oldkey;
3978 /* Remove old channel key for good */
3979 silc_cipher_free(oldkey);
3981 /* Send the channel key. This sends it to our local clients and if
3982 we are normal server to our router as well. */
3983 silc_server_send_channel_key(server, NULL, channel,
3984 server->server_type == SILC_ROUTER ?
3985 FALSE : !server->standalone);
3989 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3990 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3991 /* HMAC to use protect the traffic */
3992 unsigned char hash[32];
3996 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3998 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3999 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4003 /* Delete old hmac and allocate the new one */
4004 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4005 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4006 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4010 silc_hmac_free(channel->hmac);
4011 channel->hmac = newhmac;
4013 /* Set the HMAC key out of current channel key. The client must do
4015 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4016 channel->key_len / 8, hash);
4017 silc_hmac_set_key(channel->hmac, hash,
4018 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4019 memset(hash, 0, sizeof(hash));
4022 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4023 /* Hmac mode is unset. Remove the hmac and revert back to
4026 unsigned char hash[32];
4027 hmac = channel->hmac_name;
4029 /* Delete old hmac and allocate default one */
4030 silc_hmac_free(channel->hmac);
4031 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4032 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4033 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4037 silc_hmac_free(channel->hmac);
4038 channel->hmac = newhmac;
4040 /* Set the HMAC key out of current channel key. The client must do
4042 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4043 channel->key_len / 8,
4045 silc_hmac_set_key(channel->hmac, hash,
4046 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4047 memset(hash, 0, sizeof(hash));
4051 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4052 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4053 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4054 /* Set the founder authentication */
4055 SilcAuthPayload auth;
4057 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4059 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4060 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4064 auth = silc_auth_payload_parse(tmp, tmp_len);
4066 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4067 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4071 /* Save the public key */
4072 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
4073 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
4076 channel->founder_method = silc_auth_get_method(auth);
4078 if (channel->founder_method == SILC_AUTH_PASSWORD) {
4079 tmp = silc_auth_get_data(auth, &tmp_len);
4080 channel->founder_passwd =
4081 silc_calloc(tmp_len + 1, sizeof(*channel->founder_passwd));
4082 memcpy(channel->founder_passwd, tmp, tmp_len);
4083 channel->founder_passwd_len = tmp_len;
4085 /* Verify the payload before setting the mode */
4086 if (!silc_auth_verify(auth, channel->founder_method,
4087 channel->founder_key, 0, idata->hash,
4088 client->id, SILC_ID_CLIENT)) {
4089 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4090 SILC_STATUS_ERR_AUTH_FAILED);
4095 silc_auth_payload_free(auth);
4099 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4100 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4101 if (channel->founder_key)
4102 silc_pkcs_public_key_free(channel->founder_key);
4103 if (channel->founder_passwd) {
4104 silc_free(channel->founder_passwd);
4105 channel->founder_passwd = NULL;
4111 /* Finally, set the mode */
4112 channel->mode = mode_mask;
4114 /* Send CMODE_CHANGE notify. */
4115 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4116 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4117 SILC_NOTIFY_TYPE_CMODE_CHANGE, 5,
4118 cidp->data, cidp->len,
4120 cipher, cipher ? strlen(cipher) : 0,
4121 hmac, hmac ? strlen(hmac) : 0,
4122 passphrase, passphrase ?
4123 strlen(passphrase) : 0);
4125 /* Set CMODE notify type to network */
4126 if (!server->standalone)
4127 silc_server_send_notify_cmode(server, server->router->connection,
4128 server->server_type == SILC_ROUTER ?
4129 TRUE : FALSE, channel,
4130 mode_mask, client->id, SILC_ID_CLIENT,
4131 cipher, hmac, passphrase);
4133 /* Send command reply to sender */
4134 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4135 SILC_STATUS_OK, ident, 2,
4136 2, tmp_id, tmp_len2,
4138 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4139 packet->data, packet->len, FALSE);
4141 silc_buffer_free(packet);
4142 silc_free(channel_id);
4143 silc_buffer_free(cidp);
4146 silc_server_command_free(cmd);
4149 /* Server side of CUMODE command. Changes client's mode on a channel. */
4151 SILC_SERVER_CMD_FUNC(cumode)
4153 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4154 SilcServer server = cmd->server;
4155 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4156 SilcIDListData idata = (SilcIDListData)client;
4157 SilcChannelID *channel_id;
4158 SilcClientID *client_id;
4159 SilcChannelEntry channel;
4160 SilcClientEntry target_client;
4161 SilcChannelClientEntry chl;
4162 SilcBuffer packet, idp;
4163 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4164 uint32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4166 uint16 ident = silc_command_get_ident(cmd->payload);
4168 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4170 /* Get Channel ID */
4171 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4173 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4174 SILC_STATUS_ERR_NO_CHANNEL_ID);
4177 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
4179 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4180 SILC_STATUS_ERR_NO_CHANNEL_ID);
4184 /* Get channel entry */
4185 channel = silc_idlist_find_channel_by_id(server->local_list,
4188 channel = silc_idlist_find_channel_by_id(server->global_list,
4191 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4192 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4197 /* Check whether sender is on the channel */
4198 if (!silc_server_client_on_channel(client, channel)) {
4199 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4200 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4204 /* Check that client has rights to change other's rights */
4205 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4206 sender_mask = chl->mode;
4208 /* Get the target client's channel mode mask */
4209 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4211 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4212 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4215 SILC_GET32_MSB(target_mask, tmp_mask);
4217 /* Get target Client ID */
4218 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4220 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4221 SILC_STATUS_ERR_NO_CLIENT_ID);
4224 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
4226 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4227 SILC_STATUS_ERR_NO_CLIENT_ID);
4231 /* Get target client's entry */
4232 target_client = silc_idlist_find_client_by_id(server->local_list,
4233 client_id, TRUE, NULL);
4234 if (!target_client) {
4235 target_client = silc_idlist_find_client_by_id(server->global_list,
4236 client_id, TRUE, NULL);
4239 if (target_client != client &&
4240 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4241 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4242 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4243 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4247 /* Check whether target client is on the channel */
4248 if (target_client != client) {
4249 if (!silc_server_client_on_channel(target_client, channel)) {
4250 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4251 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4255 /* Get entry to the channel user list */
4256 silc_hash_table_find(channel->user_list, target_client, NULL,
4264 /* If the target client is founder, no one else can change their mode
4266 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
4267 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4268 SILC_STATUS_ERR_NOT_YOU);
4272 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4273 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4274 /* The client tries to claim the founder rights. */
4275 unsigned char *tmp_auth;
4276 uint32 tmp_auth_len, auth_len;
4279 if (target_client != client) {
4280 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4281 SILC_STATUS_ERR_NOT_YOU);
4285 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4286 !channel->founder_key || !idata->public_key ||
4287 !silc_pkcs_public_key_compare(channel->founder_key,
4288 idata->public_key)) {
4289 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4290 SILC_STATUS_ERR_NOT_YOU);
4294 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4296 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4297 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4301 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4302 (void *)channel->founder_passwd : (void *)channel->founder_key);
4303 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4304 channel->founder_passwd_len : 0);
4306 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4307 channel->founder_method, auth, auth_len,
4308 idata->hash, client->id, SILC_ID_CLIENT)) {
4309 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4310 SILC_STATUS_ERR_AUTH_FAILED);
4314 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4318 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4319 if (target_client == client) {
4320 /* Remove channel founder rights from itself */
4321 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4324 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4325 SILC_STATUS_ERR_NOT_YOU);
4331 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4332 /* Promote to operator */
4333 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4334 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4335 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4336 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4337 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4341 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4345 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4346 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4347 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4348 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4349 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4353 /* Demote to normal user */
4354 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4359 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4360 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4362 /* Send notify to channel, notify only if mode was actually changed. */
4364 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4365 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4366 idp->data, idp->len,
4370 /* Set CUMODE notify type to network */
4371 if (!server->standalone)
4372 silc_server_send_notify_cumode(server, server->router->connection,
4373 server->server_type == SILC_ROUTER ?
4374 TRUE : FALSE, channel,
4375 target_mask, client->id,
4380 /* Send command reply to sender */
4381 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4382 SILC_STATUS_OK, ident, 3,
4384 3, tmp_ch_id, tmp_ch_len,
4385 4, tmp_id, tmp_len);
4386 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4387 packet->data, packet->len, FALSE);
4389 silc_buffer_free(packet);
4390 silc_free(channel_id);
4391 silc_free(client_id);
4392 silc_buffer_free(idp);
4395 silc_server_command_free(cmd);
4398 /* Server side of KICK command. Kicks client out of channel. */
4400 SILC_SERVER_CMD_FUNC(kick)
4402 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4403 SilcServer server = cmd->server;
4404 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4405 SilcClientEntry target_client;
4406 SilcChannelID *channel_id;
4407 SilcClientID *client_id;
4408 SilcChannelEntry channel;
4409 SilcChannelClientEntry chl;
4411 uint32 tmp_len, target_idp_len;
4412 unsigned char *tmp, *comment, *target_idp;
4414 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4416 /* Get Channel ID */
4417 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4419 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4420 SILC_STATUS_ERR_NO_CHANNEL_ID);
4423 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
4425 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4426 SILC_STATUS_ERR_NO_CHANNEL_ID);
4430 /* Get channel entry */
4431 channel = silc_idlist_find_channel_by_id(server->local_list,
4434 channel = silc_idlist_find_channel_by_id(server->local_list,
4437 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4438 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4443 /* Check whether sender is on the channel */
4444 if (!silc_server_client_on_channel(client, channel)) {
4445 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4446 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4450 /* Check that the kicker is channel operator or channel founder */
4451 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4452 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4453 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4454 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4458 /* Get target Client ID */
4459 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4461 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4462 SILC_STATUS_ERR_NO_CLIENT_ID);
4465 client_id = silc_id_payload_parse_id(target_idp, target_idp_len);
4467 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4468 SILC_STATUS_ERR_NO_CLIENT_ID);
4472 /* Get target client's entry */
4473 target_client = silc_idlist_find_client_by_id(server->local_list,
4474 client_id, TRUE, NULL);
4475 if (!target_client) {
4476 target_client = silc_idlist_find_client_by_id(server->global_list,
4477 client_id, TRUE, NULL);
4480 /* Check that the target client is not channel founder. Channel founder
4481 cannot be kicked from the channel. */
4482 silc_hash_table_find(channel->user_list, target_client, NULL, (void *)&chl);
4483 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4484 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4485 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4489 /* Check whether target client is on the channel */
4490 if (!silc_server_client_on_channel(target_client, channel)) {
4491 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4492 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4498 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4502 /* Send command reply to sender */
4503 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4506 /* Send KICKED notify to local clients on the channel */
4507 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4508 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4509 SILC_NOTIFY_TYPE_KICKED, 3,
4510 target_idp, target_idp_len,
4511 comment, comment ? strlen(comment) : 0,
4512 idp->data, idp->len);
4513 silc_buffer_free(idp);
4515 /* Remove the client from the channel. If the channel does not exist
4516 after removing the client then the client kicked itself off the channel
4517 and we don't have to send anything after that. */
4518 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4519 target_client, FALSE))
4522 /* Send KICKED notify to primary route */
4523 if (!server->standalone)
4524 silc_server_send_notify_kicked(server, server->router->connection,
4525 server->server_type == SILC_ROUTER ?
4526 TRUE : FALSE, channel,
4527 target_client->id, comment);
4529 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4530 /* Re-generate channel key */
4531 if (!silc_server_create_channel_key(server, channel, 0))
4534 /* Send the channel key to the channel. The key of course is not sent
4535 to the client who was kicked off the channel. */
4536 silc_server_send_channel_key(server, target_client->connection, channel,
4537 server->server_type == SILC_ROUTER ?
4538 FALSE : !server->standalone);
4542 silc_server_command_free(cmd);
4545 /* Server side of OPER command. Client uses this comand to obtain server
4546 operator privileges to this server/router. */
4548 SILC_SERVER_CMD_FUNC(oper)
4550 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4551 SilcServer server = cmd->server;
4552 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4553 unsigned char *username, *auth;
4555 SilcServerConfigSectionAdminConnection *admin;
4556 SilcIDListData idata = (SilcIDListData)client;
4558 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4560 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4563 /* Get the username */
4564 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4566 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4567 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4571 /* Get the admin configuration */
4572 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4573 username, client->nickname);
4575 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4576 username, client->nickname);
4578 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4579 SILC_STATUS_ERR_AUTH_FAILED);
4584 /* Get the authentication payload */
4585 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4587 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4588 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4592 /* Verify the authentication data */
4593 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4594 admin->auth_data, admin->auth_data_len,
4595 idata->hash, client->id, SILC_ID_CLIENT)) {
4596 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4597 SILC_STATUS_ERR_AUTH_FAILED);
4601 /* Client is now server operator */
4602 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4604 /* Send UMODE change to primary router */
4605 if (!server->standalone)
4606 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4607 client->id, client->mode);
4609 /* Send reply to the sender */
4610 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4614 silc_server_command_free(cmd);
4617 /* Server side of SILCOPER command. Client uses this comand to obtain router
4618 operator privileges to this router. */
4620 SILC_SERVER_CMD_FUNC(silcoper)
4622 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4623 SilcServer server = cmd->server;
4624 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4625 unsigned char *username, *auth;
4627 SilcServerConfigSectionAdminConnection *admin;
4628 SilcIDListData idata = (SilcIDListData)client;
4630 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4632 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4635 if (server->server_type != SILC_ROUTER) {
4636 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4637 SILC_STATUS_ERR_AUTH_FAILED);
4641 /* Get the username */
4642 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4644 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4645 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4649 /* Get the admin configuration */
4650 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4651 username, client->nickname);
4653 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4654 username, client->nickname);
4656 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4657 SILC_STATUS_ERR_AUTH_FAILED);
4662 /* Get the authentication payload */
4663 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4665 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4666 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4670 /* Verify the authentication data */
4671 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4672 admin->auth_data, admin->auth_data_len,
4673 idata->hash, client->id, SILC_ID_CLIENT)) {
4674 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4675 SILC_STATUS_ERR_AUTH_FAILED);
4679 /* Client is now router operator */
4680 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4682 /* Send UMODE change to primary router */
4683 if (!server->standalone)
4684 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4685 client->id, client->mode);
4687 /* Send reply to the sender */
4688 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4692 silc_server_command_free(cmd);
4695 /* Server side command of CONNECT. Connects us to the specified remote
4696 server or router. */
4698 SILC_SERVER_CMD_FUNC(connect)
4700 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4701 SilcServer server = cmd->server;
4702 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4703 unsigned char *tmp, *host;
4705 uint32 port = SILC_PORT;
4707 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CONNECT, cmd, 1, 2);
4709 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4712 /* Check whether client has the permissions. */
4713 if (client->mode == SILC_UMODE_NONE) {
4714 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4715 SILC_STATUS_ERR_NO_SERVER_PRIV);
4719 if (server->server_type == SILC_ROUTER &&
4720 client->mode & SILC_UMODE_SERVER_OPERATOR) {
4721 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4722 SILC_STATUS_ERR_NO_ROUTER_PRIV);
4726 /* Get the remote server */
4727 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4729 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4730 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4735 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4737 SILC_GET32_MSB(port, tmp);
4739 /* Create the connection. It is done with timeout and is async. */
4740 silc_server_create_connection(server, host, port);
4742 /* Send reply to the sender */
4743 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4747 silc_server_command_free(cmd);
4750 /* Server side of command BAN. This is used to manage the ban list of the
4751 channel. To add clients and remove clients from the ban list. */
4753 SILC_SERVER_CMD_FUNC(ban)
4755 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4756 SilcServer server = cmd->server;
4757 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4759 SilcChannelEntry channel;
4760 SilcChannelClientEntry chl;
4761 SilcChannelID *channel_id = NULL;
4762 unsigned char *id, *add, *del;
4763 uint32 id_len, tmp_len;
4764 uint16 ident = silc_command_get_ident(cmd->payload);
4766 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4769 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4771 /* Get Channel ID */
4772 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4774 channel_id = silc_id_payload_parse_id(id, id_len);
4776 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4777 SILC_STATUS_ERR_NO_CHANNEL_ID);
4782 /* Get channel entry. The server must know about the channel since the
4783 client is expected to be on the channel. */
4784 channel = silc_idlist_find_channel_by_id(server->local_list,
4787 channel = silc_idlist_find_channel_by_id(server->global_list,
4790 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4791 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4796 /* Check whether this client is on the channel */
4797 if (!silc_server_client_on_channel(client, channel)) {
4798 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4799 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4803 /* Get entry to the channel user list */
4804 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4806 /* The client must be at least channel operator. */
4807 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4808 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4809 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4813 /* Get the new ban and add it to the ban list */
4814 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4816 if (!channel->ban_list)
4817 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4819 channel->ban_list = silc_realloc(channel->ban_list,
4820 sizeof(*channel->ban_list) *
4822 strlen(channel->ban_list) + 2));
4823 if (add[tmp_len - 1] == ',')
4824 add[tmp_len - 1] = '\0';
4826 strncat(channel->ban_list, add, tmp_len);
4827 strncat(channel->ban_list, ",", 1);
4830 /* Get the ban to be removed and remove it from the list */
4831 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4832 if (del && channel->ban_list) {
4833 char *start, *end, *n;
4835 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4836 silc_free(channel->ban_list);
4837 channel->ban_list = NULL;
4839 start = strstr(channel->ban_list, del);
4840 if (start && strlen(start) >= tmp_len) {
4841 end = start + tmp_len;
4842 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4843 strncat(n, channel->ban_list, start - channel->ban_list);
4844 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4846 silc_free(channel->ban_list);
4847 channel->ban_list = n;
4852 /* Send the BAN notify type to our primary router. */
4853 if (!server->standalone && (add || del))
4854 silc_server_send_notify_ban(server, server->router->connection,
4855 server->server_type == SILC_ROUTER ?
4856 TRUE : FALSE, channel, add, del);
4858 /* Send the reply back to the client */
4860 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4861 SILC_STATUS_OK, ident, 2,
4863 3, channel->ban_list,
4865 strlen(channel->ban_list) - 1 : 0);
4866 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4867 packet->data, packet->len, FALSE);
4869 silc_buffer_free(packet);
4872 silc_free(channel_id);
4873 silc_server_command_free(cmd);
4876 /* Server side command of CLOSE. Closes connection to a specified server. */
4878 SILC_SERVER_CMD_FUNC(close)
4880 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4881 SilcServer server = cmd->server;
4882 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4883 SilcServerEntry server_entry;
4884 SilcSocketConnection sock;
4887 unsigned char *name;
4888 uint32 port = SILC_PORT;
4890 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CLOSE, cmd, 1, 2);
4892 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4895 /* Check whether client has the permissions. */
4896 if (client->mode == SILC_UMODE_NONE) {
4897 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4898 SILC_STATUS_ERR_NO_SERVER_PRIV);
4902 /* Get the remote server */
4903 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4905 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4906 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4911 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4913 SILC_GET32_MSB(port, tmp);
4915 server_entry = silc_idlist_find_server_by_conn(server->local_list,
4916 name, port, FALSE, NULL);
4918 server_entry = silc_idlist_find_server_by_conn(server->global_list,
4919 name, port, FALSE, NULL);
4920 if (!server_entry) {
4921 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4922 SILC_STATUS_ERR_NO_SERVER_ID);
4926 /* Send reply to the sender */
4927 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4930 /* Close the connection to the server */
4931 sock = (SilcSocketConnection)server_entry->connection;
4933 /* If we shutdown primary router connection manually then don't trigger
4934 any reconnect or backup router connections, by setting the router
4936 if (server->router == server_entry) {
4937 server->id_entry->router = NULL;
4938 server->router = NULL;
4939 server->standalone = TRUE;
4941 silc_server_free_sock_user_data(server, sock);
4942 silc_server_close_connection(server, sock);
4945 silc_server_command_free(cmd);
4948 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4949 active connections. */
4951 SILC_SERVER_CMD_FUNC(shutdown)
4953 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4954 SilcServer server = cmd->server;
4955 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4957 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4959 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4962 /* Check whether client has the permission. */
4963 if (client->mode == SILC_UMODE_NONE) {
4964 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4965 SILC_STATUS_ERR_NO_SERVER_PRIV);
4969 /* Send reply to the sender */
4970 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4973 /* Then, gracefully, or not, bring the server down. */
4974 silc_server_stop(server);
4978 silc_server_command_free(cmd);
4981 /* Server side command of LEAVE. Removes client from a channel. */
4983 SILC_SERVER_CMD_FUNC(leave)
4985 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4986 SilcServer server = cmd->server;
4987 SilcSocketConnection sock = cmd->sock;
4988 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4989 SilcChannelID *id = NULL;
4990 SilcChannelEntry channel;
4994 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4996 /* Get Channel ID */
4997 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4999 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5000 SILC_STATUS_ERR_NO_CHANNEL_ID);
5003 id = silc_id_payload_parse_id(tmp, len);
5005 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5006 SILC_STATUS_ERR_NO_CHANNEL_ID);
5010 /* Get channel entry */
5011 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5013 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5015 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5016 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5021 /* Check whether this client is on the channel */
5022 if (!silc_server_client_on_channel(id_entry, channel)) {
5023 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5024 SILC_STATUS_ERR_NOT_ON_CHANNEL);
5028 /* Notify routers that they should remove this client from their list
5029 of clients on the channel. Send LEAVE notify type. */
5030 if (!server->standalone)
5031 silc_server_send_notify_leave(server, server->router->connection,
5032 server->server_type == SILC_ROUTER ?
5033 TRUE : FALSE, channel, id_entry->id);
5035 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5038 /* Remove client from channel */
5039 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5041 /* If the channel does not exist anymore we won't send anything */
5044 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5045 /* Re-generate channel key */
5046 if (!silc_server_create_channel_key(server, channel, 0))
5049 /* Send the channel key */
5050 silc_server_send_channel_key(server, NULL, channel,
5051 server->server_type == SILC_ROUTER ?
5052 FALSE : !server->standalone);
5057 silc_server_command_free(cmd);
5060 /* Server side of command USERS. Resolves clients and their USERS currently
5061 joined on the requested channel. The list of Client ID's and their modes
5062 on the channel is sent back. */
5064 SILC_SERVER_CMD_FUNC(users)
5066 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5067 SilcServer server = cmd->server;
5068 SilcChannelEntry channel;
5069 SilcChannelID *id = NULL;
5070 SilcBuffer packet, idp;
5071 unsigned char *channel_id;
5072 uint32 channel_id_len;
5073 SilcBuffer client_id_list;
5074 SilcBuffer client_mode_list;
5075 unsigned char lc[4];
5076 uint32 list_count = 0;
5077 uint16 ident = silc_command_get_ident(cmd->payload);
5080 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5082 /* Get Channel ID */
5083 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5085 /* Get channel name */
5086 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5088 if (!channel_id && !channel_name) {
5089 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5090 SILC_STATUS_ERR_NO_CHANNEL_ID);
5095 id = silc_id_payload_parse_id(channel_id, channel_id_len);
5097 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5098 SILC_STATUS_ERR_NO_CHANNEL_ID);
5103 /* If we are server and we don't know about this channel we will send
5104 the command to our router. If we know about the channel then we also
5105 have the list of users already. */
5107 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5109 channel = silc_idlist_find_channel_by_name(server->local_list,
5110 channel_name, NULL);
5112 if (!channel || channel->disabled) {
5113 if (server->server_type != SILC_ROUTER && !server->standalone &&
5117 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5118 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5120 /* Send USERS command */
5121 silc_server_packet_send(server, server->router->connection,
5122 SILC_PACKET_COMMAND, cmd->packet->flags,
5123 tmpbuf->data, tmpbuf->len, TRUE);
5125 /* Reprocess this packet after received reply */
5126 silc_server_command_pending(server, SILC_COMMAND_USERS,
5127 silc_command_get_ident(cmd->payload),
5128 silc_server_command_users,
5129 silc_server_command_dup(cmd));
5130 cmd->pending = TRUE;
5131 silc_command_set_ident(cmd->payload, ident);
5132 silc_buffer_free(tmpbuf);
5137 /* Check the global list as well. */
5139 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5141 channel = silc_idlist_find_channel_by_name(server->global_list,
5142 channel_name, NULL);
5144 /* Channel really does not exist */
5145 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5146 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5151 /* If the channel is private or secret do not send anything, unless the
5152 user requesting this command is on the channel. */
5153 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5154 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5155 && !silc_server_client_on_channel(cmd->sock->user_data, channel)) {
5156 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5157 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5162 (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
5163 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5164 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5169 /* Get the users list */
5170 silc_server_get_users_on_channel(server, channel, &client_id_list,
5171 &client_mode_list, &list_count);
5174 SILC_PUT32_MSB(list_count, lc);
5177 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5178 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5179 SILC_STATUS_OK, ident, 4,
5180 2, idp->data, idp->len,
5182 4, client_id_list->data,
5183 client_id_list->len,
5184 5, client_mode_list->data,
5185 client_mode_list->len);
5186 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5187 packet->data, packet->len, FALSE);
5189 silc_buffer_free(idp);
5190 silc_buffer_free(packet);
5191 silc_buffer_free(client_id_list);
5192 silc_buffer_free(client_mode_list);
5196 silc_server_command_free(cmd);
5199 /* Server side of command GETKEY. This fetches the client's public key
5200 from the server where to the client is connected. */
5202 SILC_SERVER_CMD_FUNC(getkey)
5204 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5205 SilcServer server = cmd->server;
5207 SilcClientEntry client;
5208 SilcServerEntry server_entry;
5209 SilcClientID *client_id = NULL;
5210 SilcServerID *server_id = NULL;
5211 SilcIDPayload idp = NULL;
5212 uint16 ident = silc_command_get_ident(cmd->payload);
5213 unsigned char *tmp, *pkdata;
5214 uint32 tmp_len, pklen;
5215 SilcBuffer pk = NULL;
5218 SILC_LOG_DEBUG(("Start"));
5220 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5222 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5223 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5226 idp = silc_id_payload_parse(tmp, tmp_len);
5228 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5229 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5233 id_type = silc_id_payload_get_type(idp);
5234 if (id_type == SILC_ID_CLIENT) {
5235 client_id = silc_id_payload_get_id(idp);
5237 /* If the client is not found from local list there is no chance it
5238 would be locally connected client so send the command further. */
5239 client = silc_idlist_find_client_by_id(server->local_list,
5240 client_id, TRUE, NULL);
5242 client = silc_idlist_find_client_by_id(server->global_list,
5243 client_id, TRUE, NULL);
5245 if ((!client && !cmd->pending && !server->standalone) ||
5246 (client && !client->connection && !cmd->pending) ||
5247 (client && !client->data.public_key && !cmd->pending)) {
5250 SilcSocketConnection dest_sock;
5252 dest_sock = silc_server_get_client_route(server, NULL, 0,
5257 old_ident = silc_command_get_ident(cmd->payload);
5258 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5259 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5261 silc_server_packet_send(server, dest_sock,
5262 SILC_PACKET_COMMAND, cmd->packet->flags,
5263 tmpbuf->data, tmpbuf->len, TRUE);
5265 /* Reprocess this packet after received reply from router */
5266 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5267 silc_command_get_ident(cmd->payload),
5268 silc_server_command_getkey,
5269 silc_server_command_dup(cmd));
5270 cmd->pending = TRUE;
5271 silc_command_set_ident(cmd->payload, old_ident);
5272 silc_buffer_free(tmpbuf);
5277 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5278 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5282 /* The client is locally connected, just get the public key and
5283 send it back. If they key does not exist then do not send it,
5284 send just OK reply */
5285 if (!client->data.public_key) {
5289 tmp = silc_pkcs_public_key_encode(client->data.public_key, &tmp_len);
5290 pk = silc_buffer_alloc(4 + tmp_len);
5291 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5292 silc_buffer_format(pk,
5293 SILC_STR_UI_SHORT(tmp_len),
5294 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5295 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5301 } else if (id_type == SILC_ID_SERVER) {
5302 server_id = silc_id_payload_get_id(idp);
5304 /* If the server is not found from local list there is no chance it
5305 would be locally connected server so send the command further. */
5306 server_entry = silc_idlist_find_server_by_id(server->local_list,
5307 server_id, TRUE, NULL);
5309 server_entry = silc_idlist_find_server_by_id(server->global_list,
5310 server_id, TRUE, NULL);
5312 if (server_entry != server->id_entry &&
5313 ((!server_entry && !cmd->pending && !server->standalone) ||
5314 (server_entry && !server_entry->connection && !cmd->pending &&
5315 !server->standalone) ||
5316 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5317 !server->standalone))) {
5321 old_ident = silc_command_get_ident(cmd->payload);
5322 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5323 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5325 silc_server_packet_send(server, server->router->connection,
5326 SILC_PACKET_COMMAND, cmd->packet->flags,
5327 tmpbuf->data, tmpbuf->len, TRUE);
5329 /* Reprocess this packet after received reply from router */
5330 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5331 silc_command_get_ident(cmd->payload),
5332 silc_server_command_getkey,
5333 silc_server_command_dup(cmd));
5334 cmd->pending = TRUE;
5336 silc_command_set_ident(cmd->payload, old_ident);
5337 silc_buffer_free(tmpbuf);
5341 if (!server_entry) {
5342 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5343 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5347 /* If they key does not exist then do not send it, send just OK reply */
5348 if (!server_entry->data.public_key) {
5352 tmp = silc_pkcs_public_key_encode(server_entry->data.public_key,
5354 pk = silc_buffer_alloc(4 + tmp_len);
5355 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5356 silc_buffer_format(pk,
5357 SILC_STR_UI_SHORT(tmp_len),
5358 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5359 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5369 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5370 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5371 SILC_STATUS_OK, ident,
5375 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5376 packet->data, packet->len, FALSE);
5377 silc_buffer_free(packet);
5380 silc_buffer_free(pk);
5384 silc_id_payload_free(idp);
5385 silc_free(client_id);
5386 silc_free(server_id);
5387 silc_server_command_free(cmd);