5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2001 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
22 #include "serverincludes.h"
23 #include "server_internal.h"
25 static int silc_server_is_registered(SilcServer server,
26 SilcSocketConnection sock,
27 SilcServerCommandContext cmd,
30 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
32 SilcCommandStatus status);
34 silc_server_command_send_status_data(SilcServerCommandContext cmd,
36 SilcCommandStatus status,
38 const unsigned char *arg,
41 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
42 SilcServerCommandReplyContext cmdr,
44 SILC_TASK_CALLBACK(silc_server_command_process_timeout);
46 /* Server command list. */
47 SilcServerCommand silc_command_list[] =
49 SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
50 SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
51 SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
52 SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
53 SILC_SERVER_CMD(list, LIST, SILC_CF_LAG_STRICT | SILC_CF_REG),
54 SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
55 SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
56 SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
57 SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG_STRICT | SILC_CF_REG | SILC_CF_OPER),
58 SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
59 SILC_SERVER_CMD(connect, CONNECT,
60 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
61 SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
62 SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
63 SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG_STRICT | SILC_CF_REG),
64 SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
65 SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
66 SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG_STRICT | SILC_CF_REG),
67 SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
68 SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
69 SILC_SERVER_CMD(ban, BAN, SILC_CF_LAG_STRICT | SILC_CF_REG),
70 SILC_SERVER_CMD(close, CLOSE,
71 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
72 SILC_SERVER_CMD(shutdown, SHUTDOWN, SILC_CF_LAG | SILC_CF_REG |
74 SILC_SERVER_CMD(silcoper, SILCOPER,
75 SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
76 SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
77 SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
78 SILC_SERVER_CMD(getkey, GETKEY, SILC_CF_LAG | SILC_CF_REG),
83 /* Performs several checks to the command. It first checks whether this
84 command was called as pending command callback. If it was then it checks
85 whether error occurred in the command reply where the pending command
88 It also checks that the requested command includes correct amount
90 #define SILC_SERVER_COMMAND_CHECK(command, context, min, max) \
94 SILC_LOG_DEBUG(("Start")); \
96 if (silc_server_command_pending_error_check(cmd, context2, command)) { \
97 silc_server_command_free(cmd); \
101 _argc = silc_argument_get_arg_num(cmd->args); \
103 silc_server_command_send_status_reply(cmd, command, \
104 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
105 silc_server_command_free(cmd); \
109 silc_server_command_send_status_reply(cmd, command, \
110 SILC_STATUS_ERR_TOO_MANY_PARAMS); \
111 silc_server_command_free(cmd); \
116 /* Returns TRUE if the connection is registered. Unregistered connections
117 usually cannot send commands hence the check. */
119 static int silc_server_is_registered(SilcServer server,
120 SilcSocketConnection sock,
121 SilcServerCommandContext cmd,
124 SilcIDListData idata = (SilcIDListData)sock->user_data;
129 if (idata->status & SILC_IDLIST_STATUS_REGISTERED)
132 silc_server_command_send_status_reply(cmd, command,
133 SILC_STATUS_ERR_NOT_REGISTERED);
134 silc_server_command_free(cmd);
138 /* Internal context to hold data when executed command with timeout. */
140 SilcServerCommandContext ctx;
141 SilcServerCommand *cmd;
142 } *SilcServerCommandTimeout;
144 /* Timeout callback to process commands with timeout for client. Client's
145 commands are always executed with timeout. */
147 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
149 SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
150 SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data;
152 /* Update access time */
153 client->last_command = time(NULL);
155 if (!(timeout->cmd->flags & SILC_CF_REG))
156 timeout->cmd->cb(timeout->ctx, NULL);
157 else if (silc_server_is_registered(timeout->ctx->server,
161 timeout->cmd->cb(timeout->ctx, NULL);
166 /* Processes received command packet. */
168 void silc_server_command_process(SilcServer server,
169 SilcSocketConnection sock,
170 SilcPacketContext *packet)
172 SilcServerCommandContext ctx;
173 SilcServerCommand *cmd;
176 /* Allocate command context. This must be free'd by the
177 command routine receiving it. */
178 ctx = silc_server_command_alloc();
179 ctx->server = server;
180 ctx->sock = silc_socket_dup(sock);
181 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
183 /* Parse the command payload in the packet */
184 ctx->payload = silc_command_payload_parse(packet->buffer->data,
185 packet->buffer->len);
187 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
188 silc_buffer_free(packet->buffer);
189 silc_packet_context_free(packet);
190 silc_socket_free(ctx->sock);
194 ctx->args = silc_command_get_args(ctx->payload);
196 /* Get the command */
197 command = silc_command_get(ctx->payload);
198 for (cmd = silc_command_list; cmd->cb; cmd++)
199 if (cmd->cmd == command)
203 silc_server_command_send_status_reply(ctx, command,
204 SILC_STATUS_ERR_UNKNOWN_COMMAND);
205 silc_server_command_free(ctx);
209 /* Execute client's commands always with timeout. Normally they are
210 executed with zero (0) timeout but if client is sending command more
211 frequently than once in 2 seconds, then the timeout may be 0 to 2
213 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
214 SilcClientEntry client = (SilcClientEntry)sock->user_data;
215 SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
221 if (client->last_command && (time(NULL) - client->last_command) < 2) {
222 client->fast_command++;
225 client->fast_command = ((client->fast_command - 1) <= 0 ? 0 :
226 client->fast_command--);
230 if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
231 (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
232 silc_schedule_task_add(server->schedule, sock->sock,
233 silc_server_command_process_timeout,
235 2 - (time(NULL) - client->last_command), 0,
237 SILC_TASK_PRI_NORMAL);
239 silc_schedule_task_add(server->schedule, sock->sock,
240 silc_server_command_process_timeout,
244 SILC_TASK_PRI_NORMAL);
248 /* Execute for server */
250 if (!(cmd->flags & SILC_CF_REG))
252 else if (silc_server_is_registered(server, sock, ctx, cmd->cmd))
256 /* Allocate Command Context */
258 SilcServerCommandContext silc_server_command_alloc()
260 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
265 /* Free's the command context allocated before executing the command */
267 void silc_server_command_free(SilcServerCommandContext ctx)
270 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
272 if (ctx->users < 1) {
274 silc_command_payload_free(ctx->payload);
276 silc_packet_context_free(ctx->packet);
278 silc_socket_free(ctx->sock); /* Decrease reference counter */
283 /* Duplicate Command Context by adding reference counter. The context won't
284 be free'd untill it hits zero. */
286 SilcServerCommandContext
287 silc_server_command_dup(SilcServerCommandContext ctx)
290 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
295 /* Add new pending command to be executed when reply to a command has been
296 received. The `reply_cmd' is the command that will call the `callback'
297 with `context' when reply has been received. It can be SILC_COMMAND_NONE
298 to match any command with the `ident'. If `ident' is non-zero
299 the `callback' will be executed when received reply with command
300 identifier `ident'. If there already exists pending command for the
301 specified command, ident, callback and context this function has no
304 bool silc_server_command_pending(SilcServer server,
305 SilcCommand reply_cmd,
307 SilcCommandCb callback,
310 SilcServerCommandPending *reply;
312 /* Check whether identical pending already exists for same command,
313 ident, callback and callback context. If it does then it would be
314 error to register it again. */
315 silc_dlist_start(server->pending_commands);
316 while ((reply = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
317 if (reply->reply_cmd == reply_cmd && reply->ident == ident &&
318 reply->callback == callback && reply->context == context)
322 reply = silc_calloc(1, sizeof(*reply));
323 reply->reply_cmd = reply_cmd;
324 reply->ident = ident;
325 reply->context = context;
326 reply->callback = callback;
327 silc_dlist_add(server->pending_commands, reply);
332 /* Deletes pending command by reply command type. */
334 void silc_server_command_pending_del(SilcServer server,
335 SilcCommand reply_cmd,
338 SilcServerCommandPending *r;
340 silc_dlist_start(server->pending_commands);
341 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
342 if (r->reply_cmd == reply_cmd && r->ident == ident) {
343 silc_dlist_del(server->pending_commands, r);
349 /* Checks for pending commands and marks callbacks to be called from
350 the command reply function. Returns TRUE if there were pending command. */
352 SilcServerCommandPendingCallbacks
353 silc_server_command_pending_check(SilcServer server,
354 SilcServerCommandReplyContext ctx,
357 uint32 *callbacks_count)
359 SilcServerCommandPending *r;
360 SilcServerCommandPendingCallbacks callbacks = NULL;
363 silc_dlist_start(server->pending_commands);
364 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
365 if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE)
366 && r->ident == ident) {
367 callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
368 callbacks[i].context = r->context;
369 callbacks[i].callback = r->callback;
375 *callbacks_count = i;
379 /* Sends simple status message as command reply packet */
382 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
384 SilcCommandStatus status)
388 SILC_LOG_DEBUG(("Sending command status %d", status));
391 silc_command_reply_payload_encode_va(command, status,
392 silc_command_get_ident(cmd->payload),
394 silc_server_packet_send(cmd->server, cmd->sock,
395 SILC_PACKET_COMMAND_REPLY, 0,
396 buffer->data, buffer->len, FALSE);
397 silc_buffer_free(buffer);
400 /* Sends command status reply with one extra argument. The argument
401 type must be sent as argument. */
404 silc_server_command_send_status_data(SilcServerCommandContext cmd,
406 SilcCommandStatus status,
408 const unsigned char *arg,
413 SILC_LOG_DEBUG(("Sending command status %d", status));
416 silc_command_reply_payload_encode_va(command, status,
417 silc_command_get_ident(cmd->payload),
418 1, arg_type, arg, arg_len);
419 silc_server_packet_send(cmd->server, cmd->sock,
420 SILC_PACKET_COMMAND_REPLY, 0,
421 buffer->data, buffer->len, FALSE);
422 silc_buffer_free(buffer);
425 /* This function can be called to check whether in the command reply
426 an error occurred. This function has no effect if this is called
427 when the command function was not called as pending command callback.
428 This returns TRUE if error had occurred. */
431 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
432 SilcServerCommandReplyContext cmdr,
435 SilcCommandStatus status;
437 if (!cmd->pending || !cmdr)
440 SILC_GET16_MSB(status, silc_argument_get_arg_type(cmdr->args, 1, NULL));
441 if (status != SILC_STATUS_OK &&
442 status != SILC_STATUS_LIST_START &&
443 status != SILC_STATUS_LIST_ITEM &&
444 status != SILC_STATUS_LIST_END) {
447 /* Send the same command reply payload */
448 silc_command_set_ident(cmdr->payload,
449 silc_command_get_ident(cmd->payload));
450 buffer = silc_command_payload_encode_payload(cmdr->payload);
451 silc_server_packet_send(cmd->server, cmd->sock,
452 SILC_PACKET_COMMAND_REPLY, 0,
453 buffer->data, buffer->len, FALSE);
454 silc_buffer_free(buffer);
461 /******************************************************************************
465 ******************************************************************************/
468 silc_server_command_whois_parse(SilcServerCommandContext cmd,
469 SilcClientID ***client_id,
470 uint32 *client_id_count,
478 uint32 argc = silc_argument_get_arg_num(cmd->args);
481 /* If client ID is in the command it must be used instead of nickname */
482 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
484 /* No ID, get the nickname@server string and parse it. */
485 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
487 silc_parse_userfqdn(tmp, nickname, server_name);
489 silc_server_command_send_status_reply(cmd, command,
490 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
494 /* Command includes ID, we must use that. Also check whether the command
495 has more than one ID set - take them all. */
497 *client_id = silc_calloc(1, sizeof(**client_id));
498 (*client_id)[0] = silc_id_payload_parse_id(tmp, len);
499 if ((*client_id)[0] == NULL) {
500 silc_free(*client_id);
503 *client_id_count = 1;
505 /* Take all ID's from the command packet */
507 for (k = 1, i = 1; i < argc; i++) {
508 tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
510 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
511 (*client_id_count + 1));
512 (*client_id)[k] = silc_id_payload_parse_id(tmp, len);
513 if ((*client_id)[k] == NULL) {
514 /* Cleanup all and fail */
515 for (i = 0; i < *client_id_count; i++)
516 silc_free((*client_id)[i]);
517 silc_free(*client_id);
520 (*client_id_count)++;
527 /* Get the max count of reply messages allowed */
528 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
537 /* Resolve context used by both WHOIS and IDENTIFY commands */
539 SilcServerEntry router;
541 unsigned char **res_argv;
542 uint32 *res_argv_lens;
543 uint32 *res_argv_types;
545 } *SilcServerResolveContext;
548 silc_server_command_whois_check(SilcServerCommandContext cmd,
549 SilcClientEntry *clients,
550 uint32 clients_count)
552 SilcServer server = cmd->server;
553 SilcClientEntry entry;
554 SilcServerResolveContext resolve = NULL, r = NULL;
555 uint32 resolve_count = 0;
559 for (i = 0; i < clients_count; i++) {
564 if ((entry->nickname && entry->username && entry->userinfo) ||
565 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
569 /* If we are normal server, and we've not resolved this client from
570 router and it is global client, we'll check whether it is on some
571 channel. If not then we cannot be sure about its validity, and
572 we'll resolve it from router. */
573 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
574 entry->connection || silc_hash_table_count(entry->channels))
578 /* We need to resolve this entry since it is not complete */
580 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
581 /* The entry is being resolved (and we are not the resolver) so attach
582 to the command reply and we're done with this one. */
583 silc_server_command_pending(server, SILC_COMMAND_NONE,
584 entry->resolve_cmd_ident,
585 silc_server_command_whois,
586 silc_server_command_dup(cmd));
589 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
590 /* We've resolved this and it still is not ready. We'll return
591 and are that this will be handled again after it is resolved. */
592 for (i = 0; i < resolve_count; i++) {
593 for (k = 0; k < r->res_argc; k++)
594 silc_free(r->res_argv[k]);
595 silc_free(r->res_argv);
596 silc_free(r->res_argv_lens);
597 silc_free(r->res_argv_types);
602 /* We'll resolve this client */
606 for (k = 0; k < resolve_count; k++) {
607 if (resolve[k].router == entry->router) {
614 resolve = silc_realloc(resolve, sizeof(*resolve) *
615 (resolve_count + 1));
616 r = &resolve[resolve_count];
617 memset(r, 0, sizeof(*r));
618 r->router = entry->router;
619 r->ident = ++server->cmd_ident;
623 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
625 r->res_argv_lens = silc_realloc(r->res_argv_lens,
626 sizeof(*r->res_argv_lens) *
628 r->res_argv_types = silc_realloc(r->res_argv_types,
629 sizeof(*r->res_argv_types) *
631 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
632 r->res_argv[r->res_argc] = silc_calloc(idp->len,
633 sizeof(**r->res_argv));
634 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
635 r->res_argv_lens[r->res_argc] = idp->len;
636 r->res_argv_types[r->res_argc] = r->res_argc + 3;
638 silc_buffer_free(idp);
640 entry->resolve_cmd_ident = r->ident;
641 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
642 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
647 /* Do the resolving */
648 for (i = 0; i < resolve_count; i++) {
653 /* Send WHOIS request. We send WHOIS since we're doing the requesting
654 now anyway so make it a good one. */
655 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
656 r->res_argc, r->res_argv,
660 silc_server_packet_send(server, r->router->connection,
661 SILC_PACKET_COMMAND, cmd->packet->flags,
662 res_cmd->data, res_cmd->len, FALSE);
664 /* Reprocess this packet after received reply */
665 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
667 silc_server_command_whois,
668 silc_server_command_dup(cmd));
671 silc_buffer_free(res_cmd);
672 for (k = 0; k < r->res_argc; k++)
673 silc_free(r->res_argv[k]);
674 silc_free(r->res_argv);
675 silc_free(r->res_argv_lens);
676 silc_free(r->res_argv_types);
685 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
686 SilcClientEntry *clients,
687 uint32 clients_count,
689 const char *nickname,
690 SilcClientID **client_ids)
692 SilcServer server = cmd->server;
694 int i, k, len, valid_count;
695 SilcBuffer packet, idp, channels;
696 SilcClientEntry entry;
697 SilcCommandStatus status;
698 uint16 ident = silc_command_get_ident(cmd->payload);
699 char nh[256], uh[256];
700 unsigned char idle[4], mode[4];
701 unsigned char *fingerprint;
702 SilcSocketConnection hsock;
704 /* Process only valid clients and ignore those that are not registered. */
706 for (i = 0; i < clients_count; i++) {
707 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
714 /* No valid clients found, send error reply */
716 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
717 SILC_STATUS_ERR_NO_SUCH_NICK,
718 3, nickname, strlen(nickname));
719 } else if (client_ids && client_ids[0]) {
720 SilcBuffer idp = silc_id_payload_encode(client_ids[0], SILC_ID_CLIENT);
721 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
722 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
723 2, idp->data, idp->len);
724 silc_buffer_free(idp);
729 /* Start processing found clients. */
731 status = SILC_STATUS_LIST_START;
733 status = SILC_STATUS_OK;
735 for (i = 0, k = 0; i < clients_count; i++) {
741 status = SILC_STATUS_LIST_ITEM;
742 if (valid_count > 1 && k == valid_count - 1)
743 status = SILC_STATUS_LIST_END;
744 if (count && k - 1 == count)
745 status = SILC_STATUS_LIST_END;
747 /* Send WHOIS reply */
748 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
749 tmp = silc_argument_get_first_arg(cmd->args, NULL);
751 memset(uh, 0, sizeof(uh));
752 memset(nh, 0, sizeof(nh));
753 memset(idle, 0, sizeof(idle));
755 strncat(nh, entry->nickname, strlen(entry->nickname));
756 if (!strchr(entry->nickname, '@')) {
758 if (entry->servername) {
759 strncat(nh, entry->servername, strlen(entry->servername));
761 len = entry->router ? strlen(entry->router->server_name) :
762 strlen(server->server_name);
763 strncat(nh, entry->router ? entry->router->server_name :
764 server->server_name, len);
768 strncat(uh, entry->username, strlen(entry->username));
769 if (!strchr(entry->username, '@')) {
771 hsock = (SilcSocketConnection)entry->connection;
772 len = strlen(hsock->hostname);
773 strncat(uh, hsock->hostname, len);
776 channels = silc_server_get_client_channel_list(server, entry);
778 if (entry->data.fingerprint[0] != 0 && entry->data.fingerprint[1] != 0)
779 fingerprint = entry->data.fingerprint;
783 SILC_PUT32_MSB(entry->mode, mode);
785 if (entry->connection) {
786 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
790 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
792 2, idp->data, idp->len,
796 strlen(entry->userinfo),
797 6, channels ? channels->data : NULL,
798 channels ? channels->len : 0,
802 fingerprint ? 20 : 0);
804 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
805 0, packet->data, packet->len, FALSE);
807 silc_buffer_free(packet);
808 silc_buffer_free(idp);
810 silc_buffer_free(channels);
817 silc_server_command_whois_send_router(SilcServerCommandContext cmd)
819 SilcServer server = cmd->server;
823 old_ident = silc_command_get_ident(cmd->payload);
824 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
825 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
827 /* Send WHOIS command to our router */
828 silc_server_packet_send(server, (SilcSocketConnection)
829 server->router->connection,
830 SILC_PACKET_COMMAND, cmd->packet->flags,
831 tmpbuf->data, tmpbuf->len, TRUE);
833 /* Reprocess this packet after received reply from router */
834 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
835 silc_command_get_ident(cmd->payload),
836 silc_server_command_whois,
837 silc_server_command_dup(cmd));
839 silc_command_set_ident(cmd->payload, old_ident);
840 silc_buffer_free(tmpbuf);
844 silc_server_command_whois_process(SilcServerCommandContext cmd)
846 SilcServer server = cmd->server;
847 char *nick = NULL, *server_name = NULL;
849 SilcClientEntry *clients = NULL, entry;
850 SilcClientID **client_id = NULL;
851 uint32 client_id_count = 0, clients_count = 0;
853 bool check_global = FALSE;
855 /* Parse the whois request */
856 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
857 &nick, &server_name, &count,
861 /* Send the WHOIS request to the router only if it included nickname.
862 Since nicknames can be expanded into many clients we need to send it
863 to router. If the WHOIS included only client ID's we will check them
864 first locally since we just might have them. */
865 if (nick && !client_id_count && cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
866 server->server_type == SILC_SERVER && !cmd->pending &&
867 !server->standalone) {
868 silc_server_command_whois_send_router(cmd);
873 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
875 else if (server->server_type != SILC_SERVER)
878 /* Get all clients matching that ID or nickname from local list */
879 if (client_id_count) {
880 /* Check all Client ID's received in the command packet */
881 for (i = 0; i < client_id_count; i++) {
882 entry = silc_idlist_find_client_by_id(server->local_list,
883 client_id[i], TRUE, NULL);
884 if (!entry && check_global)
885 entry = silc_idlist_find_client_by_id(server->global_list,
886 client_id[i], TRUE, NULL);
888 clients = silc_realloc(clients, sizeof(*clients) *
889 (clients_count + 1));
890 clients[clients_count++] = entry;
892 /* If we are normal server and did not send the request first to router
893 do it now, since we do not have the Client ID information. */
894 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
895 server->server_type == SILC_SERVER && !cmd->pending &&
896 !server->standalone) {
897 silc_server_command_whois_send_router(cmd);
904 /* Find by nickname */
905 if (!silc_idlist_get_clients_by_hash(server->local_list,
906 nick, server->md5hash,
907 &clients, &clients_count))
908 silc_idlist_get_clients_by_nickname(server->local_list,
910 &clients, &clients_count);
912 if (!silc_idlist_get_clients_by_hash(server->global_list,
913 nick, server->md5hash,
914 &clients, &clients_count))
915 silc_idlist_get_clients_by_nickname(server->global_list,
917 &clients, &clients_count);
922 /* If we are normal server and did not send the request first to router
923 do it now, since we do not have the information. */
924 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
925 server->server_type == SILC_SERVER && !cmd->pending &&
926 !server->standalone) {
927 silc_server_command_whois_send_router(cmd);
932 /* Such client(s) really does not exist in the SILC network. */
933 if (!client_id_count) {
934 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
935 SILC_STATUS_ERR_NO_SUCH_NICK,
936 3, nick, strlen(nick));
938 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
939 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
940 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
941 2, idp->data, idp->len);
942 silc_buffer_free(idp);
947 /* Router always finds the client entry if it exists in the SILC network.
948 However, it might be incomplete entry and does not include all the
949 mandatory fields that WHOIS command reply requires. Check for these and
950 make query from the server who owns the client if some fields are
952 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
957 /* Send the command reply */
958 silc_server_command_whois_send_reply(cmd, clients, clients_count,
959 count, nick, client_id);
962 if (client_id_count) {
963 for (i = 0; i < client_id_count; i++)
964 silc_free(client_id[i]);
965 silc_free(client_id);
969 silc_free(server_name);
974 /* Server side of command WHOIS. Processes user's query and sends found
975 results as command replies back to the client. */
977 SILC_SERVER_CMD_FUNC(whois)
979 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
982 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 3328);
984 ret = silc_server_command_whois_process(cmd);
985 silc_server_command_free(cmd);
988 /******************************************************************************
992 ******************************************************************************/
995 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
1003 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1005 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
1006 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1010 /* Get the nickname@server string and parse it. */
1011 silc_parse_userfqdn(tmp, nickname, server_name);
1013 /* Get the max count of reply messages allowed */
1014 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1024 silc_server_command_whowas_check(SilcServerCommandContext cmd,
1025 SilcClientEntry *clients,
1026 uint32 clients_count)
1028 SilcServer server = cmd->server;
1030 SilcClientEntry entry;
1032 for (i = 0; i < clients_count; i++) {
1035 if (!entry->nickname || !entry->username) {
1042 old_ident = silc_command_get_ident(cmd->payload);
1043 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1044 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1046 /* Send WHOWAS command */
1047 silc_server_packet_send(server, entry->router->connection,
1048 SILC_PACKET_COMMAND, cmd->packet->flags,
1049 tmpbuf->data, tmpbuf->len, TRUE);
1051 /* Reprocess this packet after received reply */
1052 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1053 silc_command_get_ident(cmd->payload),
1054 silc_server_command_whowas,
1055 silc_server_command_dup(cmd));
1056 cmd->pending = TRUE;
1058 silc_command_set_ident(cmd->payload, old_ident);
1060 silc_buffer_free(tmpbuf);
1069 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1070 SilcClientEntry *clients,
1071 uint32 clients_count)
1073 SilcServer server = cmd->server;
1075 int i, count = 0, len;
1076 SilcBuffer packet, idp;
1077 SilcClientEntry entry = NULL;
1078 SilcCommandStatus status;
1079 uint16 ident = silc_command_get_ident(cmd->payload);
1081 char nh[256], uh[256];
1083 status = SILC_STATUS_OK;
1084 if (clients_count > 1)
1085 status = SILC_STATUS_LIST_START;
1087 for (i = 0; i < clients_count; i++) {
1090 /* We will take only clients that are not valid anymore. They are the
1091 ones that are not registered anymore but still have a ID. They
1092 have disconnected us, and thus valid for WHOWAS. */
1093 if (entry->data.status & SILC_IDLIST_STATUS_REGISTERED || !entry->id)
1096 if (count && i - 1 == count)
1101 if (clients_count > 2)
1102 status = SILC_STATUS_LIST_ITEM;
1103 if (clients_count > 1 && i == clients_count - 1)
1104 status = SILC_STATUS_LIST_END;
1106 /* Send WHOWAS reply */
1107 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1108 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1109 memset(uh, 0, sizeof(uh));
1110 memset(nh, 0, sizeof(nh));
1112 strncat(nh, entry->nickname, strlen(entry->nickname));
1113 if (!strchr(entry->nickname, '@')) {
1114 strncat(nh, "@", 1);
1115 if (entry->servername) {
1116 strncat(nh, entry->servername, strlen(entry->servername));
1118 len = entry->router ? strlen(entry->router->server_name) :
1119 strlen(server->server_name);
1120 strncat(nh, entry->router ? entry->router->server_name :
1121 server->server_name, len);
1125 strncat(uh, entry->username, strlen(entry->username));
1126 if (!strchr(entry->username, '@')) {
1127 strncat(uh, "@", 1);
1128 strcat(uh, "*private*");
1132 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1134 2, idp->data, idp->len,
1139 strlen(entry->userinfo) : 0);
1140 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1141 0, packet->data, packet->len, FALSE);
1143 silc_buffer_free(packet);
1144 silc_buffer_free(idp);
1147 if (found == FALSE && entry)
1148 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1149 SILC_STATUS_ERR_NO_SUCH_NICK,
1151 strlen(entry->nickname));
1155 silc_server_command_whowas_process(SilcServerCommandContext cmd)
1157 SilcServer server = cmd->server;
1158 char *nick = NULL, *server_name = NULL;
1160 SilcClientEntry *clients = NULL;
1161 uint32 clients_count = 0;
1163 bool check_global = FALSE;
1165 /* Protocol dictates that we must always send the received WHOWAS request
1166 to our router if we are normal server, so let's do it now unless we
1167 are standalone. We will not send any replies to the client until we
1168 have received reply from the router. */
1169 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1170 server->server_type == SILC_SERVER && !cmd->pending &&
1171 !server->standalone) {
1175 old_ident = silc_command_get_ident(cmd->payload);
1176 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1177 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1179 /* Send WHOWAS command to our router */
1180 silc_server_packet_send(server, (SilcSocketConnection)
1181 server->router->connection,
1182 SILC_PACKET_COMMAND, cmd->packet->flags,
1183 tmpbuf->data, tmpbuf->len, TRUE);
1185 /* Reprocess this packet after received reply from router */
1186 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1187 silc_command_get_ident(cmd->payload),
1188 silc_server_command_whowas,
1189 silc_server_command_dup(cmd));
1190 cmd->pending = TRUE;
1192 silc_command_set_ident(cmd->payload, old_ident);
1194 silc_buffer_free(tmpbuf);
1199 /* We are ready to process the command request. Let's search for the
1200 requested client and send reply to the requesting client. */
1202 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1203 check_global = TRUE;
1204 else if (server->server_type != SILC_SERVER)
1205 check_global = TRUE;
1207 /* Parse the whowas request */
1208 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1211 /* Get all clients matching that nickname from local list */
1212 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1214 &clients, &clients_count))
1215 silc_idlist_get_clients_by_hash(server->local_list,
1216 nick, server->md5hash,
1217 &clients, &clients_count);
1219 /* Check global list as well */
1221 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1223 &clients, &clients_count))
1224 silc_idlist_get_clients_by_hash(server->global_list,
1225 nick, server->md5hash,
1226 &clients, &clients_count);
1230 /* Such a client really does not exist in the SILC network. */
1231 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1232 SILC_STATUS_ERR_NO_SUCH_NICK,
1233 3, nick, strlen(nick));
1237 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1242 /* Send the command reply to the client */
1243 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1248 silc_free(server_name);
1252 /* Server side of command WHOWAS. */
1254 SILC_SERVER_CMD_FUNC(whowas)
1256 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1259 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1261 ret = silc_server_command_whowas_process(cmd);
1262 silc_server_command_free(cmd);
1265 /******************************************************************************
1269 ******************************************************************************/
1272 silc_server_command_identify_send_router(SilcServerCommandContext cmd)
1274 SilcServer server = cmd->server;
1278 old_ident = silc_command_get_ident(cmd->payload);
1279 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1280 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1282 /* Send IDENTIFY command to our router */
1283 silc_server_packet_send(server, (SilcSocketConnection)
1284 server->router->connection,
1285 SILC_PACKET_COMMAND, cmd->packet->flags,
1286 tmpbuf->data, tmpbuf->len, TRUE);
1288 /* Reprocess this packet after received reply from router */
1289 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1290 silc_command_get_ident(cmd->payload),
1291 silc_server_command_identify,
1292 silc_server_command_dup(cmd));
1293 cmd->pending = TRUE;
1294 silc_command_set_ident(cmd->payload, old_ident);
1295 silc_buffer_free(tmpbuf);
1299 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1300 SilcClientEntry **clients,
1301 uint32 *clients_count,
1302 SilcServerEntry **servers,
1303 uint32 *servers_count,
1304 SilcChannelEntry **channels,
1305 uint32 *channels_count,
1308 SilcServer server = cmd->server;
1311 uint32 argc = silc_argument_get_arg_num(cmd->args);
1313 bool check_global = FALSE;
1318 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1319 check_global = TRUE;
1320 else if (server->server_type != SILC_SERVER)
1321 check_global = TRUE;
1323 /* If ID Payload is in the command it must be used instead of names */
1324 tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1326 /* No ID, get the names. */
1328 /* If we are normal server and have not resolved information from
1329 router yet, do so now. */
1330 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1331 server->server_type == SILC_SERVER && !cmd->pending &&
1332 !server->standalone) {
1333 silc_server_command_identify_send_router(cmd);
1337 /* Try to get nickname@server. */
1338 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1341 char *nick_server = NULL;
1343 silc_parse_userfqdn(tmp, &nick, &nick_server);
1345 if (!silc_idlist_get_clients_by_hash(server->local_list,
1346 nick, server->md5hash,
1347 clients, clients_count))
1348 silc_idlist_get_clients_by_nickname(server->local_list,
1350 clients, clients_count);
1352 if (!silc_idlist_get_clients_by_hash(server->global_list,
1353 nick, server->md5hash,
1354 clients, clients_count))
1355 silc_idlist_get_clients_by_nickname(server->global_list,
1357 clients, clients_count);
1361 silc_free(nick_server);
1364 /* the nickname does not exist, send error reply */
1365 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1366 SILC_STATUS_ERR_NO_SUCH_NICK,
1367 3, tmp, strlen(tmp));
1372 /* Try to get server name */
1373 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1375 entry = silc_idlist_find_server_by_name(server->local_list,
1377 if (!entry && check_global)
1378 entry = silc_idlist_find_server_by_name(server->global_list,
1381 *servers = silc_realloc(*servers, sizeof(**servers) *
1382 (*servers_count + 1));
1383 (*servers)[(*servers_count)++] = entry;
1387 /* the server does not exist, send error reply */
1388 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1389 SILC_STATUS_ERR_NO_SUCH_SERVER,
1390 3, tmp, strlen(tmp));
1395 /* Try to get channel name */
1396 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1398 entry = silc_idlist_find_channel_by_name(server->local_list,
1400 if (!entry && check_global)
1401 entry = silc_idlist_find_channel_by_name(server->global_list,
1404 *channels = silc_realloc(*channels, sizeof(**channels) *
1405 (*channels_count + 1));
1406 (*channels)[(*channels_count)++] = entry;
1410 /* The channel does not exist, send error reply */
1411 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1412 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1413 3, tmp, strlen(tmp));
1418 if (!(*clients) && !(*servers) && !(*channels)) {
1419 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1420 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1424 /* Command includes ID, we must use that. Also check whether the command
1425 has more than one ID set - take them all. */
1427 /* Take all ID's from the command packet */
1428 for (i = 0; i < argc; i++) {
1431 tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
1435 idp = silc_id_payload_parse(tmp, len);
1437 silc_free(*clients);
1438 silc_free(*servers);
1439 silc_free(*channels);
1440 silc_server_command_send_status_reply(
1441 cmd, SILC_COMMAND_IDENTIFY,
1442 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1446 id = silc_id_payload_get_id(idp);
1448 switch (silc_id_payload_get_type(idp)) {
1450 case SILC_ID_CLIENT:
1451 entry = (void *)silc_idlist_find_client_by_id(server->local_list,
1453 if (!entry && check_global)
1454 entry = (void *)silc_idlist_find_client_by_id(server->global_list,
1457 *clients = silc_realloc(*clients, sizeof(**clients) *
1458 (*clients_count + 1));
1459 (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
1461 /* If we are normal server and have not resolved information from
1462 router yet, do so now. */
1463 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1464 server->server_type == SILC_SERVER && !cmd->pending &&
1465 !server->standalone) {
1466 silc_server_command_identify_send_router(cmd);
1467 silc_free(*clients);
1468 silc_free(*servers);
1469 silc_free(*channels);
1472 silc_server_command_send_status_data(
1473 cmd, SILC_COMMAND_IDENTIFY,
1474 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1482 case SILC_ID_SERVER:
1483 entry = (void *)silc_idlist_find_server_by_id(server->local_list,
1485 if (!entry && check_global)
1486 entry = (void *)silc_idlist_find_server_by_id(server->global_list,
1489 *servers = silc_realloc(*servers, sizeof(**servers) *
1490 (*servers_count + 1));
1491 (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
1493 /* If we are normal server and have not resolved information from
1494 router yet, do so now. */
1495 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1496 server->server_type == SILC_SERVER && !cmd->pending &&
1497 !server->standalone) {
1498 silc_server_command_identify_send_router(cmd);
1499 silc_free(*clients);
1500 silc_free(*servers);
1501 silc_free(*channels);
1504 silc_server_command_send_status_data(
1505 cmd, SILC_COMMAND_IDENTIFY,
1506 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
1513 case SILC_ID_CHANNEL:
1514 entry = (void *)silc_idlist_find_channel_by_id(server->local_list,
1516 if (!entry && check_global)
1517 entry = (void *)silc_idlist_find_channel_by_id(server->global_list,
1520 *channels = silc_realloc(*channels, sizeof(**channels) *
1521 (*channels_count + 1));
1522 (*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
1524 /* If we are normal server and have not resolved information from
1525 router yet, do so now. */
1526 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1527 server->server_type == SILC_SERVER && !cmd->pending &&
1528 !server->standalone) {
1529 silc_server_command_identify_send_router(cmd);
1530 silc_free(*clients);
1531 silc_free(*servers);
1532 silc_free(*channels);
1535 silc_server_command_send_status_data(
1536 cmd, SILC_COMMAND_IDENTIFY,
1537 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
1550 silc_free(*clients);
1551 silc_free(*servers);
1552 silc_free(*channels);
1556 /* Get the max count of reply messages allowed */
1557 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1566 /* Checks that all mandatory fields in client entry are present. If not
1567 then send WHOIS request to the server who owns the client. We use
1568 WHOIS because we want to get as much information as possible at once. */
1571 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1572 SilcClientEntry *clients,
1573 uint32 clients_count)
1575 SilcServer server = cmd->server;
1576 SilcClientEntry entry;
1577 SilcServerResolveContext resolve = NULL, r = NULL;
1578 uint32 resolve_count = 0;
1582 for (i = 0; i < clients_count; i++) {
1587 if (entry->nickname ||
1588 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1592 /* If we are normal server, and we've not resolved this client from
1593 router and it is global client, we'll check whether it is on some
1594 channel. If not then we cannot be sure about its validity, and
1595 we'll resolve it from router. */
1596 if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
1597 entry->connection || silc_hash_table_count(entry->channels))
1601 /* We need to resolve this entry since it is not complete */
1603 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1604 /* The entry is being resolved (and we are not the resolver) so attach
1605 to the command reply and we're done with this one. */
1606 silc_server_command_pending(server, SILC_COMMAND_NONE,
1607 entry->resolve_cmd_ident,
1608 silc_server_command_identify,
1609 silc_server_command_dup(cmd));
1612 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1613 /* We've resolved this and it still is not ready. We'll return
1614 and are that this will be handled again after it is resolved. */
1615 for (i = 0; i < resolve_count; i++) {
1616 for (k = 0; k < r->res_argc; k++)
1617 silc_free(r->res_argv[k]);
1618 silc_free(r->res_argv);
1619 silc_free(r->res_argv_lens);
1620 silc_free(r->res_argv_types);
1625 /* We'll resolve this client */
1629 for (k = 0; k < resolve_count; k++) {
1630 if (resolve[k].router == entry->router) {
1637 resolve = silc_realloc(resolve, sizeof(*resolve) *
1638 (resolve_count + 1));
1639 r = &resolve[resolve_count];
1640 memset(r, 0, sizeof(*r));
1641 r->router = entry->router;
1642 r->ident = ++server->cmd_ident;
1646 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1648 r->res_argv_lens = silc_realloc(r->res_argv_lens,
1649 sizeof(*r->res_argv_lens) *
1651 r->res_argv_types = silc_realloc(r->res_argv_types,
1652 sizeof(*r->res_argv_types) *
1654 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1655 r->res_argv[r->res_argc] = silc_calloc(idp->len,
1656 sizeof(**r->res_argv));
1657 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1658 r->res_argv_lens[r->res_argc] = idp->len;
1659 r->res_argv_types[r->res_argc] = r->res_argc + 3;
1661 silc_buffer_free(idp);
1663 entry->resolve_cmd_ident = r->ident;
1664 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1665 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1670 /* Do the resolving */
1671 for (i = 0; i < resolve_count; i++) {
1676 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1677 now anyway so make it a good one. */
1678 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1679 r->res_argc, r->res_argv,
1683 silc_server_packet_send(server, r->router->connection,
1684 SILC_PACKET_COMMAND, cmd->packet->flags,
1685 res_cmd->data, res_cmd->len, FALSE);
1687 /* Reprocess this packet after received reply */
1688 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1690 silc_server_command_identify,
1691 silc_server_command_dup(cmd));
1692 cmd->pending = TRUE;
1694 silc_buffer_free(res_cmd);
1695 for (k = 0; k < r->res_argc; k++)
1696 silc_free(r->res_argv[k]);
1697 silc_free(r->res_argv);
1698 silc_free(r->res_argv_lens);
1699 silc_free(r->res_argv_types);
1708 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1709 SilcClientEntry *clients,
1710 uint32 clients_count,
1711 SilcServerEntry *servers,
1712 uint32 servers_count,
1713 SilcChannelEntry *channels,
1714 uint32 channels_count,
1717 SilcServer server = cmd->server;
1718 int i, k, len, valid_count;
1719 SilcBuffer packet, idp;
1720 SilcCommandStatus status;
1721 uint16 ident = silc_command_get_ident(cmd->payload);
1722 char nh[256], uh[256];
1723 SilcSocketConnection hsock;
1725 status = SILC_STATUS_OK;
1728 SilcClientEntry entry;
1730 /* Process only valid entries. */
1732 for (i = 0; i < clients_count; i++) {
1733 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1740 /* No valid entries found at all, just send error */
1743 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1745 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1746 SILC_STATUS_ERR_NO_SUCH_NICK,
1747 3, tmp, strlen(tmp));
1749 tmp = silc_argument_get_arg_type(cmd->args, 5, (uint32 *)&len);
1750 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1751 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1757 /* Process all valid client entries and send command replies */
1759 if (valid_count > 1)
1760 status = SILC_STATUS_LIST_START;
1762 for (i = 0, k = 0; i < clients_count; i++) {
1768 status = SILC_STATUS_LIST_ITEM;
1769 if (valid_count > 1 && k == valid_count - 1
1770 && !servers_count && !channels_count)
1771 status = SILC_STATUS_LIST_END;
1772 if (count && k - 1 == count)
1773 status = SILC_STATUS_LIST_END;
1774 if (count && k - 1 > count)
1777 /* Send IDENTIFY reply */
1779 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1780 memset(uh, 0, sizeof(uh));
1781 memset(nh, 0, sizeof(nh));
1782 strncat(nh, entry->nickname, strlen(entry->nickname));
1783 if (!strchr(entry->nickname, '@')) {
1784 strncat(nh, "@", 1);
1785 if (entry->servername) {
1786 strncat(nh, entry->servername, strlen(entry->servername));
1788 len = entry->router ? strlen(entry->router->server_name) :
1789 strlen(server->server_name);
1790 strncat(nh, entry->router ? entry->router->server_name :
1791 server->server_name, len);
1795 if (!entry->username) {
1796 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1798 2, idp->data, idp->len,
1801 strncat(uh, entry->username, strlen(entry->username));
1802 if (!strchr(entry->username, '@')) {
1803 strncat(uh, "@", 1);
1804 hsock = (SilcSocketConnection)entry->connection;
1805 len = strlen(hsock->hostname);
1806 strncat(uh, hsock->hostname, len);
1809 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1811 2, idp->data, idp->len,
1816 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1817 0, packet->data, packet->len, FALSE);
1819 silc_buffer_free(packet);
1820 silc_buffer_free(idp);
1827 SilcServerEntry entry;
1829 if (status == SILC_STATUS_OK && servers_count > 1)
1830 status = SILC_STATUS_LIST_START;
1832 for (i = 0, k = 0; i < servers_count; i++) {
1836 status = SILC_STATUS_LIST_ITEM;
1837 if (servers_count > 1 && k == servers_count - 1 && !channels_count)
1838 status = SILC_STATUS_LIST_END;
1839 if (count && k - 1 == count)
1840 status = SILC_STATUS_LIST_END;
1841 if (count && k - 1 > count)
1844 /* Send IDENTIFY reply */
1845 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1847 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1849 2, idp->data, idp->len,
1850 3, entry->server_name,
1851 entry->server_name ?
1852 strlen(entry->server_name) : 0);
1853 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1854 0, packet->data, packet->len, FALSE);
1856 silc_buffer_free(packet);
1857 silc_buffer_free(idp);
1864 SilcChannelEntry entry;
1866 if (status == SILC_STATUS_OK && channels_count > 1)
1867 status = SILC_STATUS_LIST_START;
1869 for (i = 0, k = 0; i < channels_count; i++) {
1870 entry = channels[i];
1873 status = SILC_STATUS_LIST_ITEM;
1874 if (channels_count > 1 && k == channels_count - 1)
1875 status = SILC_STATUS_LIST_END;
1876 if (count && k - 1 == count)
1877 status = SILC_STATUS_LIST_END;
1878 if (count && k - 1 > count)
1881 /* Send IDENTIFY reply */
1882 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1884 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1886 2, idp->data, idp->len,
1887 3, entry->channel_name,
1888 entry->channel_name ?
1889 strlen(entry->channel_name): 0);
1890 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1891 0, packet->data, packet->len, FALSE);
1893 silc_buffer_free(packet);
1894 silc_buffer_free(idp);
1902 silc_server_command_identify_process(SilcServerCommandContext cmd)
1906 SilcClientEntry *clients = NULL;
1907 SilcServerEntry *servers = NULL;
1908 SilcChannelEntry *channels = NULL;
1909 uint32 clients_count = 0, servers_count = 0, channels_count = 0;
1911 /* Parse the IDENTIFY request */
1912 ret = silc_server_command_identify_parse(cmd,
1913 &clients, &clients_count,
1914 &servers, &servers_count,
1915 &channels, &channels_count,
1921 /* Check that all mandatory fields are present and request those data
1922 from the server who owns the client if necessary. */
1923 if (clients && !silc_server_command_identify_check_client(cmd, clients,
1929 /* Send the command reply to the client */
1930 silc_server_command_identify_send_reply(cmd,
1931 clients, clients_count,
1932 servers, servers_count,
1933 channels, channels_count,
1939 silc_free(channels);
1943 SILC_SERVER_CMD_FUNC(identify)
1945 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1948 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1950 ret = silc_server_command_identify_process(cmd);
1951 silc_server_command_free(cmd);
1954 /* Checks string for bad characters and returns TRUE if they are found. */
1956 static int silc_server_command_bad_chars(char *nick)
1960 for (i = 0; i < strlen(nick); i++) {
1961 if (!isascii(nick[i]))
1963 if (nick[i] <= 32) return TRUE;
1964 if (nick[i] == ' ') return TRUE;
1965 if (nick[i] == '*') return TRUE;
1966 if (nick[i] == '?') return TRUE;
1967 if (nick[i] == ',') return TRUE;
1973 /* Server side of command NICK. Sets nickname for user. Setting
1974 nickname causes generation of a new client ID for the client. The
1975 new client ID is sent to the client after changing the nickname. */
1977 SILC_SERVER_CMD_FUNC(nick)
1979 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1980 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1981 SilcServer server = cmd->server;
1982 SilcBuffer packet, nidp, oidp = NULL;
1983 SilcClientID *new_id;
1985 uint16 ident = silc_command_get_ident(cmd->payload);
1988 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1991 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
1993 /* Check nickname */
1994 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1995 if (silc_server_command_bad_chars(nick) == TRUE) {
1996 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1997 SILC_STATUS_ERR_BAD_NICKNAME);
2001 if (strlen(nick) > 128)
2004 /* Check for same nickname */
2005 if (!strcmp(client->nickname, nick)) {
2006 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2010 /* Create new Client ID */
2011 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
2013 cmd->server->md5hash, nick,
2016 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2019 /* Send notify about nickname change to our router. We send the new
2020 ID and ask to replace it with the old one. If we are router the
2021 packet is broadcasted. Send NICK_CHANGE notify. */
2022 if (!server->standalone)
2023 silc_server_send_notify_nick_change(server, server->router->connection,
2024 server->server_type == SILC_SERVER ?
2025 FALSE : TRUE, client->id,
2028 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2030 /* Remove old cache entry */
2031 silc_idcache_del_by_context(server->local_list->clients, client);
2034 silc_free(client->id);
2036 /* Save the nickname as this client is our local client */
2037 silc_free(client->nickname);
2039 client->nickname = strdup(nick);
2040 client->id = new_id;
2042 /* Update client cache */
2043 silc_idcache_add(server->local_list->clients, client->nickname,
2044 client->id, (void *)client, 0, NULL);
2046 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2048 /* Send NICK_CHANGE notify to the client's channels */
2049 silc_server_send_notify_on_channels(server, NULL, client,
2050 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
2051 oidp->data, oidp->len,
2052 nidp->data, nidp->len);
2055 /* Send the new Client ID as reply command back to client */
2056 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
2057 SILC_STATUS_OK, ident, 1,
2058 2, nidp->data, nidp->len);
2059 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2060 0, packet->data, packet->len, FALSE);
2062 silc_buffer_free(packet);
2063 silc_buffer_free(nidp);
2065 silc_buffer_free(oidp);
2068 silc_server_command_free(cmd);
2071 /* Sends the LIST command reply */
2074 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2075 SilcChannelEntry *lch,
2077 SilcChannelEntry *gch,
2081 SilcBuffer packet, idp;
2082 SilcChannelEntry entry;
2083 SilcCommandStatus status;
2084 uint16 ident = silc_command_get_ident(cmd->payload);
2086 unsigned char usercount[4];
2088 int valid_lcount = 0, valid_rcount = 0;
2090 for (i = 0; i < lch_count; i++) {
2091 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2096 for (i = 0; i < gch_count; i++) {
2097 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2103 status = SILC_STATUS_OK;
2104 if ((lch_count + gch_count) > 1)
2105 status = SILC_STATUS_LIST_START;
2108 for (i = 0, k = 0; i < lch_count; i++) {
2114 status = SILC_STATUS_LIST_ITEM;
2115 if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
2116 status = SILC_STATUS_LIST_END;
2118 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2120 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2121 topic = "*private*";
2122 memset(usercount, 0, sizeof(usercount));
2124 topic = entry->topic;
2125 users = silc_hash_table_count(entry->user_list);
2126 SILC_PUT32_MSB(users, usercount);
2129 /* Send the reply */
2131 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2133 2, idp->data, idp->len,
2134 3, entry->channel_name,
2135 strlen(entry->channel_name),
2136 4, topic, topic ? strlen(topic) : 0,
2138 silc_server_packet_send(cmd->server, cmd->sock,
2139 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2140 packet->len, FALSE);
2141 silc_buffer_free(packet);
2142 silc_buffer_free(idp);
2147 for (i = 0, k = 0; i < gch_count; i++) {
2153 status = SILC_STATUS_LIST_ITEM;
2154 if (valid_rcount > 1 && k == valid_rcount - 1)
2155 status = SILC_STATUS_LIST_END;
2157 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2159 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2160 topic = "*private*";
2161 memset(usercount, 0, sizeof(usercount));
2163 topic = entry->topic;
2164 users = silc_hash_table_count(entry->user_list);
2165 SILC_PUT32_MSB(users, usercount);
2168 /* Send the reply */
2170 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2172 2, idp->data, idp->len,
2173 3, entry->channel_name,
2174 strlen(entry->channel_name),
2175 4, topic, topic ? strlen(topic) : 0,
2177 silc_server_packet_send(cmd->server, cmd->sock,
2178 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2179 packet->len, FALSE);
2180 silc_buffer_free(packet);
2181 silc_buffer_free(idp);
2186 /* Server side of LIST command. This lists the channel of the requested
2187 server. Secret channels are not listed. */
2189 SILC_SERVER_CMD_FUNC(list)
2191 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2192 SilcServer server = cmd->server;
2193 SilcChannelID *channel_id = NULL;
2196 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2197 uint32 lch_count = 0, gch_count = 0;
2199 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2201 /* If we are normal server, send the command to router, since we
2202 want to know all channels in the network. */
2203 if (!cmd->pending && server->server_type == SILC_SERVER &&
2204 !server->standalone) {
2208 old_ident = silc_command_get_ident(cmd->payload);
2209 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2210 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2211 silc_server_packet_send(server, server->router->connection,
2212 SILC_PACKET_COMMAND, cmd->packet->flags,
2213 tmpbuf->data, tmpbuf->len, TRUE);
2215 /* Reprocess this packet after received reply from router */
2216 silc_server_command_pending(server, SILC_COMMAND_LIST,
2217 silc_command_get_ident(cmd->payload),
2218 silc_server_command_list,
2219 silc_server_command_dup(cmd));
2220 cmd->pending = TRUE;
2221 silc_command_set_ident(cmd->payload, old_ident);
2222 silc_buffer_free(tmpbuf);
2226 /* Get Channel ID */
2227 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2229 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2231 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2232 SILC_STATUS_ERR_NO_CHANNEL_ID);
2237 /* Get the channels from local list */
2238 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2241 /* Get the channels from global list */
2242 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2245 /* Send the reply */
2246 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2247 gchannels, gch_count);
2249 silc_free(lchannels);
2250 silc_free(gchannels);
2253 silc_server_command_free(cmd);
2256 /* Server side of TOPIC command. Sets topic for channel and/or returns
2257 current topic to client. */
2259 SILC_SERVER_CMD_FUNC(topic)
2261 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2262 SilcServer server = cmd->server;
2263 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2264 SilcChannelID *channel_id;
2265 SilcChannelEntry channel;
2266 SilcChannelClientEntry chl;
2267 SilcBuffer packet, idp;
2269 uint32 argc, tmp_len;
2270 uint16 ident = silc_command_get_ident(cmd->payload);
2272 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2274 argc = silc_argument_get_arg_num(cmd->args);
2276 /* Get Channel ID */
2277 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2279 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2280 SILC_STATUS_ERR_NO_CHANNEL_ID);
2283 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2285 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2286 SILC_STATUS_ERR_NO_CHANNEL_ID);
2290 /* Check whether the channel exists */
2291 channel = silc_idlist_find_channel_by_id(server->local_list,
2294 channel = silc_idlist_find_channel_by_id(server->global_list,
2297 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2298 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2305 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2307 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2308 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2312 if (strlen(tmp) > 256) {
2313 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2314 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2318 /* See whether the client is on channel and has rights to change topic */
2319 if (!silc_hash_table_find(channel->user_list, client, NULL,
2321 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2322 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2326 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2327 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2328 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2329 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2334 /* Set the topic for channel */
2335 silc_free(channel->topic);
2336 channel->topic = strdup(tmp);
2338 /* Send TOPIC_SET notify type to the network */
2339 if (!server->standalone)
2340 silc_server_send_notify_topic_set(server, server->router->connection,
2341 server->server_type == SILC_ROUTER ?
2342 TRUE : FALSE, channel,
2343 client->id, SILC_ID_CLIENT,
2346 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2348 /* Send notify about topic change to all clients on the channel */
2349 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2350 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2351 idp->data, idp->len,
2352 channel->topic, strlen(channel->topic));
2353 silc_buffer_free(idp);
2356 /* Send the topic to client as reply packet */
2357 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2358 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2359 SILC_STATUS_OK, ident, 2,
2360 2, idp->data, idp->len,
2363 strlen(channel->topic) : 0);
2364 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2365 0, packet->data, packet->len, FALSE);
2367 silc_buffer_free(packet);
2368 silc_buffer_free(idp);
2369 silc_free(channel_id);
2372 silc_server_command_free(cmd);
2375 /* Server side of INVITE command. Invites some client to join some channel.
2376 This command is also used to manage the invite list of the channel. */
2378 SILC_SERVER_CMD_FUNC(invite)
2380 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2381 SilcServer server = cmd->server;
2382 SilcSocketConnection sock = cmd->sock, dest_sock;
2383 SilcChannelClientEntry chl;
2384 SilcClientEntry sender, dest;
2385 SilcClientID *dest_id = NULL;
2386 SilcChannelEntry channel;
2387 SilcChannelID *channel_id = NULL;
2388 SilcIDListData idata;
2389 SilcBuffer idp, idp2, packet;
2390 unsigned char *tmp, *add, *del;
2392 uint16 ident = silc_command_get_ident(cmd->payload);
2394 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2396 /* Get Channel ID */
2397 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2399 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2400 SILC_STATUS_ERR_NO_CHANNEL_ID);
2403 channel_id = silc_id_payload_parse_id(tmp, len);
2405 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2406 SILC_STATUS_ERR_NO_CHANNEL_ID);
2410 /* Get the channel entry */
2411 channel = silc_idlist_find_channel_by_id(server->local_list,
2414 channel = silc_idlist_find_channel_by_id(server->global_list,
2417 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2418 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2423 /* Check whether the sender of this command is on the channel. */
2424 sender = (SilcClientEntry)sock->user_data;
2425 if (!silc_server_client_on_channel(sender, channel)) {
2426 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2427 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2431 /* Check whether the channel is invite-only channel. If yes then the
2432 sender of this command must be at least channel operator. */
2433 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2434 silc_hash_table_find(channel->user_list, sender, NULL, (void *)&chl);
2435 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2436 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2437 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2442 /* Get destination client ID */
2443 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2447 dest_id = silc_id_payload_parse_id(tmp, len);
2449 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2450 SILC_STATUS_ERR_NO_CLIENT_ID);
2454 /* Get the client entry */
2455 dest = silc_server_get_client_resolve(server, dest_id);
2457 if (server->server_type != SILC_SERVER) {
2458 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2459 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2463 /* The client info is being resolved. Reprocess this packet after
2464 receiving the reply to the query. */
2465 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2467 silc_server_command_invite,
2468 silc_server_command_dup(cmd));
2469 cmd->pending = TRUE;
2470 silc_free(channel_id);
2475 /* Check whether the requested client is already on the channel. */
2476 if (silc_server_client_on_channel(dest, channel)) {
2477 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2478 SILC_STATUS_ERR_USER_ON_CHANNEL);
2482 /* Get route to the client */
2483 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2485 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2486 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2490 memset(invite, 0, sizeof(invite));
2491 strncat(invite, dest->nickname, strlen(dest->nickname));
2492 strncat(invite, "!", 1);
2493 strncat(invite, dest->username, strlen(dest->username));
2494 if (!strchr(dest->username, '@')) {
2495 strncat(invite, "@", 1);
2496 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2499 len = strlen(invite);
2500 if (!channel->invite_list)
2501 channel->invite_list = silc_calloc(len + 2,
2502 sizeof(*channel->invite_list));
2504 channel->invite_list = silc_realloc(channel->invite_list,
2505 sizeof(*channel->invite_list) *
2507 strlen(channel->invite_list) + 2));
2508 strncat(channel->invite_list, invite, len);
2509 strncat(channel->invite_list, ",", 1);
2511 /* Send notify to the client that is invited to the channel */
2512 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2513 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2514 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2516 SILC_NOTIFY_TYPE_INVITE, 3,
2517 idp->data, idp->len,
2518 channel->channel_name,
2519 strlen(channel->channel_name),
2520 idp2->data, idp2->len);
2521 silc_buffer_free(idp);
2522 silc_buffer_free(idp2);
2525 /* Add the client to the invite list of the channel */
2526 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2528 if (!channel->invite_list)
2529 channel->invite_list = silc_calloc(len + 2,
2530 sizeof(*channel->invite_list));
2532 channel->invite_list = silc_realloc(channel->invite_list,
2533 sizeof(*channel->invite_list) *
2535 strlen(channel->invite_list) + 2));
2536 if (add[len - 1] == ',')
2537 add[len - 1] = '\0';
2539 strncat(channel->invite_list, add, len);
2540 strncat(channel->invite_list, ",", 1);
2543 /* Get the invite to be removed and remove it from the list */
2544 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2545 if (del && channel->invite_list) {
2546 char *start, *end, *n;
2548 if (!strncmp(channel->invite_list, del,
2549 strlen(channel->invite_list) - 1)) {
2550 silc_free(channel->invite_list);
2551 channel->invite_list = NULL;
2553 start = strstr(channel->invite_list, del);
2554 if (start && strlen(start) >= len) {
2556 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2557 strncat(n, channel->invite_list, start - channel->invite_list);
2558 strncat(n, end + 1, ((channel->invite_list +
2559 strlen(channel->invite_list)) - end) - 1);
2560 silc_free(channel->invite_list);
2561 channel->invite_list = n;
2566 /* Send notify to the primary router */
2567 if (!server->standalone)
2568 silc_server_send_notify_invite(server, server->router->connection,
2569 server->server_type == SILC_ROUTER ?
2570 TRUE : FALSE, channel,
2571 sender->id, add, del);
2573 /* Send command reply */
2574 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2578 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2579 SILC_STATUS_OK, ident, 2,
2581 3, channel->invite_list,
2582 channel->invite_list ?
2583 strlen(channel->invite_list) : 0);
2586 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2587 SILC_STATUS_OK, ident, 1,
2589 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2590 packet->data, packet->len, FALSE);
2591 silc_buffer_free(packet);
2595 silc_free(channel_id);
2596 silc_server_command_free(cmd);
2601 SilcSocketConnection sock;
2605 /* Quits connection to client. This gets called if client won't
2606 close the connection even when it has issued QUIT command. */
2608 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2610 QuitInternal q = (QuitInternal)context;
2612 /* Free all client specific data, such as client entry and entires
2613 on channels this client may be on. */
2614 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2616 q->sock->user_data = NULL;
2618 /* Close the connection on our side */
2619 silc_server_close_connection(q->server, q->sock);
2621 silc_free(q->signoff);
2625 /* Quits SILC session. This is the normal way to disconnect client. */
2627 SILC_SERVER_CMD_FUNC(quit)
2629 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2630 SilcServer server = cmd->server;
2631 SilcSocketConnection sock = cmd->sock;
2633 unsigned char *tmp = NULL;
2636 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2638 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2641 /* Get destination ID */
2642 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2646 q = silc_calloc(1, sizeof(*q));
2649 q->signoff = tmp ? strdup(tmp) : NULL;
2651 /* We quit the connection with little timeout */
2652 silc_schedule_task_add(server->schedule, sock->sock,
2653 silc_server_command_quit_cb, (void *)q,
2654 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2657 silc_server_command_free(cmd);
2660 /* Server side of command KILL. This command is used by router operator
2661 to remove an client from the SILC Network temporarily. */
2663 SILC_SERVER_CMD_FUNC(kill)
2665 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2666 SilcServer server = cmd->server;
2667 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2668 SilcClientEntry remote_client;
2669 SilcClientID *client_id;
2670 unsigned char *tmp, *comment;
2671 uint32 tmp_len, tmp_len2;
2673 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2675 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2678 /* KILL command works only on router */
2679 if (server->server_type != SILC_ROUTER) {
2680 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2681 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2685 /* Check whether client has the permissions. */
2686 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2687 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2688 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2692 /* Get the client ID */
2693 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2695 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2696 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2699 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2701 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2702 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2706 /* Get the client entry */
2707 remote_client = silc_idlist_find_client_by_id(server->local_list,
2708 client_id, TRUE, NULL);
2709 if (!remote_client) {
2710 remote_client = silc_idlist_find_client_by_id(server->global_list,
2711 client_id, TRUE, NULL);
2712 if (!remote_client) {
2713 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2714 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2720 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2724 /* Send reply to the sender */
2725 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2728 /* Send the KILL notify packets. First send it to the channel, then
2729 to our primary router and then directly to the client who is being
2730 killed right now. */
2732 /* Send KILLED notify to the channels. It is not sent to the client
2733 as it will be sent differently destined directly to the client and not
2735 silc_server_send_notify_on_channels(server, remote_client,
2736 remote_client, SILC_NOTIFY_TYPE_KILLED,
2739 comment, comment ? tmp_len2 : 0);
2741 /* Send KILLED notify to primary route */
2742 if (!server->standalone)
2743 silc_server_send_notify_killed(server, server->router->connection, TRUE,
2744 remote_client->id, comment);
2746 /* Send KILLED notify to the client directly */
2747 silc_server_send_notify_killed(server, remote_client->connection ?
2748 remote_client->connection :
2749 remote_client->router->connection, FALSE,
2750 remote_client->id, comment);
2752 /* Remove the client from all channels. This generates new keys to the
2753 channels as well. */
2754 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2757 /* Remove the client entry, If it is locally connected then we will also
2758 disconnect the client here */
2759 if (remote_client->connection) {
2760 /* Remove locally conneted client */
2761 SilcSocketConnection sock = remote_client->connection;
2762 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2763 silc_server_close_connection(server, sock);
2765 /* Remove remote client */
2766 if (!silc_idlist_del_client(server->global_list, remote_client))
2767 silc_idlist_del_client(server->local_list, remote_client);
2771 silc_server_command_free(cmd);
2774 /* Server side of command INFO. This sends information about us to
2775 the client. If client requested specific server we will send the
2776 command to that server. */
2778 SILC_SERVER_CMD_FUNC(info)
2780 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2781 SilcServer server = cmd->server;
2782 SilcBuffer packet, idp;
2785 char *dest_server, *server_info = NULL, *server_name;
2786 uint16 ident = silc_command_get_ident(cmd->payload);
2787 SilcServerEntry entry = NULL;
2788 SilcServerID *server_id = NULL;
2790 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2792 /* Get server name */
2793 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2796 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2798 server_id = silc_id_payload_parse_id(tmp, tmp_len);
2800 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2801 SILC_STATUS_ERR_NO_SERVER_ID);
2807 /* Check whether we have this server cached */
2808 entry = silc_idlist_find_server_by_id(server->local_list,
2809 server_id, TRUE, NULL);
2811 entry = silc_idlist_find_server_by_id(server->global_list,
2812 server_id, TRUE, NULL);
2813 if (!entry && server->server_type != SILC_SERVER) {
2814 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2815 SILC_STATUS_ERR_NO_SUCH_SERVER);
2821 /* Some buggy servers has sent request to router about themselves. */
2822 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2825 if ((!dest_server && !server_id && !entry) || (entry &&
2826 entry == server->id_entry) ||
2827 (dest_server && !cmd->pending &&
2828 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2829 /* Send our reply */
2830 char info_string[256];
2832 memset(info_string, 0, sizeof(info_string));
2833 snprintf(info_string, sizeof(info_string),
2834 "location: %s server: %s admin: %s <%s>",
2835 server->config->admin_info->location,
2836 server->config->admin_info->server_type,
2837 server->config->admin_info->admin_name,
2838 server->config->admin_info->admin_email);
2840 server_info = info_string;
2841 entry = server->id_entry;
2843 /* Check whether we have this server cached */
2844 if (!entry && dest_server) {
2845 entry = silc_idlist_find_server_by_name(server->global_list,
2846 dest_server, TRUE, NULL);
2848 entry = silc_idlist_find_server_by_name(server->local_list,
2849 dest_server, TRUE, NULL);
2853 if (!cmd->pending &&
2854 server->server_type != SILC_SERVER && entry && !entry->server_info) {
2855 /* Send to the server */
2859 old_ident = silc_command_get_ident(cmd->payload);
2860 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2861 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2863 silc_server_packet_send(server, entry->connection,
2864 SILC_PACKET_COMMAND, cmd->packet->flags,
2865 tmpbuf->data, tmpbuf->len, TRUE);
2867 /* Reprocess this packet after received reply from router */
2868 silc_server_command_pending(server, SILC_COMMAND_INFO,
2869 silc_command_get_ident(cmd->payload),
2870 silc_server_command_info,
2871 silc_server_command_dup(cmd));
2872 cmd->pending = TRUE;
2873 silc_command_set_ident(cmd->payload, old_ident);
2874 silc_buffer_free(tmpbuf);
2878 if (!entry && !cmd->pending && !server->standalone) {
2879 /* Send to the primary router */
2883 old_ident = silc_command_get_ident(cmd->payload);
2884 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2885 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2887 silc_server_packet_send(server, server->router->connection,
2888 SILC_PACKET_COMMAND, cmd->packet->flags,
2889 tmpbuf->data, tmpbuf->len, TRUE);
2891 /* Reprocess this packet after received reply from router */
2892 silc_server_command_pending(server, SILC_COMMAND_INFO,
2893 silc_command_get_ident(cmd->payload),
2894 silc_server_command_info,
2895 silc_server_command_dup(cmd));
2896 cmd->pending = TRUE;
2897 silc_command_set_ident(cmd->payload, old_ident);
2898 silc_buffer_free(tmpbuf);
2903 silc_free(server_id);
2906 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2907 SILC_STATUS_ERR_NO_SUCH_SERVER);
2911 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2913 server_info = entry->server_info;
2914 server_name = entry->server_name;
2916 /* Send the reply */
2917 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2918 SILC_STATUS_OK, ident, 3,
2919 2, idp->data, idp->len,
2921 strlen(server_name),
2924 strlen(server_info) : 0);
2925 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2926 packet->data, packet->len, FALSE);
2928 silc_buffer_free(packet);
2929 silc_buffer_free(idp);
2932 silc_server_command_free(cmd);
2935 /* Server side of command PING. This just replies to the ping. */
2937 SILC_SERVER_CMD_FUNC(ping)
2939 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2940 SilcServer server = cmd->server;
2945 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
2948 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2950 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2951 SILC_STATUS_ERR_NO_SERVER_ID);
2954 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2958 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2959 /* Send our reply */
2960 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2963 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2964 SILC_STATUS_ERR_NO_SUCH_SERVER);
2971 silc_server_command_free(cmd);
2974 /* Internal routine to join channel. The channel sent to this function
2975 has been either created or resolved from ID lists. This joins the sent
2976 client to the channel. */
2978 static void silc_server_command_join_channel(SilcServer server,
2979 SilcServerCommandContext cmd,
2980 SilcChannelEntry channel,
2981 SilcClientID *client_id,
2985 const unsigned char *auth,
2988 SilcSocketConnection sock = cmd->sock;
2990 uint32 tmp_len, user_count;
2991 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
2992 SilcClientEntry client;
2993 SilcChannelClientEntry chl;
2994 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
2995 uint16 ident = silc_command_get_ident(cmd->payload);
2996 char check[512], check2[512];
2997 bool founder = FALSE;
2999 SILC_LOG_DEBUG(("Start"));
3004 /* Get the client entry */
3005 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3006 client = (SilcClientEntry)sock->user_data;
3008 client = silc_server_get_client_resolve(server, client_id);
3013 /* The client info is being resolved. Reprocess this packet after
3014 receiving the reply to the query. */
3015 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
3017 silc_server_command_join,
3018 silc_server_command_dup(cmd));
3019 cmd->pending = TRUE;
3023 cmd->pending = FALSE;
3027 * Check founder auth payload if provided. If client can gain founder
3028 * privileges it can override various conditions on joining the channel,
3029 * and can have directly the founder mode set on the channel.
3031 if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3032 SilcIDListData idata = (SilcIDListData)client;
3034 if (channel->founder_key && idata->public_key &&
3035 silc_pkcs_public_key_compare(channel->founder_key,
3036 idata->public_key)) {
3037 void *auth_data = (channel->founder_method == SILC_AUTH_PASSWORD ?
3038 (void *)channel->founder_passwd :
3039 (void *)channel->founder_key);
3040 uint32 auth_data_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
3041 channel->founder_passwd_len : 0);
3043 /* Check whether the client is to become founder */
3044 if (silc_auth_verify_data(auth, auth_len, channel->founder_method,
3045 auth_data, auth_data_len,
3046 idata->hash, client->id, SILC_ID_CLIENT)) {
3047 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3054 * Check channel modes
3058 memset(check, 0, sizeof(check));
3059 memset(check2, 0, sizeof(check2));
3060 strncat(check, client->nickname, strlen(client->nickname));
3061 strncat(check, "!", 1);
3062 strncat(check, client->username, strlen(client->username));
3063 if (!strchr(client->username, '@')) {
3064 strncat(check, "@", 1);
3065 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3068 strncat(check2, client->nickname, strlen(client->nickname));
3069 if (!strchr(client->nickname, '@')) {
3070 strncat(check2, "@", 1);
3071 strncat(check2, server->server_name, strlen(server->server_name));
3073 strncat(check2, "!", 1);
3074 strncat(check2, client->username, strlen(client->username));
3075 if (!strchr(client->username, '@')) {
3076 strncat(check2, "@", 1);
3077 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3080 /* Check invite list if channel is invite-only channel */
3081 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3082 if (!channel->invite_list ||
3083 (!silc_string_match(channel->invite_list, check) &&
3084 !silc_string_match(channel->invite_list, check2))) {
3085 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3086 SILC_STATUS_ERR_NOT_INVITED);
3091 /* Check ban list if it exists. If the client's nickname, server,
3092 username and/or hostname is in the ban list the access to the
3093 channel is denied. */
3094 if (channel->ban_list) {
3095 if (silc_string_match(channel->ban_list, check) ||
3096 silc_string_match(channel->ban_list, check2)) {
3097 silc_server_command_send_status_reply(
3098 cmd, SILC_COMMAND_JOIN,
3099 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
3104 /* Check user count limit if set. */
3105 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3106 if (silc_hash_table_count(channel->user_list) + 1 >
3107 channel->user_limit) {
3108 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3109 SILC_STATUS_ERR_CHANNEL_IS_FULL);
3115 /* Check the channel passphrase if set. */
3116 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3117 /* Get passphrase */
3118 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3120 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
3121 memcpy(passphrase, tmp, tmp_len);
3124 if (!passphrase || !channel->passphrase ||
3125 memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3126 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3127 SILC_STATUS_ERR_BAD_PASSWORD);
3133 * Client is allowed to join to the channel. Make it happen.
3136 /* Check whether the client already is on the channel */
3137 if (silc_server_client_on_channel(client, channel)) {
3138 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3139 SILC_STATUS_ERR_USER_ON_CHANNEL);
3143 /* Generate new channel key as protocol dictates */
3145 if (!silc_server_create_channel_key(server, channel, 0))
3148 /* Send the channel key. This is broadcasted to the channel but is not
3149 sent to the client who is joining to the channel. */
3150 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3151 silc_server_send_channel_key(server, NULL, channel,
3152 server->server_type == SILC_ROUTER ?
3153 FALSE : !server->standalone);
3156 /* Join the client to the channel by adding it to channel's user list.
3157 Add also the channel to client entry's channels list for fast cross-
3159 chl = silc_calloc(1, sizeof(*chl));
3161 chl->client = client;
3162 chl->channel = channel;
3163 silc_hash_table_add(channel->user_list, client, chl);
3164 silc_hash_table_add(client->channels, channel, chl);
3166 /* Get users on the channel */
3167 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3170 /* Encode Client ID Payload of the original client who wants to join */
3171 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3173 /* Encode command reply packet */
3174 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3175 SILC_PUT32_MSB(channel->mode, mode);
3176 SILC_PUT32_MSB(created, tmp2);
3177 SILC_PUT32_MSB(user_count, tmp3);
3179 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3180 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3181 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
3182 strlen(channel->channel_key->
3184 channel->channel_key->cipher->name,
3185 channel->key_len / 8, channel->key);
3190 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3191 SILC_STATUS_OK, ident, 13,
3192 2, channel->channel_name,
3193 strlen(channel->channel_name),
3194 3, chidp->data, chidp->len,
3195 4, clidp->data, clidp->len,
3198 7, keyp ? keyp->data : NULL,
3199 keyp ? keyp->len : 0,
3200 8, channel->ban_list,
3202 strlen(channel->ban_list) : 0,
3203 9, channel->invite_list,
3204 channel->invite_list ?
3205 strlen(channel->invite_list) : 0,
3208 strlen(channel->topic) : 0,
3209 11, silc_hmac_get_name(channel->hmac),
3210 strlen(silc_hmac_get_name(channel->
3213 13, user_list->data, user_list->len,
3214 14, mode_list->data,
3217 /* Send command reply */
3218 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3219 reply->data, reply->len, FALSE);
3221 /* Send JOIN notify to locally connected clients on the channel. If
3222 we are normal server then router will send or have sent JOIN notify
3223 already. However since we've added the client already to our channel
3224 we'll ignore it (in packet_receive.c) so we must send it here. If
3225 we are router then this will send it to local clients and local
3227 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3228 SILC_NOTIFY_TYPE_JOIN, 2,
3229 clidp->data, clidp->len,
3230 chidp->data, chidp->len);
3232 if (!cmd->pending) {
3233 /* Send JOIN notify packet to our primary router */
3234 if (!server->standalone)
3235 silc_server_send_notify_join(server, server->router->connection,
3236 server->server_type == SILC_ROUTER ?
3237 TRUE : FALSE, channel, client->id);
3240 /* Distribute the channel key to all backup routers. */
3241 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3242 keyp->data, keyp->len, FALSE, TRUE);
3244 /* If client became founder by providing correct founder auth data
3245 notify the mode change to the channel. */
3247 SILC_PUT32_MSB(chl->mode, mode);
3248 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3249 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3250 clidp->data, clidp->len,
3251 mode, 4, clidp->data, clidp->len);
3253 /* Set CUMODE notify type to network */
3254 if (!server->standalone)
3255 silc_server_send_notify_cumode(server, server->router->connection,
3256 server->server_type == SILC_ROUTER ?
3257 TRUE : FALSE, channel,
3258 chl->mode, client->id, SILC_ID_CLIENT,
3263 silc_buffer_free(reply);
3264 silc_buffer_free(clidp);
3265 silc_buffer_free(chidp);
3266 silc_buffer_free(keyp);
3267 silc_buffer_free(user_list);
3268 silc_buffer_free(mode_list);
3271 silc_free(passphrase);
3274 /* Server side of command JOIN. Joins client into requested channel. If
3275 the channel does not exist it will be created. */
3277 SILC_SERVER_CMD_FUNC(join)
3279 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3280 SilcServer server = cmd->server;
3281 unsigned char *auth;
3282 uint32 tmp_len, auth_len;
3283 char *tmp, *channel_name = NULL, *cipher, *hmac;
3284 SilcChannelEntry channel;
3286 bool created = FALSE, create_key = TRUE;
3287 SilcClientID *client_id;
3289 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3291 /* Get channel name */
3292 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3294 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3295 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3300 if (strlen(channel_name) > 256)
3301 channel_name[255] = '\0';
3303 if (silc_server_command_bad_chars(channel_name) == TRUE) {
3304 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3305 SILC_STATUS_ERR_BAD_CHANNEL);
3309 /* Get Client ID of the client who is joining to the channel */
3310 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3312 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3313 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3316 client_id = silc_id_payload_parse_id(tmp, tmp_len);
3318 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3319 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3323 /* Get cipher, hmac name and auth payload */
3324 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3325 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3326 auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3328 /* See if the channel exists */
3329 channel = silc_idlist_find_channel_by_name(server->local_list,
3330 channel_name, NULL);
3332 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3333 /* If this is coming from client the Client ID in the command packet must
3334 be same as the client's ID. */
3335 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3336 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3337 if (!SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
3338 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3339 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3344 if (!channel || channel->disabled) {
3345 /* Channel not found */
3347 /* If we are standalone server we don't have a router, we just create
3348 the channel by ourselves. */
3349 if (server->standalone) {
3350 channel = silc_server_create_new_channel(server, server->id, cipher,
3351 hmac, channel_name, TRUE);
3353 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3354 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3358 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3364 /* The channel does not exist on our server. If we are normal server
3365 we will send JOIN command to our router which will handle the
3366 joining procedure (either creates the channel if it doesn't exist
3367 or joins the client to it). */
3368 if (server->server_type != SILC_ROUTER) {
3372 /* If this is pending command callback then we've resolved
3373 it and it didn't work, return since we've notified the
3374 client already in the command reply callback. */
3378 old_ident = silc_command_get_ident(cmd->payload);
3379 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3380 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3382 /* Send JOIN command to our router */
3383 silc_server_packet_send(server, (SilcSocketConnection)
3384 server->router->connection,
3385 SILC_PACKET_COMMAND, cmd->packet->flags,
3386 tmpbuf->data, tmpbuf->len, TRUE);
3388 /* Reprocess this packet after received reply from router */
3389 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3390 silc_command_get_ident(cmd->payload),
3391 silc_server_command_join,
3392 silc_server_command_dup(cmd));
3393 cmd->pending = TRUE;
3397 /* We are router and the channel does not seem exist so we will check
3398 our global list as well for the channel. */
3399 channel = silc_idlist_find_channel_by_name(server->global_list,
3400 channel_name, NULL);
3402 /* Channel really does not exist, create it */
3403 channel = silc_server_create_new_channel(server, server->id, cipher,
3404 hmac, channel_name, TRUE);
3406 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3407 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3411 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3419 /* Channel not found */
3421 /* If the command came from router and we are normal server then
3422 something went wrong with the joining as the channel was not found.
3423 We can't do anything else but ignore this. */
3424 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3425 server->server_type != SILC_ROUTER)
3428 /* We are router and the channel does not seem exist so we will check
3429 our global list as well for the channel. */
3430 channel = silc_idlist_find_channel_by_name(server->global_list,
3431 channel_name, NULL);
3433 /* Channel really does not exist, create it */
3434 channel = silc_server_create_new_channel(server, server->id, cipher,
3435 hmac, channel_name, TRUE);
3437 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3438 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3442 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3449 /* Check whether the channel was created by our router */
3450 if (cmd->pending && context2) {
3451 SilcServerCommandReplyContext reply =
3452 (SilcServerCommandReplyContext)context2;
3454 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3455 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3456 SILC_GET32_MSB(created, tmp);
3457 create_key = FALSE; /* Router returned the key already */
3460 if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS)
3464 /* If the channel does not have global users and is also empty the client
3465 will be the channel founder and operator. */
3466 if (!channel->global_users && !silc_hash_table_count(channel->user_list))
3467 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3469 /* Join to the channel */
3470 silc_server_command_join_channel(server, cmd, channel, client_id,
3471 created, create_key, umode,
3474 silc_free(client_id);
3477 silc_server_command_free(cmd);
3480 /* Server side of command MOTD. Sends server's current "message of the
3481 day" to the client. */
3483 SILC_SERVER_CMD_FUNC(motd)
3485 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3486 SilcServer server = cmd->server;
3487 SilcBuffer packet, idp;
3488 char *motd, *dest_server;
3490 uint16 ident = silc_command_get_ident(cmd->payload);
3492 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3494 /* Get server name */
3495 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3497 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3498 SILC_STATUS_ERR_NO_SUCH_SERVER);
3502 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3505 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3507 if (server->config && server->config->motd &&
3508 server->config->motd->motd_file) {
3510 motd = silc_file_readfile(server->config->motd->motd_file, &motd_len);
3515 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3516 SILC_STATUS_OK, ident, 2,
3521 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3522 SILC_STATUS_OK, ident, 1,
3526 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3527 packet->data, packet->len, FALSE);
3528 silc_buffer_free(packet);
3529 silc_buffer_free(idp);
3531 SilcServerEntry entry;
3533 /* Check whether we have this server cached */
3534 entry = silc_idlist_find_server_by_name(server->global_list,
3535 dest_server, TRUE, NULL);
3537 entry = silc_idlist_find_server_by_name(server->local_list,
3538 dest_server, TRUE, NULL);
3541 if (server->server_type != SILC_SERVER && !cmd->pending &&
3542 entry && !entry->motd) {
3543 /* Send to the server */
3547 old_ident = silc_command_get_ident(cmd->payload);
3548 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3549 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3551 silc_server_packet_send(server, entry->connection,
3552 SILC_PACKET_COMMAND, cmd->packet->flags,
3553 tmpbuf->data, tmpbuf->len, TRUE);
3555 /* Reprocess this packet after received reply from router */
3556 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3557 silc_command_get_ident(cmd->payload),
3558 silc_server_command_motd,
3559 silc_server_command_dup(cmd));
3560 cmd->pending = TRUE;
3561 silc_command_set_ident(cmd->payload, old_ident);
3562 silc_buffer_free(tmpbuf);
3566 if (!entry && !cmd->pending && !server->standalone) {
3567 /* Send to the primary router */
3571 old_ident = silc_command_get_ident(cmd->payload);
3572 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3573 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3575 silc_server_packet_send(server, server->router->connection,
3576 SILC_PACKET_COMMAND, cmd->packet->flags,
3577 tmpbuf->data, tmpbuf->len, TRUE);
3579 /* Reprocess this packet after received reply from router */
3580 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3581 silc_command_get_ident(cmd->payload),
3582 silc_server_command_motd,
3583 silc_server_command_dup(cmd));
3584 cmd->pending = TRUE;
3585 silc_command_set_ident(cmd->payload, old_ident);
3586 silc_buffer_free(tmpbuf);
3591 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3592 SILC_STATUS_ERR_NO_SUCH_SERVER);
3596 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3597 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3598 SILC_STATUS_OK, ident, 2,
3602 strlen(entry->motd) : 0);
3603 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3604 packet->data, packet->len, FALSE);
3605 silc_buffer_free(packet);
3606 silc_buffer_free(idp);
3610 silc_server_command_free(cmd);
3613 /* Server side of command UMODE. Client can use this command to set/unset
3614 user mode. Client actually cannot set itself to be as server/router
3615 operator so this can be used only to unset the modes. */
3617 SILC_SERVER_CMD_FUNC(umode)
3619 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3620 SilcServer server = cmd->server;
3621 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3623 unsigned char *tmp_mask;
3625 uint16 ident = silc_command_get_ident(cmd->payload);
3627 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3630 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 2, 2);
3632 /* Get the client's mode mask */
3633 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3635 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3636 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3639 SILC_GET32_MSB(mask, tmp_mask);
3645 if (mask & SILC_UMODE_SERVER_OPERATOR) {
3646 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR)) {
3647 /* Cannot operator mode */
3648 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3649 SILC_STATUS_ERR_PERM_DENIED);
3653 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
3654 /* Remove the server operator rights */
3655 client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3658 if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3659 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
3660 /* Cannot operator mode */
3661 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3662 SILC_STATUS_ERR_PERM_DENIED);
3666 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
3667 /* Remove the router operator rights */
3668 client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3671 if (mask & SILC_UMODE_GONE) {
3672 client->mode |= SILC_UMODE_GONE;
3674 if (client->mode & SILC_UMODE_GONE)
3675 /* Remove the gone status */
3676 client->mode &= ~SILC_UMODE_GONE;
3679 /* Send UMODE change to primary router */
3680 if (!server->standalone)
3681 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3682 client->id, client->mode);
3684 /* Send command reply to sender */
3685 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3686 SILC_STATUS_OK, ident, 1,
3688 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3689 packet->data, packet->len, FALSE);
3690 silc_buffer_free(packet);
3693 silc_server_command_free(cmd);
3696 /* Checks that client has rights to add or remove channel modes. If any
3697 of the checks fails FALSE is returned. */
3699 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3700 SilcChannelClientEntry client,
3703 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3704 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3706 /* Check whether has rights to change anything */
3707 if (!is_op && !is_fo)
3710 /* Check whether has rights to change everything */
3714 /* We know that client is channel operator, check that they are not
3715 changing anything that requires channel founder rights. Rest of the
3716 modes are available automatically for channel operator. */
3718 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3719 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3720 if (is_op && !is_fo)
3723 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3724 if (is_op && !is_fo)
3729 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3730 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE))
3731 if (is_op && !is_fo)
3734 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3735 if (is_op && !is_fo)
3740 if (mode & SILC_CHANNEL_MODE_CIPHER) {
3741 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER))
3742 if (is_op && !is_fo)
3745 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3746 if (is_op && !is_fo)
3751 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3752 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH))
3753 if (is_op && !is_fo)
3756 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3757 if (is_op && !is_fo)
3765 /* Server side command of CMODE. Changes channel mode */
3767 SILC_SERVER_CMD_FUNC(cmode)
3769 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3770 SilcServer server = cmd->server;
3771 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3772 SilcIDListData idata = (SilcIDListData)client;
3773 SilcChannelID *channel_id;
3774 SilcChannelEntry channel;
3775 SilcChannelClientEntry chl;
3776 SilcBuffer packet, cidp;
3777 unsigned char *tmp, *tmp_id, *tmp_mask;
3778 char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3779 uint32 mode_mask, tmp_len, tmp_len2;
3780 uint16 ident = silc_command_get_ident(cmd->payload);
3782 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 2, 7);
3784 /* Get Channel ID */
3785 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3787 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3788 SILC_STATUS_ERR_NO_CHANNEL_ID);
3791 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3793 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3794 SILC_STATUS_ERR_NO_CHANNEL_ID);
3798 /* Get the channel mode mask */
3799 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3801 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3802 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3805 SILC_GET32_MSB(mode_mask, tmp_mask);
3807 /* Get channel entry */
3808 channel = silc_idlist_find_channel_by_id(server->local_list,
3811 channel = silc_idlist_find_channel_by_id(server->global_list,
3814 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3815 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3820 /* Check whether this client is on the channel */
3821 if (!silc_server_client_on_channel(client, channel)) {
3822 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3823 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3827 /* Get entry to the channel user list */
3828 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
3830 /* Check that client has rights to change any requested channel modes */
3831 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3832 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3833 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3838 * Check the modes. Modes that requires nothing special operation are
3842 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3843 /* Channel uses private keys to protect traffic. Client(s) has set the
3844 key locally they want to use, server does not know that key. */
3845 /* Nothing interesting to do here */
3847 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3848 /* The mode is removed and we need to generate and distribute
3849 new channel key. Clients are not using private channel keys
3850 anymore after this. */
3852 /* Re-generate channel key */
3853 if (!silc_server_create_channel_key(server, channel, 0))
3856 /* Send the channel key. This sends it to our local clients and if
3857 we are normal server to our router as well. */
3858 silc_server_send_channel_key(server, NULL, channel,
3859 server->server_type == SILC_ROUTER ?
3860 FALSE : !server->standalone);
3862 cipher = channel->channel_key->cipher->name;
3863 hmac = (char *)silc_hmac_get_name(channel->hmac);
3867 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3868 /* User limit is set on channel */
3871 /* Get user limit */
3872 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3874 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3875 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3876 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3880 SILC_GET32_MSB(user_limit, tmp);
3881 channel->user_limit = user_limit;
3884 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3885 /* User limit mode is unset. Remove user limit */
3886 channel->user_limit = 0;
3889 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3890 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3891 /* Passphrase has been set to channel */
3893 /* Get the passphrase */
3894 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3896 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3897 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3901 /* Save the passphrase */
3902 passphrase = channel->passphrase = strdup(tmp);
3905 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3906 /* Passphrase mode is unset. remove the passphrase */
3907 if (channel->passphrase) {
3908 silc_free(channel->passphrase);
3909 channel->passphrase = NULL;
3914 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3915 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3916 /* Cipher to use protect the traffic */
3917 SilcCipher newkey, oldkey;
3920 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3922 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3923 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3927 /* Delete old cipher and allocate the new one */
3928 if (!silc_cipher_alloc(cipher, &newkey)) {
3929 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3930 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3934 oldkey = channel->channel_key;
3935 channel->channel_key = newkey;
3937 /* Re-generate channel key */
3938 if (!silc_server_create_channel_key(server, channel, 0)) {
3939 /* We don't have new key, revert to old one */
3940 channel->channel_key = oldkey;
3944 /* Remove old channel key for good */
3945 silc_cipher_free(oldkey);
3947 /* Send the channel key. This sends it to our local clients and if
3948 we are normal server to our router as well. */
3949 silc_server_send_channel_key(server, NULL, channel,
3950 server->server_type == SILC_ROUTER ?
3951 FALSE : !server->standalone);
3954 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3955 /* Cipher mode is unset. Remove the cipher and revert back to
3957 SilcCipher newkey, oldkey;
3958 cipher = channel->cipher;
3960 /* Delete old cipher and allocate default one */
3961 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
3962 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3963 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3967 oldkey = channel->channel_key;
3968 channel->channel_key = newkey;
3970 /* Re-generate channel key */
3971 if (!silc_server_create_channel_key(server, channel, 0)) {
3972 /* We don't have new key, revert to old one */
3973 channel->channel_key = oldkey;
3977 /* Remove old channel key for good */
3978 silc_cipher_free(oldkey);
3980 /* Send the channel key. This sends it to our local clients and if
3981 we are normal server to our router as well. */
3982 silc_server_send_channel_key(server, NULL, channel,
3983 server->server_type == SILC_ROUTER ?
3984 FALSE : !server->standalone);
3988 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3989 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3990 /* HMAC to use protect the traffic */
3991 unsigned char hash[32];
3995 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3997 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3998 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4002 /* Delete old hmac and allocate the new one */
4003 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4004 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4005 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4009 silc_hmac_free(channel->hmac);
4010 channel->hmac = newhmac;
4012 /* Set the HMAC key out of current channel key. The client must do
4014 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4015 channel->key_len / 8, hash);
4016 silc_hmac_set_key(channel->hmac, hash,
4017 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4018 memset(hash, 0, sizeof(hash));
4021 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4022 /* Hmac mode is unset. Remove the hmac and revert back to
4025 unsigned char hash[32];
4026 hmac = channel->hmac_name;
4028 /* Delete old hmac and allocate default one */
4029 silc_hmac_free(channel->hmac);
4030 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4031 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4032 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4036 silc_hmac_free(channel->hmac);
4037 channel->hmac = newhmac;
4039 /* Set the HMAC key out of current channel key. The client must do
4041 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4042 channel->key_len / 8,
4044 silc_hmac_set_key(channel->hmac, hash,
4045 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4046 memset(hash, 0, sizeof(hash));
4050 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4051 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4052 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4053 /* Set the founder authentication */
4054 SilcAuthPayload auth;
4056 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4058 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4059 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4063 auth = silc_auth_payload_parse(tmp, tmp_len);
4065 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4066 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4070 /* Save the public key */
4071 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
4072 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
4075 channel->founder_method = silc_auth_get_method(auth);
4077 if (channel->founder_method == SILC_AUTH_PASSWORD) {
4078 tmp = silc_auth_get_data(auth, &tmp_len);
4079 channel->founder_passwd =
4080 silc_calloc(tmp_len + 1, sizeof(*channel->founder_passwd));
4081 memcpy(channel->founder_passwd, tmp, tmp_len);
4082 channel->founder_passwd_len = tmp_len;
4084 /* Verify the payload before setting the mode */
4085 if (!silc_auth_verify(auth, channel->founder_method,
4086 channel->founder_key, 0, idata->hash,
4087 client->id, SILC_ID_CLIENT)) {
4088 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4089 SILC_STATUS_ERR_AUTH_FAILED);
4094 silc_auth_payload_free(auth);
4098 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4099 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4100 if (channel->founder_key)
4101 silc_pkcs_public_key_free(channel->founder_key);
4102 if (channel->founder_passwd) {
4103 silc_free(channel->founder_passwd);
4104 channel->founder_passwd = NULL;
4110 /* Finally, set the mode */
4111 channel->mode = mode_mask;
4113 /* Send CMODE_CHANGE notify. */
4114 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4115 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4116 SILC_NOTIFY_TYPE_CMODE_CHANGE, 5,
4117 cidp->data, cidp->len,
4119 cipher, cipher ? strlen(cipher) : 0,
4120 hmac, hmac ? strlen(hmac) : 0,
4121 passphrase, passphrase ?
4122 strlen(passphrase) : 0);
4124 /* Set CMODE notify type to network */
4125 if (!server->standalone)
4126 silc_server_send_notify_cmode(server, server->router->connection,
4127 server->server_type == SILC_ROUTER ?
4128 TRUE : FALSE, channel,
4129 mode_mask, client->id, SILC_ID_CLIENT,
4130 cipher, hmac, passphrase);
4132 /* Send command reply to sender */
4133 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4134 SILC_STATUS_OK, ident, 2,
4135 2, tmp_id, tmp_len2,
4137 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4138 packet->data, packet->len, FALSE);
4140 silc_buffer_free(packet);
4141 silc_free(channel_id);
4142 silc_buffer_free(cidp);
4145 silc_server_command_free(cmd);
4148 /* Server side of CUMODE command. Changes client's mode on a channel. */
4150 SILC_SERVER_CMD_FUNC(cumode)
4152 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4153 SilcServer server = cmd->server;
4154 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4155 SilcIDListData idata = (SilcIDListData)client;
4156 SilcChannelID *channel_id;
4157 SilcClientID *client_id;
4158 SilcChannelEntry channel;
4159 SilcClientEntry target_client;
4160 SilcChannelClientEntry chl;
4161 SilcBuffer packet, idp;
4162 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4163 uint32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4165 uint16 ident = silc_command_get_ident(cmd->payload);
4167 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4169 /* Get Channel ID */
4170 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4172 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4173 SILC_STATUS_ERR_NO_CHANNEL_ID);
4176 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
4178 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4179 SILC_STATUS_ERR_NO_CHANNEL_ID);
4183 /* Get channel entry */
4184 channel = silc_idlist_find_channel_by_id(server->local_list,
4187 channel = silc_idlist_find_channel_by_id(server->global_list,
4190 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4191 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4196 /* Check whether sender is on the channel */
4197 if (!silc_server_client_on_channel(client, channel)) {
4198 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4199 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4203 /* Check that client has rights to change other's rights */
4204 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4205 sender_mask = chl->mode;
4207 /* Get the target client's channel mode mask */
4208 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4210 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4211 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4214 SILC_GET32_MSB(target_mask, tmp_mask);
4216 /* Get target Client ID */
4217 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4219 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4220 SILC_STATUS_ERR_NO_CLIENT_ID);
4223 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
4225 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4226 SILC_STATUS_ERR_NO_CLIENT_ID);
4230 /* Get target client's entry */
4231 target_client = silc_idlist_find_client_by_id(server->local_list,
4232 client_id, TRUE, NULL);
4233 if (!target_client) {
4234 target_client = silc_idlist_find_client_by_id(server->global_list,
4235 client_id, TRUE, NULL);
4238 if (target_client != client &&
4239 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4240 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4241 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4242 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4246 /* Check whether target client is on the channel */
4247 if (target_client != client) {
4248 if (!silc_server_client_on_channel(target_client, channel)) {
4249 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4250 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4254 /* Get entry to the channel user list */
4255 silc_hash_table_find(channel->user_list, target_client, NULL,
4263 /* If the target client is founder, no one else can change their mode
4265 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
4266 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4267 SILC_STATUS_ERR_NOT_YOU);
4271 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4272 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4273 /* The client tries to claim the founder rights. */
4274 unsigned char *tmp_auth;
4275 uint32 tmp_auth_len, auth_len;
4278 if (target_client != client) {
4279 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4280 SILC_STATUS_ERR_NOT_YOU);
4284 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4285 !channel->founder_key || !idata->public_key ||
4286 !silc_pkcs_public_key_compare(channel->founder_key,
4287 idata->public_key)) {
4288 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4289 SILC_STATUS_ERR_NOT_YOU);
4293 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4295 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4296 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4300 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4301 (void *)channel->founder_passwd : (void *)channel->founder_key);
4302 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4303 channel->founder_passwd_len : 0);
4305 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4306 channel->founder_method, auth, auth_len,
4307 idata->hash, client->id, SILC_ID_CLIENT)) {
4308 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4309 SILC_STATUS_ERR_AUTH_FAILED);
4313 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4317 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4318 if (target_client == client) {
4319 /* Remove channel founder rights from itself */
4320 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4323 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4324 SILC_STATUS_ERR_NOT_YOU);
4330 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4331 /* Promote to operator */
4332 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4333 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4334 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4335 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4336 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4340 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4344 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4345 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4346 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4347 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4348 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4352 /* Demote to normal user */
4353 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4358 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4359 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4361 /* Send notify to channel, notify only if mode was actually changed. */
4363 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4364 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4365 idp->data, idp->len,
4369 /* Set CUMODE notify type to network */
4370 if (!server->standalone)
4371 silc_server_send_notify_cumode(server, server->router->connection,
4372 server->server_type == SILC_ROUTER ?
4373 TRUE : FALSE, channel,
4374 target_mask, client->id,
4379 /* Send command reply to sender */
4380 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4381 SILC_STATUS_OK, ident, 3,
4383 3, tmp_ch_id, tmp_ch_len,
4384 4, tmp_id, tmp_len);
4385 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4386 packet->data, packet->len, FALSE);
4388 silc_buffer_free(packet);
4389 silc_free(channel_id);
4390 silc_free(client_id);
4391 silc_buffer_free(idp);
4394 silc_server_command_free(cmd);
4397 /* Server side of KICK command. Kicks client out of channel. */
4399 SILC_SERVER_CMD_FUNC(kick)
4401 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4402 SilcServer server = cmd->server;
4403 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4404 SilcClientEntry target_client;
4405 SilcChannelID *channel_id;
4406 SilcClientID *client_id;
4407 SilcChannelEntry channel;
4408 SilcChannelClientEntry chl;
4410 uint32 tmp_len, target_idp_len;
4411 unsigned char *tmp, *comment, *target_idp;
4413 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4415 /* Get Channel ID */
4416 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4418 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4419 SILC_STATUS_ERR_NO_CHANNEL_ID);
4422 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
4424 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4425 SILC_STATUS_ERR_NO_CHANNEL_ID);
4429 /* Get channel entry */
4430 channel = silc_idlist_find_channel_by_id(server->local_list,
4433 channel = silc_idlist_find_channel_by_id(server->local_list,
4436 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4437 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4442 /* Check whether sender is on the channel */
4443 if (!silc_server_client_on_channel(client, channel)) {
4444 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4445 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4449 /* Check that the kicker is channel operator or channel founder */
4450 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4451 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4452 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4453 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4457 /* Get target Client ID */
4458 target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4460 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4461 SILC_STATUS_ERR_NO_CLIENT_ID);
4464 client_id = silc_id_payload_parse_id(target_idp, target_idp_len);
4466 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4467 SILC_STATUS_ERR_NO_CLIENT_ID);
4471 /* Get target client's entry */
4472 target_client = silc_idlist_find_client_by_id(server->local_list,
4473 client_id, TRUE, NULL);
4474 if (!target_client) {
4475 target_client = silc_idlist_find_client_by_id(server->global_list,
4476 client_id, TRUE, NULL);
4479 /* Check that the target client is not channel founder. Channel founder
4480 cannot be kicked from the channel. */
4481 silc_hash_table_find(channel->user_list, target_client, NULL, (void *)&chl);
4482 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4483 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4484 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4488 /* Check whether target client is on the channel */
4489 if (!silc_server_client_on_channel(target_client, channel)) {
4490 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4491 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4497 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4501 /* Send command reply to sender */
4502 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4505 /* Send KICKED notify to local clients on the channel */
4506 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4507 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4508 SILC_NOTIFY_TYPE_KICKED, 3,
4509 target_idp, target_idp_len,
4510 comment, comment ? strlen(comment) : 0,
4511 idp->data, idp->len);
4512 silc_buffer_free(idp);
4514 /* Remove the client from the channel. If the channel does not exist
4515 after removing the client then the client kicked itself off the channel
4516 and we don't have to send anything after that. */
4517 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4518 target_client, FALSE))
4521 /* Send KICKED notify to primary route */
4522 if (!server->standalone)
4523 silc_server_send_notify_kicked(server, server->router->connection,
4524 server->server_type == SILC_ROUTER ?
4525 TRUE : FALSE, channel,
4526 target_client->id, comment);
4528 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4529 /* Re-generate channel key */
4530 if (!silc_server_create_channel_key(server, channel, 0))
4533 /* Send the channel key to the channel. The key of course is not sent
4534 to the client who was kicked off the channel. */
4535 silc_server_send_channel_key(server, target_client->connection, channel,
4536 server->server_type == SILC_ROUTER ?
4537 FALSE : !server->standalone);
4541 silc_server_command_free(cmd);
4544 /* Server side of OPER command. Client uses this comand to obtain server
4545 operator privileges to this server/router. */
4547 SILC_SERVER_CMD_FUNC(oper)
4549 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4550 SilcServer server = cmd->server;
4551 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4552 unsigned char *username, *auth;
4554 SilcServerConfigSectionAdminConnection *admin;
4555 SilcIDListData idata = (SilcIDListData)client;
4557 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4559 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4562 /* Get the username */
4563 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4565 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4566 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4570 /* Get the admin configuration */
4571 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4572 username, client->nickname);
4574 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4575 username, client->nickname);
4577 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4578 SILC_STATUS_ERR_AUTH_FAILED);
4583 /* Get the authentication payload */
4584 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4586 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4587 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4591 /* Verify the authentication data */
4592 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4593 admin->auth_data, admin->auth_data_len,
4594 idata->hash, client->id, SILC_ID_CLIENT)) {
4595 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4596 SILC_STATUS_ERR_AUTH_FAILED);
4600 /* Client is now server operator */
4601 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4603 /* Send UMODE change to primary router */
4604 if (!server->standalone)
4605 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4606 client->id, client->mode);
4608 /* Send reply to the sender */
4609 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4613 silc_server_command_free(cmd);
4616 /* Server side of SILCOPER command. Client uses this comand to obtain router
4617 operator privileges to this router. */
4619 SILC_SERVER_CMD_FUNC(silcoper)
4621 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4622 SilcServer server = cmd->server;
4623 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4624 unsigned char *username, *auth;
4626 SilcServerConfigSectionAdminConnection *admin;
4627 SilcIDListData idata = (SilcIDListData)client;
4629 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4631 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4634 if (server->server_type != SILC_ROUTER) {
4635 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4636 SILC_STATUS_ERR_AUTH_FAILED);
4640 /* Get the username */
4641 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4643 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4644 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4648 /* Get the admin configuration */
4649 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4650 username, client->nickname);
4652 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4653 username, client->nickname);
4655 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4656 SILC_STATUS_ERR_AUTH_FAILED);
4661 /* Get the authentication payload */
4662 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4664 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4665 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4669 /* Verify the authentication data */
4670 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4671 admin->auth_data, admin->auth_data_len,
4672 idata->hash, client->id, SILC_ID_CLIENT)) {
4673 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4674 SILC_STATUS_ERR_AUTH_FAILED);
4678 /* Client is now router operator */
4679 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4681 /* Send UMODE change to primary router */
4682 if (!server->standalone)
4683 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4684 client->id, client->mode);
4686 /* Send reply to the sender */
4687 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4691 silc_server_command_free(cmd);
4694 /* Server side command of CONNECT. Connects us to the specified remote
4695 server or router. */
4697 SILC_SERVER_CMD_FUNC(connect)
4699 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4700 SilcServer server = cmd->server;
4701 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4702 unsigned char *tmp, *host;
4704 uint32 port = SILC_PORT;
4706 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CONNECT, cmd, 1, 2);
4708 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4711 /* Check whether client has the permissions. */
4712 if (client->mode == SILC_UMODE_NONE) {
4713 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4714 SILC_STATUS_ERR_NO_SERVER_PRIV);
4718 if (server->server_type == SILC_ROUTER &&
4719 client->mode & SILC_UMODE_SERVER_OPERATOR) {
4720 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4721 SILC_STATUS_ERR_NO_ROUTER_PRIV);
4725 /* Get the remote server */
4726 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4728 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4729 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4734 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4736 SILC_GET32_MSB(port, tmp);
4738 /* Create the connection. It is done with timeout and is async. */
4739 silc_server_create_connection(server, host, port);
4741 /* Send reply to the sender */
4742 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4746 silc_server_command_free(cmd);
4749 /* Server side of command BAN. This is used to manage the ban list of the
4750 channel. To add clients and remove clients from the ban list. */
4752 SILC_SERVER_CMD_FUNC(ban)
4754 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4755 SilcServer server = cmd->server;
4756 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4758 SilcChannelEntry channel;
4759 SilcChannelClientEntry chl;
4760 SilcChannelID *channel_id = NULL;
4761 unsigned char *id, *add, *del;
4762 uint32 id_len, tmp_len;
4763 uint16 ident = silc_command_get_ident(cmd->payload);
4765 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4768 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4770 /* Get Channel ID */
4771 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4773 channel_id = silc_id_payload_parse_id(id, id_len);
4775 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4776 SILC_STATUS_ERR_NO_CHANNEL_ID);
4781 /* Get channel entry. The server must know about the channel since the
4782 client is expected to be on the channel. */
4783 channel = silc_idlist_find_channel_by_id(server->local_list,
4786 channel = silc_idlist_find_channel_by_id(server->global_list,
4789 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4790 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4795 /* Check whether this client is on the channel */
4796 if (!silc_server_client_on_channel(client, channel)) {
4797 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4798 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4802 /* Get entry to the channel user list */
4803 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4805 /* The client must be at least channel operator. */
4806 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4807 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4808 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4812 /* Get the new ban and add it to the ban list */
4813 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4815 if (!channel->ban_list)
4816 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4818 channel->ban_list = silc_realloc(channel->ban_list,
4819 sizeof(*channel->ban_list) *
4821 strlen(channel->ban_list) + 2));
4822 if (add[tmp_len - 1] == ',')
4823 add[tmp_len - 1] = '\0';
4825 strncat(channel->ban_list, add, tmp_len);
4826 strncat(channel->ban_list, ",", 1);
4829 /* Get the ban to be removed and remove it from the list */
4830 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4831 if (del && channel->ban_list) {
4832 char *start, *end, *n;
4834 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4835 silc_free(channel->ban_list);
4836 channel->ban_list = NULL;
4838 start = strstr(channel->ban_list, del);
4839 if (start && strlen(start) >= tmp_len) {
4840 end = start + tmp_len;
4841 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4842 strncat(n, channel->ban_list, start - channel->ban_list);
4843 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4845 silc_free(channel->ban_list);
4846 channel->ban_list = n;
4851 /* Send the BAN notify type to our primary router. */
4852 if (!server->standalone && (add || del))
4853 silc_server_send_notify_ban(server, server->router->connection,
4854 server->server_type == SILC_ROUTER ?
4855 TRUE : FALSE, channel, add, del);
4857 /* Send the reply back to the client */
4859 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4860 SILC_STATUS_OK, ident, 2,
4862 3, channel->ban_list,
4864 strlen(channel->ban_list) - 1 : 0);
4865 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4866 packet->data, packet->len, FALSE);
4868 silc_buffer_free(packet);
4871 silc_free(channel_id);
4872 silc_server_command_free(cmd);
4875 /* Server side command of CLOSE. Closes connection to a specified server. */
4877 SILC_SERVER_CMD_FUNC(close)
4879 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4880 SilcServer server = cmd->server;
4881 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4882 SilcServerEntry server_entry;
4883 SilcSocketConnection sock;
4886 unsigned char *name;
4887 uint32 port = SILC_PORT;
4889 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CLOSE, cmd, 1, 2);
4891 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4894 /* Check whether client has the permissions. */
4895 if (client->mode == SILC_UMODE_NONE) {
4896 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4897 SILC_STATUS_ERR_NO_SERVER_PRIV);
4901 /* Get the remote server */
4902 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4904 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4905 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4910 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4912 SILC_GET32_MSB(port, tmp);
4914 server_entry = silc_idlist_find_server_by_conn(server->local_list,
4915 name, port, FALSE, NULL);
4917 server_entry = silc_idlist_find_server_by_conn(server->global_list,
4918 name, port, FALSE, NULL);
4919 if (!server_entry) {
4920 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4921 SILC_STATUS_ERR_NO_SERVER_ID);
4925 /* Send reply to the sender */
4926 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4929 /* Close the connection to the server */
4930 sock = (SilcSocketConnection)server_entry->connection;
4932 /* If we shutdown primary router connection manually then don't trigger
4933 any reconnect or backup router connections, by setting the router
4935 if (server->router == server_entry) {
4936 server->id_entry->router = NULL;
4937 server->router = NULL;
4938 server->standalone = TRUE;
4940 silc_server_free_sock_user_data(server, sock, NULL);
4941 silc_server_close_connection(server, sock);
4944 silc_server_command_free(cmd);
4947 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4948 active connections. */
4950 SILC_SERVER_CMD_FUNC(shutdown)
4952 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4953 SilcServer server = cmd->server;
4954 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4956 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4958 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4961 /* Check whether client has the permission. */
4962 if (client->mode == SILC_UMODE_NONE) {
4963 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4964 SILC_STATUS_ERR_NO_SERVER_PRIV);
4968 /* Send reply to the sender */
4969 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4972 /* Then, gracefully, or not, bring the server down. */
4973 silc_server_stop(server);
4977 silc_server_command_free(cmd);
4980 /* Server side command of LEAVE. Removes client from a channel. */
4982 SILC_SERVER_CMD_FUNC(leave)
4984 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4985 SilcServer server = cmd->server;
4986 SilcSocketConnection sock = cmd->sock;
4987 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4988 SilcChannelID *id = NULL;
4989 SilcChannelEntry channel;
4993 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4995 /* Get Channel ID */
4996 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4998 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4999 SILC_STATUS_ERR_NO_CHANNEL_ID);
5002 id = silc_id_payload_parse_id(tmp, len);
5004 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5005 SILC_STATUS_ERR_NO_CHANNEL_ID);
5009 /* Get channel entry */
5010 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5012 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5014 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5015 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5020 /* Check whether this client is on the channel */
5021 if (!silc_server_client_on_channel(id_entry, channel)) {
5022 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5023 SILC_STATUS_ERR_NOT_ON_CHANNEL);
5027 /* Notify routers that they should remove this client from their list
5028 of clients on the channel. Send LEAVE notify type. */
5029 if (!server->standalone)
5030 silc_server_send_notify_leave(server, server->router->connection,
5031 server->server_type == SILC_ROUTER ?
5032 TRUE : FALSE, channel, id_entry->id);
5034 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5037 /* Remove client from channel */
5038 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5040 /* If the channel does not exist anymore we won't send anything */
5043 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5044 /* Re-generate channel key */
5045 if (!silc_server_create_channel_key(server, channel, 0))
5048 /* Send the channel key */
5049 silc_server_send_channel_key(server, NULL, channel,
5050 server->server_type == SILC_ROUTER ?
5051 FALSE : !server->standalone);
5056 silc_server_command_free(cmd);
5059 /* Server side of command USERS. Resolves clients and their USERS currently
5060 joined on the requested channel. The list of Client ID's and their modes
5061 on the channel is sent back. */
5063 SILC_SERVER_CMD_FUNC(users)
5065 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5066 SilcServer server = cmd->server;
5067 SilcChannelEntry channel;
5068 SilcChannelID *id = NULL;
5069 SilcBuffer packet, idp;
5070 unsigned char *channel_id;
5071 uint32 channel_id_len;
5072 SilcBuffer client_id_list;
5073 SilcBuffer client_mode_list;
5074 unsigned char lc[4];
5075 uint32 list_count = 0;
5076 uint16 ident = silc_command_get_ident(cmd->payload);
5079 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5081 /* Get Channel ID */
5082 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5084 /* Get channel name */
5085 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5087 if (!channel_id && !channel_name) {
5088 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5089 SILC_STATUS_ERR_NO_CHANNEL_ID);
5094 id = silc_id_payload_parse_id(channel_id, channel_id_len);
5096 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5097 SILC_STATUS_ERR_NO_CHANNEL_ID);
5102 /* If we are server and we don't know about this channel we will send
5103 the command to our router. If we know about the channel then we also
5104 have the list of users already. */
5106 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5108 channel = silc_idlist_find_channel_by_name(server->local_list,
5109 channel_name, NULL);
5111 if (!channel || channel->disabled) {
5112 if (server->server_type != SILC_ROUTER && !server->standalone &&
5116 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5117 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5119 /* Send USERS command */
5120 silc_server_packet_send(server, server->router->connection,
5121 SILC_PACKET_COMMAND, cmd->packet->flags,
5122 tmpbuf->data, tmpbuf->len, TRUE);
5124 /* Reprocess this packet after received reply */
5125 silc_server_command_pending(server, SILC_COMMAND_USERS,
5126 silc_command_get_ident(cmd->payload),
5127 silc_server_command_users,
5128 silc_server_command_dup(cmd));
5129 cmd->pending = TRUE;
5130 silc_command_set_ident(cmd->payload, ident);
5131 silc_buffer_free(tmpbuf);
5136 /* Check the global list as well. */
5138 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5140 channel = silc_idlist_find_channel_by_name(server->global_list,
5141 channel_name, NULL);
5143 /* Channel really does not exist */
5144 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5145 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5150 /* If the channel is private or secret do not send anything, unless the
5151 user requesting this command is on the channel. */
5152 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5153 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5154 && !silc_server_client_on_channel(cmd->sock->user_data, channel)) {
5155 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5156 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5161 (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
5162 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5163 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5168 /* Get the users list */
5169 silc_server_get_users_on_channel(server, channel, &client_id_list,
5170 &client_mode_list, &list_count);
5173 SILC_PUT32_MSB(list_count, lc);
5176 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5177 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5178 SILC_STATUS_OK, ident, 4,
5179 2, idp->data, idp->len,
5181 4, client_id_list->data,
5182 client_id_list->len,
5183 5, client_mode_list->data,
5184 client_mode_list->len);
5185 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5186 packet->data, packet->len, FALSE);
5188 silc_buffer_free(idp);
5189 silc_buffer_free(packet);
5190 silc_buffer_free(client_id_list);
5191 silc_buffer_free(client_mode_list);
5195 silc_server_command_free(cmd);
5198 /* Server side of command GETKEY. This fetches the client's public key
5199 from the server where to the client is connected. */
5201 SILC_SERVER_CMD_FUNC(getkey)
5203 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5204 SilcServer server = cmd->server;
5206 SilcClientEntry client;
5207 SilcServerEntry server_entry;
5208 SilcClientID *client_id = NULL;
5209 SilcServerID *server_id = NULL;
5210 SilcIDPayload idp = NULL;
5211 uint16 ident = silc_command_get_ident(cmd->payload);
5212 unsigned char *tmp, *pkdata;
5213 uint32 tmp_len, pklen;
5214 SilcBuffer pk = NULL;
5217 SILC_LOG_DEBUG(("Start"));
5219 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5221 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5222 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5225 idp = silc_id_payload_parse(tmp, tmp_len);
5227 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5228 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5232 id_type = silc_id_payload_get_type(idp);
5233 if (id_type == SILC_ID_CLIENT) {
5234 client_id = silc_id_payload_get_id(idp);
5236 /* If the client is not found from local list there is no chance it
5237 would be locally connected client so send the command further. */
5238 client = silc_idlist_find_client_by_id(server->local_list,
5239 client_id, TRUE, NULL);
5241 client = silc_idlist_find_client_by_id(server->global_list,
5242 client_id, TRUE, NULL);
5244 if ((!client && !cmd->pending && !server->standalone) ||
5245 (client && !client->connection && !cmd->pending) ||
5246 (client && !client->data.public_key && !cmd->pending)) {
5249 SilcSocketConnection dest_sock;
5251 dest_sock = silc_server_get_client_route(server, NULL, 0,
5256 old_ident = silc_command_get_ident(cmd->payload);
5257 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5258 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5260 silc_server_packet_send(server, dest_sock,
5261 SILC_PACKET_COMMAND, cmd->packet->flags,
5262 tmpbuf->data, tmpbuf->len, TRUE);
5264 /* Reprocess this packet after received reply from router */
5265 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5266 silc_command_get_ident(cmd->payload),
5267 silc_server_command_getkey,
5268 silc_server_command_dup(cmd));
5269 cmd->pending = TRUE;
5270 silc_command_set_ident(cmd->payload, old_ident);
5271 silc_buffer_free(tmpbuf);
5276 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5277 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5281 /* The client is locally connected, just get the public key and
5282 send it back. If they key does not exist then do not send it,
5283 send just OK reply */
5284 if (!client->data.public_key) {
5288 tmp = silc_pkcs_public_key_encode(client->data.public_key, &tmp_len);
5289 pk = silc_buffer_alloc(4 + tmp_len);
5290 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5291 silc_buffer_format(pk,
5292 SILC_STR_UI_SHORT(tmp_len),
5293 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5294 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5300 } else if (id_type == SILC_ID_SERVER) {
5301 server_id = silc_id_payload_get_id(idp);
5303 /* If the server is not found from local list there is no chance it
5304 would be locally connected server so send the command further. */
5305 server_entry = silc_idlist_find_server_by_id(server->local_list,
5306 server_id, TRUE, NULL);
5308 server_entry = silc_idlist_find_server_by_id(server->global_list,
5309 server_id, TRUE, NULL);
5311 if (server_entry != server->id_entry &&
5312 ((!server_entry && !cmd->pending && !server->standalone) ||
5313 (server_entry && !server_entry->connection && !cmd->pending &&
5314 !server->standalone) ||
5315 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5316 !server->standalone))) {
5320 old_ident = silc_command_get_ident(cmd->payload);
5321 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5322 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5324 silc_server_packet_send(server, server->router->connection,
5325 SILC_PACKET_COMMAND, cmd->packet->flags,
5326 tmpbuf->data, tmpbuf->len, TRUE);
5328 /* Reprocess this packet after received reply from router */
5329 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5330 silc_command_get_ident(cmd->payload),
5331 silc_server_command_getkey,
5332 silc_server_command_dup(cmd));
5333 cmd->pending = TRUE;
5335 silc_command_set_ident(cmd->payload, old_ident);
5336 silc_buffer_free(tmpbuf);
5340 if (!server_entry) {
5341 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5342 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5346 /* If they key does not exist then do not send it, send just OK reply */
5347 if (!server_entry->data.public_key) {
5351 tmp = silc_pkcs_public_key_encode(server_entry->data.public_key,
5353 pk = silc_buffer_alloc(4 + tmp_len);
5354 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5355 silc_buffer_format(pk,
5356 SILC_STR_UI_SHORT(tmp_len),
5357 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5358 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5368 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5369 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5370 SILC_STATUS_OK, ident,
5374 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5375 packet->data, packet->len, FALSE);
5376 silc_buffer_free(packet);
5379 silc_buffer_free(pk);
5383 silc_id_payload_free(idp);
5384 silc_free(client_id);
5385 silc_free(server_id);
5386 silc_server_command_free(cmd);