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 /* Server side of command NICK. Sets nickname for user. Setting
1955 nickname causes generation of a new client ID for the client. The
1956 new client ID is sent to the client after changing the nickname. */
1958 SILC_SERVER_CMD_FUNC(nick)
1960 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1961 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1962 SilcServer server = cmd->server;
1963 SilcBuffer packet, nidp, oidp = NULL;
1964 SilcClientID *new_id;
1967 uint16 ident = silc_command_get_ident(cmd->payload);
1970 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1973 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
1975 /* Check nickname */
1976 nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
1979 if (silc_server_name_bad_chars(nick, nick_len) == TRUE) {
1980 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1981 SILC_STATUS_ERR_BAD_NICKNAME);
1985 /* Check for same nickname */
1986 if (!strcmp(client->nickname, nick)) {
1987 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1991 /* Create new Client ID */
1992 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
1994 cmd->server->md5hash, nick,
1997 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2000 /* Send notify about nickname change to our router. We send the new
2001 ID and ask to replace it with the old one. If we are router the
2002 packet is broadcasted. Send NICK_CHANGE notify. */
2003 if (!server->standalone)
2004 silc_server_send_notify_nick_change(server, server->router->connection,
2005 server->server_type == SILC_SERVER ?
2006 FALSE : TRUE, client->id,
2009 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2011 /* Remove old cache entry */
2012 silc_idcache_del_by_context(server->local_list->clients, client);
2015 silc_free(client->id);
2017 /* Save the nickname as this client is our local client */
2018 silc_free(client->nickname);
2020 client->nickname = strdup(nick);
2021 client->id = new_id;
2023 /* Update client cache */
2024 silc_idcache_add(server->local_list->clients, client->nickname,
2025 client->id, (void *)client, 0, NULL);
2027 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2029 /* Send NICK_CHANGE notify to the client's channels */
2030 silc_server_send_notify_on_channels(server, NULL, client,
2031 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
2032 oidp->data, oidp->len,
2033 nidp->data, nidp->len);
2036 /* Send the new Client ID as reply command back to client */
2037 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
2038 SILC_STATUS_OK, ident, 1,
2039 2, nidp->data, nidp->len);
2040 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2041 0, packet->data, packet->len, FALSE);
2043 silc_buffer_free(packet);
2044 silc_buffer_free(nidp);
2046 silc_buffer_free(oidp);
2049 silc_server_command_free(cmd);
2052 /* Sends the LIST command reply */
2055 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2056 SilcChannelEntry *lch,
2058 SilcChannelEntry *gch,
2062 SilcBuffer packet, idp;
2063 SilcChannelEntry entry;
2064 SilcCommandStatus status;
2065 uint16 ident = silc_command_get_ident(cmd->payload);
2067 unsigned char usercount[4];
2069 int valid_lcount = 0, valid_rcount = 0;
2071 for (i = 0; i < lch_count; i++) {
2072 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2077 for (i = 0; i < gch_count; i++) {
2078 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2084 status = SILC_STATUS_OK;
2085 if ((lch_count + gch_count) > 1)
2086 status = SILC_STATUS_LIST_START;
2089 for (i = 0, k = 0; i < lch_count; i++) {
2095 status = SILC_STATUS_LIST_ITEM;
2096 if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
2097 status = SILC_STATUS_LIST_END;
2099 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2101 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2102 topic = "*private*";
2103 memset(usercount, 0, sizeof(usercount));
2105 topic = entry->topic;
2106 users = silc_hash_table_count(entry->user_list);
2107 SILC_PUT32_MSB(users, usercount);
2110 /* Send the reply */
2112 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2114 2, idp->data, idp->len,
2115 3, entry->channel_name,
2116 strlen(entry->channel_name),
2117 4, topic, topic ? strlen(topic) : 0,
2119 silc_server_packet_send(cmd->server, cmd->sock,
2120 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2121 packet->len, FALSE);
2122 silc_buffer_free(packet);
2123 silc_buffer_free(idp);
2128 for (i = 0, k = 0; i < gch_count; i++) {
2134 status = SILC_STATUS_LIST_ITEM;
2135 if (valid_rcount > 1 && k == valid_rcount - 1)
2136 status = SILC_STATUS_LIST_END;
2138 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2140 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2141 topic = "*private*";
2142 memset(usercount, 0, sizeof(usercount));
2144 topic = entry->topic;
2145 users = silc_hash_table_count(entry->user_list);
2146 SILC_PUT32_MSB(users, usercount);
2149 /* Send the reply */
2151 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2153 2, idp->data, idp->len,
2154 3, entry->channel_name,
2155 strlen(entry->channel_name),
2156 4, topic, topic ? strlen(topic) : 0,
2158 silc_server_packet_send(cmd->server, cmd->sock,
2159 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2160 packet->len, FALSE);
2161 silc_buffer_free(packet);
2162 silc_buffer_free(idp);
2167 /* Server side of LIST command. This lists the channel of the requested
2168 server. Secret channels are not listed. */
2170 SILC_SERVER_CMD_FUNC(list)
2172 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2173 SilcServer server = cmd->server;
2174 SilcChannelID *channel_id = NULL;
2177 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2178 uint32 lch_count = 0, gch_count = 0;
2180 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2182 /* If we are normal server, send the command to router, since we
2183 want to know all channels in the network. */
2184 if (!cmd->pending && server->server_type == SILC_SERVER &&
2185 !server->standalone) {
2189 old_ident = silc_command_get_ident(cmd->payload);
2190 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2191 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2192 silc_server_packet_send(server, server->router->connection,
2193 SILC_PACKET_COMMAND, cmd->packet->flags,
2194 tmpbuf->data, tmpbuf->len, TRUE);
2196 /* Reprocess this packet after received reply from router */
2197 silc_server_command_pending(server, SILC_COMMAND_LIST,
2198 silc_command_get_ident(cmd->payload),
2199 silc_server_command_list,
2200 silc_server_command_dup(cmd));
2201 cmd->pending = TRUE;
2202 silc_command_set_ident(cmd->payload, old_ident);
2203 silc_buffer_free(tmpbuf);
2207 /* Get Channel ID */
2208 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2210 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2212 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2213 SILC_STATUS_ERR_NO_CHANNEL_ID);
2218 /* Get the channels from local list */
2219 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2222 /* Get the channels from global list */
2223 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2226 /* Send the reply */
2227 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2228 gchannels, gch_count);
2230 silc_free(lchannels);
2231 silc_free(gchannels);
2234 silc_server_command_free(cmd);
2237 /* Server side of TOPIC command. Sets topic for channel and/or returns
2238 current topic to client. */
2240 SILC_SERVER_CMD_FUNC(topic)
2242 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2243 SilcServer server = cmd->server;
2244 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2245 SilcChannelID *channel_id;
2246 SilcChannelEntry channel;
2247 SilcChannelClientEntry chl;
2248 SilcBuffer packet, idp;
2250 uint32 argc, tmp_len;
2251 uint16 ident = silc_command_get_ident(cmd->payload);
2253 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2255 argc = silc_argument_get_arg_num(cmd->args);
2257 /* Get Channel ID */
2258 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2260 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2261 SILC_STATUS_ERR_NO_CHANNEL_ID);
2264 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2266 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2267 SILC_STATUS_ERR_NO_CHANNEL_ID);
2271 /* Check whether the channel exists */
2272 channel = silc_idlist_find_channel_by_id(server->local_list,
2275 channel = silc_idlist_find_channel_by_id(server->global_list,
2278 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2279 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2286 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2288 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2289 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2293 if (strlen(tmp) > 256) {
2294 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2295 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2299 /* See whether the client is on channel and has rights to change topic */
2300 if (!silc_hash_table_find(channel->user_list, client, NULL,
2302 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2303 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2307 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2308 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2309 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2310 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2315 /* Set the topic for channel */
2316 silc_free(channel->topic);
2317 channel->topic = strdup(tmp);
2319 /* Send TOPIC_SET notify type to the network */
2320 if (!server->standalone)
2321 silc_server_send_notify_topic_set(server, server->router->connection,
2322 server->server_type == SILC_ROUTER ?
2323 TRUE : FALSE, channel,
2324 client->id, SILC_ID_CLIENT,
2327 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2329 /* Send notify about topic change to all clients on the channel */
2330 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2331 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2332 idp->data, idp->len,
2333 channel->topic, strlen(channel->topic));
2334 silc_buffer_free(idp);
2337 /* Send the topic to client as reply packet */
2338 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2339 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2340 SILC_STATUS_OK, ident, 2,
2341 2, idp->data, idp->len,
2344 strlen(channel->topic) : 0);
2345 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2346 0, packet->data, packet->len, FALSE);
2348 silc_buffer_free(packet);
2349 silc_buffer_free(idp);
2350 silc_free(channel_id);
2353 silc_server_command_free(cmd);
2356 /* Server side of INVITE command. Invites some client to join some channel.
2357 This command is also used to manage the invite list of the channel. */
2359 SILC_SERVER_CMD_FUNC(invite)
2361 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2362 SilcServer server = cmd->server;
2363 SilcSocketConnection sock = cmd->sock, dest_sock;
2364 SilcChannelClientEntry chl;
2365 SilcClientEntry sender, dest;
2366 SilcClientID *dest_id = NULL;
2367 SilcChannelEntry channel;
2368 SilcChannelID *channel_id = NULL;
2369 SilcIDListData idata;
2370 SilcBuffer idp, idp2, packet;
2371 unsigned char *tmp, *add, *del;
2373 uint16 ident = silc_command_get_ident(cmd->payload);
2375 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2377 /* Get Channel ID */
2378 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2380 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2381 SILC_STATUS_ERR_NO_CHANNEL_ID);
2384 channel_id = silc_id_payload_parse_id(tmp, len);
2386 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2387 SILC_STATUS_ERR_NO_CHANNEL_ID);
2391 /* Get the channel entry */
2392 channel = silc_idlist_find_channel_by_id(server->local_list,
2395 channel = silc_idlist_find_channel_by_id(server->global_list,
2398 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2399 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2404 /* Check whether the sender of this command is on the channel. */
2405 sender = (SilcClientEntry)sock->user_data;
2406 if (!silc_server_client_on_channel(sender, channel)) {
2407 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2408 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2412 /* Check whether the channel is invite-only channel. If yes then the
2413 sender of this command must be at least channel operator. */
2414 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2415 silc_hash_table_find(channel->user_list, sender, NULL, (void *)&chl);
2416 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2417 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2418 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2423 /* Get destination client ID */
2424 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2428 dest_id = silc_id_payload_parse_id(tmp, len);
2430 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2431 SILC_STATUS_ERR_NO_CLIENT_ID);
2435 /* Get the client entry */
2436 dest = silc_server_get_client_resolve(server, dest_id);
2438 if (server->server_type != SILC_SERVER) {
2439 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2440 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2444 /* The client info is being resolved. Reprocess this packet after
2445 receiving the reply to the query. */
2446 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2448 silc_server_command_invite,
2449 silc_server_command_dup(cmd));
2450 cmd->pending = TRUE;
2451 silc_free(channel_id);
2456 /* Check whether the requested client is already on the channel. */
2457 if (silc_server_client_on_channel(dest, channel)) {
2458 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2459 SILC_STATUS_ERR_USER_ON_CHANNEL);
2463 /* Get route to the client */
2464 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2466 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2467 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2471 memset(invite, 0, sizeof(invite));
2472 strncat(invite, dest->nickname, strlen(dest->nickname));
2473 strncat(invite, "!", 1);
2474 strncat(invite, dest->username, strlen(dest->username));
2475 if (!strchr(dest->username, '@')) {
2476 strncat(invite, "@", 1);
2477 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2480 len = strlen(invite);
2481 if (!channel->invite_list)
2482 channel->invite_list = silc_calloc(len + 2,
2483 sizeof(*channel->invite_list));
2485 channel->invite_list = silc_realloc(channel->invite_list,
2486 sizeof(*channel->invite_list) *
2488 strlen(channel->invite_list) + 2));
2489 strncat(channel->invite_list, invite, len);
2490 strncat(channel->invite_list, ",", 1);
2492 /* Send notify to the client that is invited to the channel */
2493 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2494 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2495 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2497 SILC_NOTIFY_TYPE_INVITE, 3,
2498 idp->data, idp->len,
2499 channel->channel_name,
2500 strlen(channel->channel_name),
2501 idp2->data, idp2->len);
2502 silc_buffer_free(idp);
2503 silc_buffer_free(idp2);
2506 /* Add the client to the invite list of the channel */
2507 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2509 if (!channel->invite_list)
2510 channel->invite_list = silc_calloc(len + 2,
2511 sizeof(*channel->invite_list));
2513 channel->invite_list = silc_realloc(channel->invite_list,
2514 sizeof(*channel->invite_list) *
2516 strlen(channel->invite_list) + 2));
2517 if (add[len - 1] == ',')
2518 add[len - 1] = '\0';
2520 strncat(channel->invite_list, add, len);
2521 strncat(channel->invite_list, ",", 1);
2524 /* Get the invite to be removed and remove it from the list */
2525 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2526 if (del && channel->invite_list) {
2527 char *start, *end, *n;
2529 if (!strncmp(channel->invite_list, del,
2530 strlen(channel->invite_list) - 1)) {
2531 silc_free(channel->invite_list);
2532 channel->invite_list = NULL;
2534 start = strstr(channel->invite_list, del);
2535 if (start && strlen(start) >= len) {
2537 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2538 strncat(n, channel->invite_list, start - channel->invite_list);
2539 strncat(n, end + 1, ((channel->invite_list +
2540 strlen(channel->invite_list)) - end) - 1);
2541 silc_free(channel->invite_list);
2542 channel->invite_list = n;
2547 /* Send notify to the primary router */
2548 if (!server->standalone)
2549 silc_server_send_notify_invite(server, server->router->connection,
2550 server->server_type == SILC_ROUTER ?
2551 TRUE : FALSE, channel,
2552 sender->id, add, del);
2554 /* Send command reply */
2555 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2559 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2560 SILC_STATUS_OK, ident, 2,
2562 3, channel->invite_list,
2563 channel->invite_list ?
2564 strlen(channel->invite_list) : 0);
2567 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2568 SILC_STATUS_OK, ident, 1,
2570 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2571 packet->data, packet->len, FALSE);
2572 silc_buffer_free(packet);
2576 silc_free(channel_id);
2577 silc_server_command_free(cmd);
2582 SilcSocketConnection sock;
2586 /* Quits connection to client. This gets called if client won't
2587 close the connection even when it has issued QUIT command. */
2589 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2591 QuitInternal q = (QuitInternal)context;
2593 /* Free all client specific data, such as client entry and entires
2594 on channels this client may be on. */
2595 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2597 q->sock->user_data = NULL;
2599 /* Close the connection on our side */
2600 silc_server_close_connection(q->server, q->sock);
2602 silc_free(q->signoff);
2606 /* Quits SILC session. This is the normal way to disconnect client. */
2608 SILC_SERVER_CMD_FUNC(quit)
2610 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2611 SilcServer server = cmd->server;
2612 SilcSocketConnection sock = cmd->sock;
2614 unsigned char *tmp = NULL;
2617 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2619 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2622 /* Get destination ID */
2623 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2627 q = silc_calloc(1, sizeof(*q));
2630 q->signoff = tmp ? strdup(tmp) : NULL;
2632 /* We quit the connection with little timeout */
2633 silc_schedule_task_add(server->schedule, sock->sock,
2634 silc_server_command_quit_cb, (void *)q,
2635 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2638 silc_server_command_free(cmd);
2641 /* Server side of command KILL. This command is used by router operator
2642 to remove an client from the SILC Network temporarily. */
2644 SILC_SERVER_CMD_FUNC(kill)
2646 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2647 SilcServer server = cmd->server;
2648 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2649 SilcClientEntry remote_client;
2650 SilcClientID *client_id;
2651 unsigned char *tmp, *comment;
2652 uint32 tmp_len, tmp_len2;
2654 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2656 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2659 /* KILL command works only on router */
2660 if (server->server_type != SILC_ROUTER) {
2661 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2662 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2666 /* Check whether client has the permissions. */
2667 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2668 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2669 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2673 /* Get the client ID */
2674 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2676 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2677 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2680 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2682 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2683 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2687 /* Get the client entry */
2688 remote_client = silc_idlist_find_client_by_id(server->local_list,
2689 client_id, TRUE, NULL);
2690 if (!remote_client) {
2691 remote_client = silc_idlist_find_client_by_id(server->global_list,
2692 client_id, TRUE, NULL);
2693 if (!remote_client) {
2694 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2695 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2701 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2705 /* Send reply to the sender */
2706 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2709 /* Send the KILL notify packets. First send it to the channel, then
2710 to our primary router and then directly to the client who is being
2711 killed right now. */
2713 /* Send KILLED notify to the channels. It is not sent to the client
2714 as it will be sent differently destined directly to the client and not
2716 silc_server_send_notify_on_channels(server, remote_client,
2717 remote_client, SILC_NOTIFY_TYPE_KILLED,
2720 comment, comment ? tmp_len2 : 0);
2722 /* Send KILLED notify to primary route */
2723 if (!server->standalone)
2724 silc_server_send_notify_killed(server, server->router->connection, TRUE,
2725 remote_client->id, comment);
2727 /* Send KILLED notify to the client directly */
2728 silc_server_send_notify_killed(server, remote_client->connection ?
2729 remote_client->connection :
2730 remote_client->router->connection, FALSE,
2731 remote_client->id, comment);
2733 /* Remove the client from all channels. This generates new keys to the
2734 channels as well. */
2735 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2738 /* Remove the client entry, If it is locally connected then we will also
2739 disconnect the client here */
2740 if (remote_client->connection) {
2741 /* Remove locally conneted client */
2742 SilcSocketConnection sock = remote_client->connection;
2743 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2744 silc_server_close_connection(server, sock);
2746 /* Remove remote client */
2747 if (!silc_idlist_del_client(server->global_list, remote_client))
2748 silc_idlist_del_client(server->local_list, remote_client);
2752 silc_server_command_free(cmd);
2755 /* Server side of command INFO. This sends information about us to
2756 the client. If client requested specific server we will send the
2757 command to that server. */
2759 SILC_SERVER_CMD_FUNC(info)
2761 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2762 SilcServer server = cmd->server;
2763 SilcBuffer packet, idp;
2766 char *dest_server, *server_info = NULL, *server_name;
2767 uint16 ident = silc_command_get_ident(cmd->payload);
2768 SilcServerEntry entry = NULL;
2769 SilcServerID *server_id = NULL;
2771 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2773 /* Get server name */
2774 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2777 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2779 server_id = silc_id_payload_parse_id(tmp, tmp_len);
2781 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2782 SILC_STATUS_ERR_NO_SERVER_ID);
2788 /* Check whether we have this server cached */
2789 entry = silc_idlist_find_server_by_id(server->local_list,
2790 server_id, TRUE, NULL);
2792 entry = silc_idlist_find_server_by_id(server->global_list,
2793 server_id, TRUE, NULL);
2794 if (!entry && server->server_type != SILC_SERVER) {
2795 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2796 SILC_STATUS_ERR_NO_SUCH_SERVER);
2802 /* Some buggy servers has sent request to router about themselves. */
2803 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2806 if ((!dest_server && !server_id && !entry) || (entry &&
2807 entry == server->id_entry) ||
2808 (dest_server && !cmd->pending &&
2809 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2810 /* Send our reply */
2811 char info_string[256];
2813 memset(info_string, 0, sizeof(info_string));
2814 snprintf(info_string, sizeof(info_string),
2815 "location: %s server: %s admin: %s <%s>",
2816 server->config->admin_info->location,
2817 server->config->admin_info->server_type,
2818 server->config->admin_info->admin_name,
2819 server->config->admin_info->admin_email);
2821 server_info = info_string;
2822 entry = server->id_entry;
2824 /* Check whether we have this server cached */
2825 if (!entry && dest_server) {
2826 entry = silc_idlist_find_server_by_name(server->global_list,
2827 dest_server, TRUE, NULL);
2829 entry = silc_idlist_find_server_by_name(server->local_list,
2830 dest_server, TRUE, NULL);
2834 if (!cmd->pending &&
2835 server->server_type != SILC_SERVER && entry && !entry->server_info) {
2836 /* Send to the server */
2840 old_ident = silc_command_get_ident(cmd->payload);
2841 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2842 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2844 silc_server_packet_send(server, entry->connection,
2845 SILC_PACKET_COMMAND, cmd->packet->flags,
2846 tmpbuf->data, tmpbuf->len, TRUE);
2848 /* Reprocess this packet after received reply from router */
2849 silc_server_command_pending(server, SILC_COMMAND_INFO,
2850 silc_command_get_ident(cmd->payload),
2851 silc_server_command_info,
2852 silc_server_command_dup(cmd));
2853 cmd->pending = TRUE;
2854 silc_command_set_ident(cmd->payload, old_ident);
2855 silc_buffer_free(tmpbuf);
2859 if (!entry && !cmd->pending && !server->standalone) {
2860 /* Send to the primary router */
2864 old_ident = silc_command_get_ident(cmd->payload);
2865 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2866 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2868 silc_server_packet_send(server, server->router->connection,
2869 SILC_PACKET_COMMAND, cmd->packet->flags,
2870 tmpbuf->data, tmpbuf->len, TRUE);
2872 /* Reprocess this packet after received reply from router */
2873 silc_server_command_pending(server, SILC_COMMAND_INFO,
2874 silc_command_get_ident(cmd->payload),
2875 silc_server_command_info,
2876 silc_server_command_dup(cmd));
2877 cmd->pending = TRUE;
2878 silc_command_set_ident(cmd->payload, old_ident);
2879 silc_buffer_free(tmpbuf);
2884 silc_free(server_id);
2887 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2888 SILC_STATUS_ERR_NO_SUCH_SERVER);
2892 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2894 server_info = entry->server_info;
2895 server_name = entry->server_name;
2897 /* Send the reply */
2898 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2899 SILC_STATUS_OK, ident, 3,
2900 2, idp->data, idp->len,
2902 strlen(server_name),
2905 strlen(server_info) : 0);
2906 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2907 packet->data, packet->len, FALSE);
2909 silc_buffer_free(packet);
2910 silc_buffer_free(idp);
2913 silc_server_command_free(cmd);
2916 /* Server side of command PING. This just replies to the ping. */
2918 SILC_SERVER_CMD_FUNC(ping)
2920 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2921 SilcServer server = cmd->server;
2926 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
2929 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2931 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2932 SILC_STATUS_ERR_NO_SERVER_ID);
2935 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2939 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2940 /* Send our reply */
2941 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2944 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2945 SILC_STATUS_ERR_NO_SUCH_SERVER);
2952 silc_server_command_free(cmd);
2955 /* Internal routine to join channel. The channel sent to this function
2956 has been either created or resolved from ID lists. This joins the sent
2957 client to the channel. */
2959 static void silc_server_command_join_channel(SilcServer server,
2960 SilcServerCommandContext cmd,
2961 SilcChannelEntry channel,
2962 SilcClientID *client_id,
2966 const unsigned char *auth,
2969 SilcSocketConnection sock = cmd->sock;
2971 uint32 tmp_len, user_count;
2972 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
2973 SilcClientEntry client;
2974 SilcChannelClientEntry chl;
2975 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
2976 uint16 ident = silc_command_get_ident(cmd->payload);
2977 char check[512], check2[512];
2978 bool founder = FALSE;
2980 SILC_LOG_DEBUG(("Start"));
2985 /* Get the client entry */
2986 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2987 client = (SilcClientEntry)sock->user_data;
2989 client = silc_server_get_client_resolve(server, client_id);
2994 /* The client info is being resolved. Reprocess this packet after
2995 receiving the reply to the query. */
2996 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2998 silc_server_command_join,
2999 silc_server_command_dup(cmd));
3000 cmd->pending = TRUE;
3004 cmd->pending = FALSE;
3008 * Check founder auth payload if provided. If client can gain founder
3009 * privileges it can override various conditions on joining the channel,
3010 * and can have directly the founder mode set on the channel.
3012 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3013 SilcIDListData idata = (SilcIDListData)client;
3015 if (channel->founder_key && idata->public_key &&
3016 silc_pkcs_public_key_compare(channel->founder_key,
3017 idata->public_key)) {
3018 void *auth_data = (channel->founder_method == SILC_AUTH_PASSWORD ?
3019 (void *)channel->founder_passwd :
3020 (void *)channel->founder_key);
3021 uint32 auth_data_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
3022 channel->founder_passwd_len : 0);
3024 /* Check whether the client is to become founder */
3025 if (silc_auth_verify_data(auth, auth_len, channel->founder_method,
3026 auth_data, auth_data_len,
3027 idata->hash, client->id, SILC_ID_CLIENT)) {
3028 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3035 * Check channel modes
3039 memset(check, 0, sizeof(check));
3040 memset(check2, 0, sizeof(check2));
3041 strncat(check, client->nickname, strlen(client->nickname));
3042 strncat(check, "!", 1);
3043 strncat(check, client->username, strlen(client->username));
3044 if (!strchr(client->username, '@')) {
3045 strncat(check, "@", 1);
3046 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3049 strncat(check2, client->nickname, strlen(client->nickname));
3050 if (!strchr(client->nickname, '@')) {
3051 strncat(check2, "@", 1);
3052 strncat(check2, server->server_name, strlen(server->server_name));
3054 strncat(check2, "!", 1);
3055 strncat(check2, client->username, strlen(client->username));
3056 if (!strchr(client->username, '@')) {
3057 strncat(check2, "@", 1);
3058 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3061 /* Check invite list if channel is invite-only channel */
3062 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3063 if (!channel->invite_list ||
3064 (!silc_string_match(channel->invite_list, check) &&
3065 !silc_string_match(channel->invite_list, check2))) {
3066 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3067 SILC_STATUS_ERR_NOT_INVITED);
3072 /* Check ban list if it exists. If the client's nickname, server,
3073 username and/or hostname is in the ban list the access to the
3074 channel is denied. */
3075 if (channel->ban_list) {
3076 if (silc_string_match(channel->ban_list, check) ||
3077 silc_string_match(channel->ban_list, check2)) {
3078 silc_server_command_send_status_reply(
3079 cmd, SILC_COMMAND_JOIN,
3080 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
3085 /* Check user count limit if set. */
3086 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3087 if (silc_hash_table_count(channel->user_list) + 1 >
3088 channel->user_limit) {
3089 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3090 SILC_STATUS_ERR_CHANNEL_IS_FULL);
3096 /* Check the channel passphrase if set. */
3097 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3098 /* Get passphrase */
3099 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3101 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
3102 memcpy(passphrase, tmp, tmp_len);
3105 if (!passphrase || !channel->passphrase ||
3106 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3107 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3108 SILC_STATUS_ERR_BAD_PASSWORD);
3114 * Client is allowed to join to the channel. Make it happen.
3117 /* Check whether the client already is on the channel */
3118 if (silc_server_client_on_channel(client, channel)) {
3119 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3120 SILC_STATUS_ERR_USER_ON_CHANNEL);
3124 /* Generate new channel key as protocol dictates */
3126 if (!silc_server_create_channel_key(server, channel, 0))
3129 /* Send the channel key. This is broadcasted to the channel but is not
3130 sent to the client who is joining to the channel. */
3131 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3132 silc_server_send_channel_key(server, NULL, channel,
3133 server->server_type == SILC_ROUTER ?
3134 FALSE : !server->standalone);
3137 /* Join the client to the channel by adding it to channel's user list.
3138 Add also the channel to client entry's channels list for fast cross-
3140 chl = silc_calloc(1, sizeof(*chl));
3142 chl->client = client;
3143 chl->channel = channel;
3144 silc_hash_table_add(channel->user_list, client, chl);
3145 silc_hash_table_add(client->channels, channel, chl);
3147 /* Get users on the channel */
3148 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3151 /* Encode Client ID Payload of the original client who wants to join */
3152 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3154 /* Encode command reply packet */
3155 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3156 SILC_PUT32_MSB(channel->mode, mode);
3157 SILC_PUT32_MSB(created, tmp2);
3158 SILC_PUT32_MSB(user_count, tmp3);
3160 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3161 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3162 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
3163 strlen(channel->channel_key->
3165 channel->channel_key->cipher->name,
3166 channel->key_len / 8, channel->key);
3171 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3172 SILC_STATUS_OK, ident, 13,
3173 2, channel->channel_name,
3174 strlen(channel->channel_name),
3175 3, chidp->data, chidp->len,
3176 4, clidp->data, clidp->len,
3179 7, keyp ? keyp->data : NULL,
3180 keyp ? keyp->len : 0,
3181 8, channel->ban_list,
3183 strlen(channel->ban_list) : 0,
3184 9, channel->invite_list,
3185 channel->invite_list ?
3186 strlen(channel->invite_list) : 0,
3189 strlen(channel->topic) : 0,
3190 11, silc_hmac_get_name(channel->hmac),
3191 strlen(silc_hmac_get_name(channel->
3194 13, user_list->data, user_list->len,
3195 14, mode_list->data,
3198 /* Send command reply */
3199 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3200 reply->data, reply->len, FALSE);
3202 /* Send JOIN notify to locally connected clients on the channel. If
3203 we are normal server then router will send or have sent JOIN notify
3204 already. However since we've added the client already to our channel
3205 we'll ignore it (in packet_receive.c) so we must send it here. If
3206 we are router then this will send it to local clients and local
3208 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3209 SILC_NOTIFY_TYPE_JOIN, 2,
3210 clidp->data, clidp->len,
3211 chidp->data, chidp->len);
3213 if (!cmd->pending) {
3214 /* Send JOIN notify packet to our primary router */
3215 if (!server->standalone)
3216 silc_server_send_notify_join(server, server->router->connection,
3217 server->server_type == SILC_ROUTER ?
3218 TRUE : FALSE, channel, client->id);
3221 /* Distribute the channel key to all backup routers. */
3222 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3223 keyp->data, keyp->len, FALSE, TRUE);
3225 /* If client became founder by providing correct founder auth data
3226 notify the mode change to the channel. */
3228 SILC_PUT32_MSB(chl->mode, mode);
3229 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3230 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3231 clidp->data, clidp->len,
3232 mode, 4, clidp->data, clidp->len);
3234 /* Set CUMODE notify type to network */
3235 if (!server->standalone)
3236 silc_server_send_notify_cumode(server, server->router->connection,
3237 server->server_type == SILC_ROUTER ?
3238 TRUE : FALSE, channel,
3239 chl->mode, client->id, SILC_ID_CLIENT,
3244 silc_buffer_free(reply);
3245 silc_buffer_free(clidp);
3246 silc_buffer_free(chidp);
3247 silc_buffer_free(keyp);
3248 silc_buffer_free(user_list);
3249 silc_buffer_free(mode_list);
3252 silc_free(passphrase);
3255 /* Server side of command JOIN. Joins client into requested channel. If
3256 the channel does not exist it will be created. */
3258 SILC_SERVER_CMD_FUNC(join)
3260 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3261 SilcServer server = cmd->server;
3262 unsigned char *auth;
3263 uint32 tmp_len, auth_len;
3264 char *tmp, *channel_name = NULL, *cipher, *hmac;
3265 SilcChannelEntry channel;
3267 bool created = FALSE, create_key = TRUE;
3268 SilcClientID *client_id;
3270 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3272 /* Get channel name */
3273 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3275 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3276 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3282 channel_name[255] = '\0';
3284 if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
3285 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3286 SILC_STATUS_ERR_BAD_CHANNEL);
3290 /* Get Client ID of the client who is joining to the channel */
3291 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3293 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3294 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3297 client_id = silc_id_payload_parse_id(tmp, tmp_len);
3299 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3300 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3304 /* Get cipher, hmac name and auth payload */
3305 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3306 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3307 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3309 /* See if the channel exists */
3310 channel = silc_idlist_find_channel_by_name(server->local_list,
3311 channel_name, NULL);
3313 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3314 /* If this is coming from client the Client ID in the command packet must
3315 be same as the client's ID. */
3316 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3317 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3318 if (!SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
3319 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3320 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3325 if (!channel || channel->disabled) {
3326 /* Channel not found */
3328 /* If we are standalone server we don't have a router, we just create
3329 the channel by ourselves. */
3330 if (server->standalone) {
3331 channel = silc_server_create_new_channel(server, server->id, cipher,
3332 hmac, channel_name, TRUE);
3334 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3335 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3339 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3345 /* The channel does not exist on our server. If we are normal server
3346 we will send JOIN command to our router which will handle the
3347 joining procedure (either creates the channel if it doesn't exist
3348 or joins the client to it). */
3349 if (server->server_type != SILC_ROUTER) {
3353 /* If this is pending command callback then we've resolved
3354 it and it didn't work, return since we've notified the
3355 client already in the command reply callback. */
3359 old_ident = silc_command_get_ident(cmd->payload);
3360 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3361 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3363 /* Send JOIN command to our router */
3364 silc_server_packet_send(server, (SilcSocketConnection)
3365 server->router->connection,
3366 SILC_PACKET_COMMAND, cmd->packet->flags,
3367 tmpbuf->data, tmpbuf->len, TRUE);
3369 /* Reprocess this packet after received reply from router */
3370 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3371 silc_command_get_ident(cmd->payload),
3372 silc_server_command_join,
3373 silc_server_command_dup(cmd));
3374 cmd->pending = TRUE;
3378 /* We are router and the channel does not seem exist so we will check
3379 our global list as well for the channel. */
3380 channel = silc_idlist_find_channel_by_name(server->global_list,
3381 channel_name, NULL);
3383 /* Channel really does not exist, create it */
3384 channel = silc_server_create_new_channel(server, server->id, cipher,
3385 hmac, channel_name, TRUE);
3387 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3388 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3392 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3400 /* Channel not found */
3402 /* If the command came from router and we are normal server then
3403 something went wrong with the joining as the channel was not found.
3404 We can't do anything else but ignore this. */
3405 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3406 server->server_type != SILC_ROUTER)
3409 /* We are router and the channel does not seem exist so we will check
3410 our global list as well for the channel. */
3411 channel = silc_idlist_find_channel_by_name(server->global_list,
3412 channel_name, NULL);
3414 /* Channel really does not exist, create it */
3415 channel = silc_server_create_new_channel(server, server->id, cipher,
3416 hmac, channel_name, TRUE);
3418 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3419 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3423 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3430 /* Check whether the channel was created by our router */
3431 if (cmd->pending && context2) {
3432 SilcServerCommandReplyContext reply =
3433 (SilcServerCommandReplyContext)context2;
3435 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3436 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3437 SILC_GET32_MSB(created, tmp);
3438 create_key = FALSE; /* Router returned the key already */
3441 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS)
3445 /* If the channel does not have global users and is also empty the client
3446 will be the channel founder and operator. */
3447 if (!channel->global_users && !silc_hash_table_count(channel->user_list))
3448 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3450 /* Join to the channel */
3451 silc_server_command_join_channel(server, cmd, channel, client_id,
3452 created, create_key, umode,
3455 silc_free(client_id);
3458 silc_server_command_free(cmd);
3461 /* Server side of command MOTD. Sends server's current "message of the
3462 day" to the client. */
3464 SILC_SERVER_CMD_FUNC(motd)
3466 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3467 SilcServer server = cmd->server;
3468 SilcBuffer packet, idp;
3469 char *motd, *dest_server;
3471 uint16 ident = silc_command_get_ident(cmd->payload);
3473 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3475 /* Get server name */
3476 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3478 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3479 SILC_STATUS_ERR_NO_SUCH_SERVER);
3483 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3486 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3488 if (server->config && server->config->motd &&
3489 server->config->motd->motd_file) {
3491 motd = silc_file_readfile(server->config->motd->motd_file, &motd_len);
3496 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3497 SILC_STATUS_OK, ident, 2,
3502 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3503 SILC_STATUS_OK, ident, 1,
3507 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3508 packet->data, packet->len, FALSE);
3509 silc_buffer_free(packet);
3510 silc_buffer_free(idp);
3512 SilcServerEntry entry;
3514 /* Check whether we have this server cached */
3515 entry = silc_idlist_find_server_by_name(server->global_list,
3516 dest_server, TRUE, NULL);
3518 entry = silc_idlist_find_server_by_name(server->local_list,
3519 dest_server, TRUE, NULL);
3522 if (server->server_type != SILC_SERVER && !cmd->pending &&
3523 entry && !entry->motd) {
3524 /* Send to the server */
3528 old_ident = silc_command_get_ident(cmd->payload);
3529 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3530 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3532 silc_server_packet_send(server, entry->connection,
3533 SILC_PACKET_COMMAND, cmd->packet->flags,
3534 tmpbuf->data, tmpbuf->len, TRUE);
3536 /* Reprocess this packet after received reply from router */
3537 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3538 silc_command_get_ident(cmd->payload),
3539 silc_server_command_motd,
3540 silc_server_command_dup(cmd));
3541 cmd->pending = TRUE;
3542 silc_command_set_ident(cmd->payload, old_ident);
3543 silc_buffer_free(tmpbuf);
3547 if (!entry && !cmd->pending && !server->standalone) {
3548 /* Send to the primary router */
3552 old_ident = silc_command_get_ident(cmd->payload);
3553 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3554 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3556 silc_server_packet_send(server, server->router->connection,
3557 SILC_PACKET_COMMAND, cmd->packet->flags,
3558 tmpbuf->data, tmpbuf->len, TRUE);
3560 /* Reprocess this packet after received reply from router */
3561 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3562 silc_command_get_ident(cmd->payload),
3563 silc_server_command_motd,
3564 silc_server_command_dup(cmd));
3565 cmd->pending = TRUE;
3566 silc_command_set_ident(cmd->payload, old_ident);
3567 silc_buffer_free(tmpbuf);
3572 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3573 SILC_STATUS_ERR_NO_SUCH_SERVER);
3577 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3578 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3579 SILC_STATUS_OK, ident, 2,
3583 strlen(entry->motd) : 0);
3584 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3585 packet->data, packet->len, FALSE);
3586 silc_buffer_free(packet);
3587 silc_buffer_free(idp);
3591 silc_server_command_free(cmd);
3594 /* Server side of command UMODE. Client can use this command to set/unset
3595 user mode. Client actually cannot set itself to be as server/router
3596 operator so this can be used only to unset the modes. */
3598 SILC_SERVER_CMD_FUNC(umode)
3600 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3601 SilcServer server = cmd->server;
3602 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3604 unsigned char *tmp_mask;
3606 uint16 ident = silc_command_get_ident(cmd->payload);
3608 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3611 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 2, 2);
3613 /* Get the client's mode mask */
3614 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3616 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3617 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3620 SILC_GET32_MSB(mask, tmp_mask);
3626 if (mask & SILC_UMODE_SERVER_OPERATOR) {
3627 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR)) {
3628 /* Cannot operator mode */
3629 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3630 SILC_STATUS_ERR_PERM_DENIED);
3634 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
3635 /* Remove the server operator rights */
3636 client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3639 if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3640 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
3641 /* Cannot operator mode */
3642 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3643 SILC_STATUS_ERR_PERM_DENIED);
3647 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
3648 /* Remove the router operator rights */
3649 client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3652 if (mask & SILC_UMODE_GONE) {
3653 client->mode |= SILC_UMODE_GONE;
3655 if (client->mode & SILC_UMODE_GONE)
3656 /* Remove the gone status */
3657 client->mode &= ~SILC_UMODE_GONE;
3660 /* Send UMODE change to primary router */
3661 if (!server->standalone)
3662 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3663 client->id, client->mode);
3665 /* Send command reply to sender */
3666 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3667 SILC_STATUS_OK, ident, 1,
3669 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3670 packet->data, packet->len, FALSE);
3671 silc_buffer_free(packet);
3674 silc_server_command_free(cmd);
3677 /* Checks that client has rights to add or remove channel modes. If any
3678 of the checks fails FALSE is returned. */
3680 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3681 SilcChannelClientEntry client,
3684 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3685 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3687 /* Check whether has rights to change anything */
3688 if (!is_op && !is_fo)
3691 /* Check whether has rights to change everything */
3695 /* We know that client is channel operator, check that they are not
3696 changing anything that requires channel founder rights. Rest of the
3697 modes are available automatically for channel operator. */
3699 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3700 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3701 if (is_op && !is_fo)
3704 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3705 if (is_op && !is_fo)
3710 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3711 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE))
3712 if (is_op && !is_fo)
3715 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3716 if (is_op && !is_fo)
3721 if (mode & SILC_CHANNEL_MODE_CIPHER) {
3722 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER))
3723 if (is_op && !is_fo)
3726 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3727 if (is_op && !is_fo)
3732 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3733 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH))
3734 if (is_op && !is_fo)
3737 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3738 if (is_op && !is_fo)
3746 /* Server side command of CMODE. Changes channel mode */
3748 SILC_SERVER_CMD_FUNC(cmode)
3750 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3751 SilcServer server = cmd->server;
3752 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3753 SilcIDListData idata = (SilcIDListData)client;
3754 SilcChannelID *channel_id;
3755 SilcChannelEntry channel;
3756 SilcChannelClientEntry chl;
3757 SilcBuffer packet, cidp;
3758 unsigned char *tmp, *tmp_id, *tmp_mask;
3759 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3760 uint32 mode_mask, tmp_len, tmp_len2;
3761 uint16 ident = silc_command_get_ident(cmd->payload);
3763 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 2, 7);
3765 /* Get Channel ID */
3766 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3768 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3769 SILC_STATUS_ERR_NO_CHANNEL_ID);
3772 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3774 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3775 SILC_STATUS_ERR_NO_CHANNEL_ID);
3779 /* Get the channel mode mask */
3780 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3782 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3783 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3786 SILC_GET32_MSB(mode_mask, tmp_mask);
3788 /* Get channel entry */
3789 channel = silc_idlist_find_channel_by_id(server->local_list,
3792 channel = silc_idlist_find_channel_by_id(server->global_list,
3795 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3796 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3801 /* Check whether this client is on the channel */
3802 if (!silc_server_client_on_channel(client, channel)) {
3803 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3804 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3808 /* Get entry to the channel user list */
3809 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
3811 /* Check that client has rights to change any requested channel modes */
3812 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3813 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3814 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3819 * Check the modes. Modes that requires nothing special operation are
3823 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3824 /* Channel uses private keys to protect traffic. Client(s) has set the
3825 key locally they want to use, server does not know that key. */
3826 /* Nothing interesting to do here */
3828 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3829 /* The mode is removed and we need to generate and distribute
3830 new channel key. Clients are not using private channel keys
3831 anymore after this. */
3833 /* Re-generate channel key */
3834 if (!silc_server_create_channel_key(server, channel, 0))
3837 /* Send the channel key. This sends it to our local clients and if
3838 we are normal server to our router as well. */
3839 silc_server_send_channel_key(server, NULL, channel,
3840 server->server_type == SILC_ROUTER ?
3841 FALSE : !server->standalone);
3843 cipher = channel->channel_key->cipher->name;
3844 hmac = (char *)silc_hmac_get_name(channel->hmac);
3848 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3849 /* User limit is set on channel */
3852 /* Get user limit */
3853 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3855 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3856 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3857 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3861 SILC_GET32_MSB(user_limit, tmp);
3862 channel->user_limit = user_limit;
3865 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3866 /* User limit mode is unset. Remove user limit */
3867 channel->user_limit = 0;
3870 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3871 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3872 /* Passphrase has been set to channel */
3874 /* Get the passphrase */
3875 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3877 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3878 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3882 /* Save the passphrase */
3883 passphrase = channel->passphrase = strdup(tmp);
3886 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3887 /* Passphrase mode is unset. remove the passphrase */
3888 if (channel->passphrase) {
3889 silc_free(channel->passphrase);
3890 channel->passphrase = NULL;
3895 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3896 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3897 /* Cipher to use protect the traffic */
3898 SilcCipher newkey, oldkey;
3901 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3903 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3904 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3908 /* Delete old cipher and allocate the new one */
3909 if (!silc_cipher_alloc(cipher, &newkey)) {
3910 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3911 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3915 oldkey = channel->channel_key;
3916 channel->channel_key = newkey;
3918 /* Re-generate channel key */
3919 if (!silc_server_create_channel_key(server, channel, 0)) {
3920 /* We don't have new key, revert to old one */
3921 channel->channel_key = oldkey;
3925 /* Remove old channel key for good */
3926 silc_cipher_free(oldkey);
3928 /* Send the channel key. This sends it to our local clients and if
3929 we are normal server to our router as well. */
3930 silc_server_send_channel_key(server, NULL, channel,
3931 server->server_type == SILC_ROUTER ?
3932 FALSE : !server->standalone);
3935 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3936 /* Cipher mode is unset. Remove the cipher and revert back to
3938 SilcCipher newkey, oldkey;
3939 cipher = channel->cipher;
3941 /* Delete old cipher and allocate default one */
3942 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
3943 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3944 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3948 oldkey = channel->channel_key;
3949 channel->channel_key = newkey;
3951 /* Re-generate channel key */
3952 if (!silc_server_create_channel_key(server, channel, 0)) {
3953 /* We don't have new key, revert to old one */
3954 channel->channel_key = oldkey;
3958 /* Remove old channel key for good */
3959 silc_cipher_free(oldkey);
3961 /* Send the channel key. This sends it to our local clients and if
3962 we are normal server to our router as well. */
3963 silc_server_send_channel_key(server, NULL, channel,
3964 server->server_type == SILC_ROUTER ?
3965 FALSE : !server->standalone);
3969 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3970 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3971 /* HMAC to use protect the traffic */
3972 unsigned char hash[32];
3976 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3978 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3979 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3983 /* Delete old hmac and allocate the new one */
3984 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
3985 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3986 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3990 silc_hmac_free(channel->hmac);
3991 channel->hmac = newhmac;
3993 /* Set the HMAC key out of current channel key. The client must do
3995 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
3996 channel->key_len / 8, hash);
3997 silc_hmac_set_key(channel->hmac, hash,
3998 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3999 memset(hash, 0, sizeof(hash));
4002 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4003 /* Hmac mode is unset. Remove the hmac and revert back to
4006 unsigned char hash[32];
4007 hmac = channel->hmac_name;
4009 /* Delete old hmac and allocate default one */
4010 silc_hmac_free(channel->hmac);
4011 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4012 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4013 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4017 silc_hmac_free(channel->hmac);
4018 channel->hmac = newhmac;
4020 /* Set the HMAC key out of current channel key. The client must do
4022 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4023 channel->key_len / 8,
4025 silc_hmac_set_key(channel->hmac, hash,
4026 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4027 memset(hash, 0, sizeof(hash));
4031 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4032 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4033 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4034 /* Set the founder authentication */
4035 SilcAuthPayload auth;
4037 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4039 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4040 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4044 auth = silc_auth_payload_parse(tmp, tmp_len);
4046 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4047 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4051 /* Save the public key */
4052 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
4053 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
4056 channel->founder_method = silc_auth_get_method(auth);
4058 if (channel->founder_method == SILC_AUTH_PASSWORD) {
4059 tmp = silc_auth_get_data(auth, &tmp_len);
4060 channel->founder_passwd =
4061 silc_calloc(tmp_len + 1, sizeof(*channel->founder_passwd));
4062 memcpy(channel->founder_passwd, tmp, tmp_len);
4063 channel->founder_passwd_len = tmp_len;
4065 /* Verify the payload before setting the mode */
4066 if (!silc_auth_verify(auth, channel->founder_method,
4067 channel->founder_key, 0, idata->hash,
4068 client->id, SILC_ID_CLIENT)) {
4069 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4070 SILC_STATUS_ERR_AUTH_FAILED);
4075 silc_auth_payload_free(auth);
4079 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4080 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4081 if (channel->founder_key)
4082 silc_pkcs_public_key_free(channel->founder_key);
4083 if (channel->founder_passwd) {
4084 silc_free(channel->founder_passwd);
4085 channel->founder_passwd = NULL;
4091 /* Finally, set the mode */
4092 channel->mode = mode_mask;
4094 /* Send CMODE_CHANGE notify. */
4095 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4096 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4097 SILC_NOTIFY_TYPE_CMODE_CHANGE, 5,
4098 cidp->data, cidp->len,
4100 cipher, cipher ? strlen(cipher) : 0,
4101 hmac, hmac ? strlen(hmac) : 0,
4102 passphrase, passphrase ?
4103 strlen(passphrase) : 0);
4105 /* Set CMODE notify type to network */
4106 if (!server->standalone)
4107 silc_server_send_notify_cmode(server, server->router->connection,
4108 server->server_type == SILC_ROUTER ?
4109 TRUE : FALSE, channel,
4110 mode_mask, client->id, SILC_ID_CLIENT,
4111 cipher, hmac, passphrase);
4113 /* Send command reply to sender */
4114 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4115 SILC_STATUS_OK, ident, 2,
4116 2, tmp_id, tmp_len2,
4118 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4119 packet->data, packet->len, FALSE);
4121 silc_buffer_free(packet);
4122 silc_free(channel_id);
4123 silc_buffer_free(cidp);
4126 silc_server_command_free(cmd);
4129 /* Server side of CUMODE command. Changes client's mode on a channel. */
4131 SILC_SERVER_CMD_FUNC(cumode)
4133 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4134 SilcServer server = cmd->server;
4135 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4136 SilcIDListData idata = (SilcIDListData)client;
4137 SilcChannelID *channel_id;
4138 SilcClientID *client_id;
4139 SilcChannelEntry channel;
4140 SilcClientEntry target_client;
4141 SilcChannelClientEntry chl;
4142 SilcBuffer packet, idp;
4143 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4144 uint32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4146 uint16 ident = silc_command_get_ident(cmd->payload);
4148 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4150 /* Get Channel ID */
4151 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4153 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4154 SILC_STATUS_ERR_NO_CHANNEL_ID);
4157 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
4159 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4160 SILC_STATUS_ERR_NO_CHANNEL_ID);
4164 /* Get channel entry */
4165 channel = silc_idlist_find_channel_by_id(server->local_list,
4168 channel = silc_idlist_find_channel_by_id(server->global_list,
4171 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4172 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4177 /* Check whether sender is on the channel */
4178 if (!silc_server_client_on_channel(client, channel)) {
4179 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4180 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4184 /* Check that client has rights to change other's rights */
4185 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4186 sender_mask = chl->mode;
4188 /* Get the target client's channel mode mask */
4189 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4191 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4192 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4195 SILC_GET32_MSB(target_mask, tmp_mask);
4197 /* Get target Client ID */
4198 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4200 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4201 SILC_STATUS_ERR_NO_CLIENT_ID);
4204 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
4206 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4207 SILC_STATUS_ERR_NO_CLIENT_ID);
4211 /* Get target client's entry */
4212 target_client = silc_idlist_find_client_by_id(server->local_list,
4213 client_id, TRUE, NULL);
4214 if (!target_client) {
4215 target_client = silc_idlist_find_client_by_id(server->global_list,
4216 client_id, TRUE, NULL);
4219 if (target_client != client &&
4220 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4221 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4222 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4223 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4227 /* Check whether target client is on the channel */
4228 if (target_client != client) {
4229 if (!silc_server_client_on_channel(target_client, channel)) {
4230 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4231 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4235 /* Get entry to the channel user list */
4236 silc_hash_table_find(channel->user_list, target_client, NULL,
4244 /* If the target client is founder, no one else can change their mode
4246 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
4247 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4248 SILC_STATUS_ERR_NOT_YOU);
4252 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4253 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4254 /* The client tries to claim the founder rights. */
4255 unsigned char *tmp_auth;
4256 uint32 tmp_auth_len, auth_len;
4259 if (target_client != client) {
4260 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4261 SILC_STATUS_ERR_NOT_YOU);
4265 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4266 !channel->founder_key || !idata->public_key ||
4267 !silc_pkcs_public_key_compare(channel->founder_key,
4268 idata->public_key)) {
4269 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4270 SILC_STATUS_ERR_NOT_YOU);
4274 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4276 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4277 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4281 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4282 (void *)channel->founder_passwd : (void *)channel->founder_key);
4283 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4284 channel->founder_passwd_len : 0);
4286 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4287 channel->founder_method, auth, auth_len,
4288 idata->hash, client->id, SILC_ID_CLIENT)) {
4289 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4290 SILC_STATUS_ERR_AUTH_FAILED);
4294 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4298 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4299 if (target_client == client) {
4300 /* Remove channel founder rights from itself */
4301 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4304 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4305 SILC_STATUS_ERR_NOT_YOU);
4311 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4312 /* Promote to operator */
4313 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4314 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4315 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4316 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4317 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4321 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4325 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4326 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4327 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4328 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4329 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4333 /* Demote to normal user */
4334 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4339 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4340 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4342 /* Send notify to channel, notify only if mode was actually changed. */
4344 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4345 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4346 idp->data, idp->len,
4350 /* Set CUMODE notify type to network */
4351 if (!server->standalone)
4352 silc_server_send_notify_cumode(server, server->router->connection,
4353 server->server_type == SILC_ROUTER ?
4354 TRUE : FALSE, channel,
4355 target_mask, client->id,
4360 /* Send command reply to sender */
4361 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4362 SILC_STATUS_OK, ident, 3,
4364 3, tmp_ch_id, tmp_ch_len,
4365 4, tmp_id, tmp_len);
4366 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4367 packet->data, packet->len, FALSE);
4369 silc_buffer_free(packet);
4370 silc_free(channel_id);
4371 silc_free(client_id);
4372 silc_buffer_free(idp);
4375 silc_server_command_free(cmd);
4378 /* Server side of KICK command. Kicks client out of channel. */
4380 SILC_SERVER_CMD_FUNC(kick)
4382 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4383 SilcServer server = cmd->server;
4384 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4385 SilcClientEntry target_client;
4386 SilcChannelID *channel_id;
4387 SilcClientID *client_id;
4388 SilcChannelEntry channel;
4389 SilcChannelClientEntry chl;
4391 uint32 tmp_len, target_idp_len;
4392 unsigned char *tmp, *comment, *target_idp;
4394 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4396 /* Get Channel ID */
4397 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4399 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4400 SILC_STATUS_ERR_NO_CHANNEL_ID);
4403 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
4405 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4406 SILC_STATUS_ERR_NO_CHANNEL_ID);
4410 /* Get channel entry */
4411 channel = silc_idlist_find_channel_by_id(server->local_list,
4414 channel = silc_idlist_find_channel_by_id(server->local_list,
4417 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4418 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4423 /* Check whether sender is on the channel */
4424 if (!silc_server_client_on_channel(client, channel)) {
4425 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4426 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4430 /* Check that the kicker is channel operator or channel founder */
4431 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4432 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4433 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4434 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4438 /* Get target Client ID */
4439 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4441 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4442 SILC_STATUS_ERR_NO_CLIENT_ID);
4445 client_id = silc_id_payload_parse_id(target_idp, target_idp_len);
4447 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4448 SILC_STATUS_ERR_NO_CLIENT_ID);
4452 /* Get target client's entry */
4453 target_client = silc_idlist_find_client_by_id(server->local_list,
4454 client_id, TRUE, NULL);
4455 if (!target_client) {
4456 target_client = silc_idlist_find_client_by_id(server->global_list,
4457 client_id, TRUE, NULL);
4460 /* Check that the target client is not channel founder. Channel founder
4461 cannot be kicked from the channel. */
4462 silc_hash_table_find(channel->user_list, target_client, NULL, (void *)&chl);
4463 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4464 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4465 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4469 /* Check whether target client is on the channel */
4470 if (!silc_server_client_on_channel(target_client, channel)) {
4471 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4472 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4478 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4482 /* Send command reply to sender */
4483 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4486 /* Send KICKED notify to local clients on the channel */
4487 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4488 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4489 SILC_NOTIFY_TYPE_KICKED, 3,
4490 target_idp, target_idp_len,
4491 comment, comment ? strlen(comment) : 0,
4492 idp->data, idp->len);
4493 silc_buffer_free(idp);
4495 /* Remove the client from the channel. If the channel does not exist
4496 after removing the client then the client kicked itself off the channel
4497 and we don't have to send anything after that. */
4498 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4499 target_client, FALSE))
4502 /* Send KICKED notify to primary route */
4503 if (!server->standalone)
4504 silc_server_send_notify_kicked(server, server->router->connection,
4505 server->server_type == SILC_ROUTER ?
4506 TRUE : FALSE, channel,
4507 target_client->id, comment);
4509 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4510 /* Re-generate channel key */
4511 if (!silc_server_create_channel_key(server, channel, 0))
4514 /* Send the channel key to the channel. The key of course is not sent
4515 to the client who was kicked off the channel. */
4516 silc_server_send_channel_key(server, target_client->connection, channel,
4517 server->server_type == SILC_ROUTER ?
4518 FALSE : !server->standalone);
4522 silc_server_command_free(cmd);
4525 /* Server side of OPER command. Client uses this comand to obtain server
4526 operator privileges to this server/router. */
4528 SILC_SERVER_CMD_FUNC(oper)
4530 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4531 SilcServer server = cmd->server;
4532 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4533 unsigned char *username, *auth;
4535 SilcServerConfigSectionAdminConnection *admin;
4536 SilcIDListData idata = (SilcIDListData)client;
4538 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4540 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4543 /* Get the username */
4544 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4546 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4547 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4551 /* Get the admin configuration */
4552 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4553 username, client->nickname);
4555 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4556 username, client->nickname);
4558 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4559 SILC_STATUS_ERR_AUTH_FAILED);
4564 /* Get the authentication payload */
4565 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4567 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4568 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4572 /* Verify the authentication data */
4573 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4574 admin->auth_data, admin->auth_data_len,
4575 idata->hash, client->id, SILC_ID_CLIENT)) {
4576 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4577 SILC_STATUS_ERR_AUTH_FAILED);
4581 /* Client is now server operator */
4582 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4584 /* Send UMODE change to primary router */
4585 if (!server->standalone)
4586 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4587 client->id, client->mode);
4589 /* Send reply to the sender */
4590 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4594 silc_server_command_free(cmd);
4597 /* Server side of SILCOPER command. Client uses this comand to obtain router
4598 operator privileges to this router. */
4600 SILC_SERVER_CMD_FUNC(silcoper)
4602 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4603 SilcServer server = cmd->server;
4604 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4605 unsigned char *username, *auth;
4607 SilcServerConfigSectionAdminConnection *admin;
4608 SilcIDListData idata = (SilcIDListData)client;
4610 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4612 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4615 if (server->server_type != SILC_ROUTER) {
4616 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4617 SILC_STATUS_ERR_AUTH_FAILED);
4621 /* Get the username */
4622 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4624 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4625 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4629 /* Get the admin configuration */
4630 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4631 username, client->nickname);
4633 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4634 username, client->nickname);
4636 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4637 SILC_STATUS_ERR_AUTH_FAILED);
4642 /* Get the authentication payload */
4643 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4645 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4646 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4650 /* Verify the authentication data */
4651 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4652 admin->auth_data, admin->auth_data_len,
4653 idata->hash, client->id, SILC_ID_CLIENT)) {
4654 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4655 SILC_STATUS_ERR_AUTH_FAILED);
4659 /* Client is now router operator */
4660 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4662 /* Send UMODE change to primary router */
4663 if (!server->standalone)
4664 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4665 client->id, client->mode);
4667 /* Send reply to the sender */
4668 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4672 silc_server_command_free(cmd);
4675 /* Server side command of CONNECT. Connects us to the specified remote
4676 server or router. */
4678 SILC_SERVER_CMD_FUNC(connect)
4680 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4681 SilcServer server = cmd->server;
4682 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4683 unsigned char *tmp, *host;
4685 uint32 port = SILC_PORT;
4687 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CONNECT, cmd, 1, 2);
4689 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4692 /* Check whether client has the permissions. */
4693 if (client->mode == SILC_UMODE_NONE) {
4694 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4695 SILC_STATUS_ERR_NO_SERVER_PRIV);
4699 if (server->server_type == SILC_ROUTER &&
4700 client->mode & SILC_UMODE_SERVER_OPERATOR) {
4701 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4702 SILC_STATUS_ERR_NO_ROUTER_PRIV);
4706 /* Get the remote server */
4707 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4709 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4710 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4715 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4717 SILC_GET32_MSB(port, tmp);
4719 /* Create the connection. It is done with timeout and is async. */
4720 silc_server_create_connection(server, host, port);
4722 /* Send reply to the sender */
4723 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4727 silc_server_command_free(cmd);
4730 /* Server side of command BAN. This is used to manage the ban list of the
4731 channel. To add clients and remove clients from the ban list. */
4733 SILC_SERVER_CMD_FUNC(ban)
4735 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4736 SilcServer server = cmd->server;
4737 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4739 SilcChannelEntry channel;
4740 SilcChannelClientEntry chl;
4741 SilcChannelID *channel_id = NULL;
4742 unsigned char *id, *add, *del;
4743 uint32 id_len, tmp_len;
4744 uint16 ident = silc_command_get_ident(cmd->payload);
4746 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4749 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4751 /* Get Channel ID */
4752 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4754 channel_id = silc_id_payload_parse_id(id, id_len);
4756 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4757 SILC_STATUS_ERR_NO_CHANNEL_ID);
4762 /* Get channel entry. The server must know about the channel since the
4763 client is expected to be on the channel. */
4764 channel = silc_idlist_find_channel_by_id(server->local_list,
4767 channel = silc_idlist_find_channel_by_id(server->global_list,
4770 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4771 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4776 /* Check whether this client is on the channel */
4777 if (!silc_server_client_on_channel(client, channel)) {
4778 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4779 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4783 /* Get entry to the channel user list */
4784 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4786 /* The client must be at least channel operator. */
4787 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4788 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4789 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4793 /* Get the new ban and add it to the ban list */
4794 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4796 if (!channel->ban_list)
4797 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4799 channel->ban_list = silc_realloc(channel->ban_list,
4800 sizeof(*channel->ban_list) *
4802 strlen(channel->ban_list) + 2));
4803 if (add[tmp_len - 1] == ',')
4804 add[tmp_len - 1] = '\0';
4806 strncat(channel->ban_list, add, tmp_len);
4807 strncat(channel->ban_list, ",", 1);
4810 /* Get the ban to be removed and remove it from the list */
4811 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4812 if (del && channel->ban_list) {
4813 char *start, *end, *n;
4815 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4816 silc_free(channel->ban_list);
4817 channel->ban_list = NULL;
4819 start = strstr(channel->ban_list, del);
4820 if (start && strlen(start) >= tmp_len) {
4821 end = start + tmp_len;
4822 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4823 strncat(n, channel->ban_list, start - channel->ban_list);
4824 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4826 silc_free(channel->ban_list);
4827 channel->ban_list = n;
4832 /* Send the BAN notify type to our primary router. */
4833 if (!server->standalone && (add || del))
4834 silc_server_send_notify_ban(server, server->router->connection,
4835 server->server_type == SILC_ROUTER ?
4836 TRUE : FALSE, channel, add, del);
4838 /* Send the reply back to the client */
4840 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4841 SILC_STATUS_OK, ident, 2,
4843 3, channel->ban_list,
4845 strlen(channel->ban_list) - 1 : 0);
4846 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4847 packet->data, packet->len, FALSE);
4849 silc_buffer_free(packet);
4852 silc_free(channel_id);
4853 silc_server_command_free(cmd);
4856 /* Server side command of CLOSE. Closes connection to a specified server. */
4858 SILC_SERVER_CMD_FUNC(close)
4860 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4861 SilcServer server = cmd->server;
4862 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4863 SilcServerEntry server_entry;
4864 SilcSocketConnection sock;
4867 unsigned char *name;
4868 uint32 port = SILC_PORT;
4870 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CLOSE, cmd, 1, 2);
4872 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4875 /* Check whether client has the permissions. */
4876 if (client->mode == SILC_UMODE_NONE) {
4877 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4878 SILC_STATUS_ERR_NO_SERVER_PRIV);
4882 /* Get the remote server */
4883 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4885 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4886 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4891 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4893 SILC_GET32_MSB(port, tmp);
4895 server_entry = silc_idlist_find_server_by_conn(server->local_list,
4896 name, port, FALSE, NULL);
4898 server_entry = silc_idlist_find_server_by_conn(server->global_list,
4899 name, port, FALSE, NULL);
4900 if (!server_entry) {
4901 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4902 SILC_STATUS_ERR_NO_SERVER_ID);
4906 /* Send reply to the sender */
4907 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4910 /* Close the connection to the server */
4911 sock = (SilcSocketConnection)server_entry->connection;
4913 /* If we shutdown primary router connection manually then don't trigger
4914 any reconnect or backup router connections, by setting the router
4916 if (server->router == server_entry) {
4917 server->id_entry->router = NULL;
4918 server->router = NULL;
4919 server->standalone = TRUE;
4921 silc_server_free_sock_user_data(server, sock, NULL);
4922 silc_server_close_connection(server, sock);
4925 silc_server_command_free(cmd);
4928 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4929 active connections. */
4931 SILC_SERVER_CMD_FUNC(shutdown)
4933 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4934 SilcServer server = cmd->server;
4935 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4937 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4939 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4942 /* Check whether client has the permission. */
4943 if (client->mode == SILC_UMODE_NONE) {
4944 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4945 SILC_STATUS_ERR_NO_SERVER_PRIV);
4949 /* Send reply to the sender */
4950 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4953 /* Then, gracefully, or not, bring the server down. */
4954 silc_server_stop(server);
4958 silc_server_command_free(cmd);
4961 /* Server side command of LEAVE. Removes client from a channel. */
4963 SILC_SERVER_CMD_FUNC(leave)
4965 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4966 SilcServer server = cmd->server;
4967 SilcSocketConnection sock = cmd->sock;
4968 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4969 SilcChannelID *id = NULL;
4970 SilcChannelEntry channel;
4974 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4976 /* Get Channel ID */
4977 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4979 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4980 SILC_STATUS_ERR_NO_CHANNEL_ID);
4983 id = silc_id_payload_parse_id(tmp, len);
4985 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4986 SILC_STATUS_ERR_NO_CHANNEL_ID);
4990 /* Get channel entry */
4991 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4993 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4995 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4996 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5001 /* Check whether this client is on the channel */
5002 if (!silc_server_client_on_channel(id_entry, channel)) {
5003 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5004 SILC_STATUS_ERR_NOT_ON_CHANNEL);
5008 /* Notify routers that they should remove this client from their list
5009 of clients on the channel. Send LEAVE notify type. */
5010 if (!server->standalone)
5011 silc_server_send_notify_leave(server, server->router->connection,
5012 server->server_type == SILC_ROUTER ?
5013 TRUE : FALSE, channel, id_entry->id);
5015 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5018 /* Remove client from channel */
5019 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5021 /* If the channel does not exist anymore we won't send anything */
5024 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5025 /* Re-generate channel key */
5026 if (!silc_server_create_channel_key(server, channel, 0))
5029 /* Send the channel key */
5030 silc_server_send_channel_key(server, NULL, channel,
5031 server->server_type == SILC_ROUTER ?
5032 FALSE : !server->standalone);
5037 silc_server_command_free(cmd);
5040 /* Server side of command USERS. Resolves clients and their USERS currently
5041 joined on the requested channel. The list of Client ID's and their modes
5042 on the channel is sent back. */
5044 SILC_SERVER_CMD_FUNC(users)
5046 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5047 SilcServer server = cmd->server;
5048 SilcChannelEntry channel;
5049 SilcChannelID *id = NULL;
5050 SilcBuffer packet, idp;
5051 unsigned char *channel_id;
5052 uint32 channel_id_len;
5053 SilcBuffer client_id_list;
5054 SilcBuffer client_mode_list;
5055 unsigned char lc[4];
5056 uint32 list_count = 0;
5057 uint16 ident = silc_command_get_ident(cmd->payload);
5060 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5062 /* Get Channel ID */
5063 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5065 /* Get channel name */
5066 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5068 if (!channel_id && !channel_name) {
5069 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5070 SILC_STATUS_ERR_NO_CHANNEL_ID);
5075 id = silc_id_payload_parse_id(channel_id, channel_id_len);
5077 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5078 SILC_STATUS_ERR_NO_CHANNEL_ID);
5083 /* If we are server and we don't know about this channel we will send
5084 the command to our router. If we know about the channel then we also
5085 have the list of users already. */
5087 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5089 channel = silc_idlist_find_channel_by_name(server->local_list,
5090 channel_name, NULL);
5092 if (!channel || channel->disabled) {
5093 if (server->server_type != SILC_ROUTER && !server->standalone &&
5097 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5098 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5100 /* Send USERS command */
5101 silc_server_packet_send(server, server->router->connection,
5102 SILC_PACKET_COMMAND, cmd->packet->flags,
5103 tmpbuf->data, tmpbuf->len, TRUE);
5105 /* Reprocess this packet after received reply */
5106 silc_server_command_pending(server, SILC_COMMAND_USERS,
5107 silc_command_get_ident(cmd->payload),
5108 silc_server_command_users,
5109 silc_server_command_dup(cmd));
5110 cmd->pending = TRUE;
5111 silc_command_set_ident(cmd->payload, ident);
5112 silc_buffer_free(tmpbuf);
5117 /* Check the global list as well. */
5119 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5121 channel = silc_idlist_find_channel_by_name(server->global_list,
5122 channel_name, NULL);
5124 /* Channel really does not exist */
5125 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5126 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5131 /* If the channel is private or secret do not send anything, unless the
5132 user requesting this command is on the channel. */
5133 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5134 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5135 && !silc_server_client_on_channel(cmd->sock->user_data, channel)) {
5136 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5137 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5142 (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
5143 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5144 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5149 /* Get the users list */
5150 silc_server_get_users_on_channel(server, channel, &client_id_list,
5151 &client_mode_list, &list_count);
5154 SILC_PUT32_MSB(list_count, lc);
5157 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5158 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5159 SILC_STATUS_OK, ident, 4,
5160 2, idp->data, idp->len,
5162 4, client_id_list->data,
5163 client_id_list->len,
5164 5, client_mode_list->data,
5165 client_mode_list->len);
5166 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5167 packet->data, packet->len, FALSE);
5169 silc_buffer_free(idp);
5170 silc_buffer_free(packet);
5171 silc_buffer_free(client_id_list);
5172 silc_buffer_free(client_mode_list);
5176 silc_server_command_free(cmd);
5179 /* Server side of command GETKEY. This fetches the client's public key
5180 from the server where to the client is connected. */
5182 SILC_SERVER_CMD_FUNC(getkey)
5184 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5185 SilcServer server = cmd->server;
5187 SilcClientEntry client;
5188 SilcServerEntry server_entry;
5189 SilcClientID *client_id = NULL;
5190 SilcServerID *server_id = NULL;
5191 SilcIDPayload idp = NULL;
5192 uint16 ident = silc_command_get_ident(cmd->payload);
5193 unsigned char *tmp, *pkdata;
5194 uint32 tmp_len, pklen;
5195 SilcBuffer pk = NULL;
5198 SILC_LOG_DEBUG(("Start"));
5200 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5202 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5203 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5206 idp = silc_id_payload_parse(tmp, tmp_len);
5208 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5209 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5213 id_type = silc_id_payload_get_type(idp);
5214 if (id_type == SILC_ID_CLIENT) {
5215 client_id = silc_id_payload_get_id(idp);
5217 /* If the client is not found from local list there is no chance it
5218 would be locally connected client so send the command further. */
5219 client = silc_idlist_find_client_by_id(server->local_list,
5220 client_id, TRUE, NULL);
5222 client = silc_idlist_find_client_by_id(server->global_list,
5223 client_id, TRUE, NULL);
5225 if ((!client && !cmd->pending && !server->standalone) ||
5226 (client && !client->connection && !cmd->pending) ||
5227 (client && !client->data.public_key && !cmd->pending)) {
5230 SilcSocketConnection dest_sock;
5232 dest_sock = silc_server_get_client_route(server, NULL, 0,
5237 old_ident = silc_command_get_ident(cmd->payload);
5238 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5239 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5241 silc_server_packet_send(server, dest_sock,
5242 SILC_PACKET_COMMAND, cmd->packet->flags,
5243 tmpbuf->data, tmpbuf->len, TRUE);
5245 /* Reprocess this packet after received reply from router */
5246 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5247 silc_command_get_ident(cmd->payload),
5248 silc_server_command_getkey,
5249 silc_server_command_dup(cmd));
5250 cmd->pending = TRUE;
5251 silc_command_set_ident(cmd->payload, old_ident);
5252 silc_buffer_free(tmpbuf);
5257 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5258 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5262 /* The client is locally connected, just get the public key and
5263 send it back. If they key does not exist then do not send it,
5264 send just OK reply */
5265 if (!client->data.public_key) {
5269 tmp = silc_pkcs_public_key_encode(client->data.public_key, &tmp_len);
5270 pk = silc_buffer_alloc(4 + tmp_len);
5271 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5272 silc_buffer_format(pk,
5273 SILC_STR_UI_SHORT(tmp_len),
5274 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5275 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5281 } else if (id_type == SILC_ID_SERVER) {
5282 server_id = silc_id_payload_get_id(idp);
5284 /* If the server is not found from local list there is no chance it
5285 would be locally connected server so send the command further. */
5286 server_entry = silc_idlist_find_server_by_id(server->local_list,
5287 server_id, TRUE, NULL);
5289 server_entry = silc_idlist_find_server_by_id(server->global_list,
5290 server_id, TRUE, NULL);
5292 if (server_entry != server->id_entry &&
5293 ((!server_entry && !cmd->pending && !server->standalone) ||
5294 (server_entry && !server_entry->connection && !cmd->pending &&
5295 !server->standalone) ||
5296 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5297 !server->standalone))) {
5301 old_ident = silc_command_get_ident(cmd->payload);
5302 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5303 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5305 silc_server_packet_send(server, server->router->connection,
5306 SILC_PACKET_COMMAND, cmd->packet->flags,
5307 tmpbuf->data, tmpbuf->len, TRUE);
5309 /* Reprocess this packet after received reply from router */
5310 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5311 silc_command_get_ident(cmd->payload),
5312 silc_server_command_getkey,
5313 silc_server_command_dup(cmd));
5314 cmd->pending = TRUE;
5316 silc_command_set_ident(cmd->payload, old_ident);
5317 silc_buffer_free(tmpbuf);
5321 if (!server_entry) {
5322 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5323 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5327 /* If they key does not exist then do not send it, send just OK reply */
5328 if (!server_entry->data.public_key) {
5332 tmp = silc_pkcs_public_key_encode(server_entry->data.public_key,
5334 pk = silc_buffer_alloc(4 + tmp_len);
5335 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5336 silc_buffer_format(pk,
5337 SILC_STR_UI_SHORT(tmp_len),
5338 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5339 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5349 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5350 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5351 SILC_STATUS_OK, ident,
5355 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5356 packet->data, packet->len, FALSE);
5357 silc_buffer_free(packet);
5360 silc_buffer_free(pk);
5364 silc_id_payload_free(idp);
5365 silc_free(client_id);
5366 silc_free(server_id);
5367 silc_server_command_free(cmd);