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,
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);
186 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
187 silc_buffer_free(packet->buffer);
188 silc_packet_context_free(packet);
189 silc_socket_free(ctx->sock);
193 ctx->args = silc_command_get_args(ctx->payload);
195 /* Get the command */
196 command = silc_command_get(ctx->payload);
197 for (cmd = silc_command_list; cmd->cb; cmd++)
198 if (cmd->cmd == command)
202 silc_server_command_send_status_reply(ctx, command,
203 SILC_STATUS_ERR_UNKNOWN_COMMAND);
204 silc_server_command_free(ctx);
208 /* Execute client's commands always with timeout. Normally they are
209 executed with zero (0) timeout but if client is sending command more
210 frequently than once in 2 seconds, then the timeout may be 0 to 2
212 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
213 SilcClientEntry client = (SilcClientEntry)sock->user_data;
214 SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
220 if (client->last_command && (time(NULL) - client->last_command) < 2) {
221 client->fast_command++;
224 client->fast_command = ((client->fast_command - 1) <= 0 ? 0 :
225 client->fast_command--);
229 if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
230 (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
231 silc_schedule_task_add(server->schedule, sock->sock,
232 silc_server_command_process_timeout,
234 2 - (time(NULL) - client->last_command), 0,
236 SILC_TASK_PRI_NORMAL);
238 silc_schedule_task_add(server->schedule, sock->sock,
239 silc_server_command_process_timeout,
243 SILC_TASK_PRI_NORMAL);
247 /* Execute for server */
249 if (!(cmd->flags & SILC_CF_REG))
251 else if (silc_server_is_registered(server, sock, ctx, cmd->cmd))
255 /* Allocate Command Context */
257 SilcServerCommandContext silc_server_command_alloc()
259 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
264 /* Free's the command context allocated before executing the command */
266 void silc_server_command_free(SilcServerCommandContext ctx)
269 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
271 if (ctx->users < 1) {
273 silc_command_payload_free(ctx->payload);
275 silc_packet_context_free(ctx->packet);
277 silc_socket_free(ctx->sock); /* Decrease reference counter */
282 /* Duplicate Command Context by adding reference counter. The context won't
283 be free'd untill it hits zero. */
285 SilcServerCommandContext
286 silc_server_command_dup(SilcServerCommandContext ctx)
289 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
294 /* Add new pending command to be executed when reply to a command has been
295 received. The `reply_cmd' is the command that will call the `callback'
296 with `context' when reply has been received. It can be SILC_COMMAND_NONE
297 to match any command with the `ident'. If `ident' is non-zero
298 the `callback' will be executed when received reply with command
299 identifier `ident'. */
301 void silc_server_command_pending(SilcServer server,
302 SilcCommand reply_cmd,
304 SilcServerPendingDestructor destructor,
305 SilcCommandCb callback,
308 SilcServerCommandPending *reply;
310 reply = silc_calloc(1, sizeof(*reply));
311 reply->reply_cmd = reply_cmd;
312 reply->ident = ident;
313 reply->context = context;
314 reply->callback = callback;
315 reply->destructor = destructor;
316 silc_dlist_add(server->pending_commands, reply);
319 /* Deletes pending command by reply command type. */
321 void silc_server_command_pending_del(SilcServer server,
322 SilcCommand reply_cmd,
325 SilcServerCommandPending *r;
327 silc_dlist_start(server->pending_commands);
328 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
329 if (r->reply_cmd == reply_cmd && r->ident == ident) {
330 silc_dlist_del(server->pending_commands, r);
336 /* Checks for pending commands and marks callbacks to be called from
337 the command reply function. Returns TRUE if there were pending command. */
339 SilcServerCommandPendingCallbacks
340 silc_server_command_pending_check(SilcServer server,
341 SilcServerCommandReplyContext ctx,
344 uint32 *callbacks_count)
346 SilcServerCommandPending *r;
347 SilcServerCommandPendingCallbacks callbacks = NULL;
350 silc_dlist_start(server->pending_commands);
351 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
352 if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE)
353 && r->ident == ident) {
354 callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
355 callbacks[i].context = r->context;
356 callbacks[i].callback = r->callback;
357 callbacks[i].destructor = r->destructor;
363 *callbacks_count = i;
367 /* Destructor function for pending callbacks. This is called when using
368 pending commands to free the context given for the pending command. */
370 static void silc_server_command_destructor(void *context)
372 silc_server_command_free((SilcServerCommandContext)context);
375 /* Sends simple status message as command reply packet */
378 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
380 SilcCommandStatus status)
384 SILC_LOG_DEBUG(("Sending command status %d", status));
387 silc_command_reply_payload_encode_va(command, status,
388 silc_command_get_ident(cmd->payload),
390 silc_server_packet_send(cmd->server, cmd->sock,
391 SILC_PACKET_COMMAND_REPLY, 0,
392 buffer->data, buffer->len, FALSE);
393 silc_buffer_free(buffer);
396 /* Sends command status reply with one extra argument. The argument
397 type must be sent as argument. */
400 silc_server_command_send_status_data(SilcServerCommandContext cmd,
402 SilcCommandStatus status,
409 SILC_LOG_DEBUG(("Sending command status %d", status));
412 silc_command_reply_payload_encode_va(command, status,
413 silc_command_get_ident(cmd->payload),
414 1, arg_type, arg, arg_len);
415 silc_server_packet_send(cmd->server, cmd->sock,
416 SILC_PACKET_COMMAND_REPLY, 0,
417 buffer->data, buffer->len, FALSE);
418 silc_buffer_free(buffer);
421 /* This function can be called to check whether in the command reply
422 an error occurred. This function has no effect if this is called
423 when the command function was not called as pending command callback.
424 This returns TRUE if error had occurred. */
427 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
428 SilcServerCommandReplyContext cmdr,
431 SilcCommandStatus status;
433 if (!cmd->pending || !cmdr)
436 SILC_GET16_MSB(status, silc_argument_get_arg_type(cmdr->args, 1, NULL));
437 if (status != SILC_STATUS_OK &&
438 status != SILC_STATUS_LIST_START &&
439 status != SILC_STATUS_LIST_ITEM &&
440 status != SILC_STATUS_LIST_END) {
441 /* Send the error message */
442 silc_server_command_send_status_reply(cmd, command, status);
449 /******************************************************************************
453 ******************************************************************************/
456 silc_server_command_whois_parse(SilcServerCommandContext cmd,
457 SilcClientID ***client_id,
458 uint32 *client_id_count,
466 uint32 argc = silc_argument_get_arg_num(cmd->args);
469 /* If client ID is in the command it must be used instead of nickname */
470 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
472 /* No ID, get the nickname@server string and parse it. */
473 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
475 silc_parse_userfqdn(tmp, nickname, server_name);
477 silc_server_command_send_status_reply(cmd, command,
478 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
482 /* Command includes ID, we must use that. Also check whether the command
483 has more than one ID set - take them all. */
485 *client_id = silc_calloc(1, sizeof(**client_id));
486 (*client_id)[0] = silc_id_payload_parse_id(tmp, len);
487 if ((*client_id)[0] == NULL) {
488 silc_free(*client_id);
491 *client_id_count = 1;
493 /* Take all ID's from the command packet */
495 for (k = 1, i = 1; i < argc; i++) {
496 tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
498 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
499 (*client_id_count + 1));
500 (*client_id)[k] = silc_id_payload_parse_id(tmp, len);
501 if ((*client_id)[k] == NULL) {
502 /* Cleanup all and fail */
503 for (i = 0; i < *client_id_count; i++)
504 silc_free((*client_id)[i]);
505 silc_free(*client_id);
508 (*client_id_count)++;
515 /* Get the max count of reply messages allowed */
516 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
525 /* Resolve context used by both WHOIS and IDENTIFY commands */
527 SilcServerEntry router;
529 unsigned char **res_argv;
530 uint32 *res_argv_lens;
531 uint32 *res_argv_types;
533 } *SilcServerResolveContext;
536 silc_server_command_whois_check(SilcServerCommandContext cmd,
537 SilcClientEntry *clients,
538 uint32 clients_count)
540 SilcServer server = cmd->server;
541 SilcClientEntry entry;
542 SilcServerResolveContext resolve = NULL, r = NULL;
543 uint32 resolve_count = 0;
547 for (i = 0; i < clients_count; i++) {
550 if (!entry || (entry->nickname && entry->username && entry->userinfo) ||
551 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
555 /* We need to resolve this entry since it is not complete */
557 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
558 /* The entry is being resolved (and we are not the resolver) so attach
559 to the command reply and we're done with this one. */
560 silc_server_command_pending(server, SILC_COMMAND_NONE,
561 entry->resolve_cmd_ident,
562 silc_server_command_destructor,
563 silc_server_command_whois,
564 silc_server_command_dup(cmd));
567 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
568 /* We've resolved this and it still is not ready. We'll return
569 and are that this will be handled again after it is resolved. */
570 for (i = 0; i < resolve_count; i++) {
571 for (k = 0; k < r->res_argc; k++)
572 silc_free(r->res_argv[k]);
573 silc_free(r->res_argv);
574 silc_free(r->res_argv_lens);
575 silc_free(r->res_argv_types);
580 /* We'll resolve this client */
584 for (k = 0; k < resolve_count; k++) {
585 if (resolve[k].router == entry->router) {
592 resolve = silc_realloc(resolve, sizeof(*resolve) *
593 (resolve_count + 1));
594 r = &resolve[resolve_count];
595 memset(r, 0, sizeof(*r));
596 r->router = entry->router;
597 r->ident = ++server->cmd_ident;
601 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
603 r->res_argv_lens = silc_realloc(r->res_argv_lens,
604 sizeof(*r->res_argv_lens) *
606 r->res_argv_types = silc_realloc(r->res_argv_types,
607 sizeof(*r->res_argv_types) *
609 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
610 r->res_argv[r->res_argc] = silc_calloc(idp->len,
611 sizeof(**r->res_argv));
612 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
613 r->res_argv_lens[r->res_argc] = idp->len;
614 r->res_argv_types[r->res_argc] = r->res_argc + 3;
616 silc_buffer_free(idp);
618 entry->resolve_cmd_ident = r->ident;
619 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
620 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
625 /* Do the resolving */
626 for (i = 0; i < resolve_count; i++) {
631 /* Send WHOIS request. We send WHOIS since we're doing the requesting
632 now anyway so make it a good one. */
633 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
634 r->res_argc, r->res_argv,
638 silc_server_packet_send(server, r->router->connection,
639 SILC_PACKET_COMMAND, cmd->packet->flags,
640 res_cmd->data, res_cmd->len, FALSE);
642 /* Reprocess this packet after received reply */
643 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
645 silc_server_command_destructor,
646 silc_server_command_whois,
647 silc_server_command_dup(cmd));
650 silc_buffer_free(res_cmd);
651 for (k = 0; k < r->res_argc; k++)
652 silc_free(r->res_argv[k]);
653 silc_free(r->res_argv);
654 silc_free(r->res_argv_lens);
655 silc_free(r->res_argv_types);
664 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
665 SilcClientEntry *clients,
666 uint32 clients_count,
669 SilcServer server = cmd->server;
672 SilcBuffer packet, idp, channels;
673 SilcClientEntry entry;
674 SilcCommandStatus status;
675 uint16 ident = silc_command_get_ident(cmd->payload);
676 char nh[256], uh[256];
677 unsigned char idle[4], mode[4];
678 unsigned char *fingerprint;
679 SilcSocketConnection hsock;
682 for (i = 0; i < clients_count; i++)
683 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
686 if (len == 0 && clients_count) {
688 if (entry->nickname) {
689 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
690 SILC_STATUS_ERR_NO_SUCH_NICK,
692 strlen(entry->nickname));
694 SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
695 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
696 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
697 2, idp->data, idp->len);
698 silc_buffer_free(idp);
704 status = SILC_STATUS_OK;
706 status = SILC_STATUS_LIST_START;
708 for (i = 0, k = 0; i < clients_count; i++) {
711 if (!(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
712 if (clients_count == 1) {
713 if (entry->nickname) {
714 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
715 SILC_STATUS_ERR_NO_SUCH_NICK,
717 strlen(entry->nickname));
719 SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
720 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
721 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
722 2, idp->data, idp->len);
723 silc_buffer_free(idp);
730 status = SILC_STATUS_LIST_ITEM;
732 if (clients_count > 1 && k == clients_count - 1)
733 status = SILC_STATUS_LIST_END;
735 if (count && k - 1 == count)
736 status = SILC_STATUS_LIST_END;
738 if (count && k - 1 > count)
741 /* Sanity check, however these should never fail. However, as
742 this sanity check has been added here they have failed. */
743 if (!entry->nickname || !entry->username || !entry->userinfo)
746 /* Send WHOIS reply */
747 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
748 tmp = silc_argument_get_first_arg(cmd->args, NULL);
750 memset(uh, 0, sizeof(uh));
751 memset(nh, 0, sizeof(nh));
752 memset(idle, 0, sizeof(idle));
754 strncat(nh, entry->nickname, strlen(entry->nickname));
755 if (!strchr(entry->nickname, '@')) {
757 if (entry->servername) {
758 strncat(nh, entry->servername, strlen(entry->servername));
760 len = entry->router ? strlen(entry->router->server_name) :
761 strlen(server->server_name);
762 strncat(nh, entry->router ? entry->router->server_name :
763 server->server_name, len);
767 strncat(uh, entry->username, strlen(entry->username));
768 if (!strchr(entry->username, '@')) {
770 hsock = (SilcSocketConnection)entry->connection;
771 len = strlen(hsock->hostname);
772 strncat(uh, hsock->hostname, len);
775 channels = silc_server_get_client_channel_list(server, entry);
777 if (entry->data.fingerprint[0] != 0 && entry->data.fingerprint[1] != 0)
778 fingerprint = entry->data.fingerprint;
782 SILC_PUT32_MSB(entry->mode, mode);
784 if (entry->connection) {
785 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
789 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
791 2, idp->data, idp->len,
795 strlen(entry->userinfo),
796 6, channels ? channels->data : NULL,
797 channels ? channels->len : 0,
801 fingerprint ? 20 : 0);
803 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
804 0, packet->data, packet->len, FALSE);
806 silc_buffer_free(packet);
807 silc_buffer_free(idp);
809 silc_buffer_free(channels);
816 silc_server_command_whois_process(SilcServerCommandContext cmd)
818 SilcServer server = cmd->server;
819 char *nick = NULL, *server_name = NULL;
821 SilcClientEntry *clients = NULL, entry;
822 SilcClientID **client_id = NULL;
823 uint32 client_id_count = 0, clients_count = 0;
825 bool check_global = FALSE;
827 /* Protocol dictates that we must always send the received WHOIS request
828 to our router if we are normal server, so let's do it now unless we
829 are standalone. We will not send any replies to the client until we
830 have received reply from the router. */
831 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
832 server->server_type == SILC_SERVER && !cmd->pending &&
833 !server->standalone) {
837 old_ident = silc_command_get_ident(cmd->payload);
838 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
839 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
841 /* Send WHOIS command to our router */
842 silc_server_packet_send(server, (SilcSocketConnection)
843 server->router->connection,
844 SILC_PACKET_COMMAND, cmd->packet->flags,
845 tmpbuf->data, tmpbuf->len, TRUE);
847 /* Reprocess this packet after received reply from router */
848 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
849 silc_command_get_ident(cmd->payload),
850 silc_server_command_destructor,
851 silc_server_command_whois,
852 silc_server_command_dup(cmd));
855 silc_command_set_ident(cmd->payload, old_ident);
857 silc_buffer_free(tmpbuf);
862 /* We are ready to process the command request. Let's search for the
863 requested client and send reply to the requesting client. */
865 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
867 else if (server->server_type != SILC_SERVER)
870 /* Parse the whois request */
871 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
872 &nick, &server_name, &count,
876 /* Get all clients matching that ID or nickname from local list */
877 if (client_id_count) {
878 /* Check all Client ID's received in the command packet */
879 for (i = 0; i < client_id_count; i++) {
880 entry = silc_idlist_find_client_by_id(server->local_list,
881 client_id[i], TRUE, NULL);
882 if (!entry && check_global)
883 entry = silc_idlist_find_client_by_id(server->global_list,
884 client_id[i], TRUE, NULL);
886 clients = silc_realloc(clients, sizeof(*clients) *
887 (clients_count + 1));
888 clients[clients_count++] = entry;
892 if (!silc_idlist_get_clients_by_hash(server->local_list,
893 nick, server->md5hash,
894 &clients, &clients_count))
895 silc_idlist_get_clients_by_nickname(server->local_list,
897 &clients, &clients_count);
899 if (!silc_idlist_get_clients_by_hash(server->global_list,
900 nick, server->md5hash,
901 &clients, &clients_count))
902 silc_idlist_get_clients_by_nickname(server->global_list,
904 &clients, &clients_count);
909 /* Such client(s) really does not exist in the SILC network. */
910 if (!client_id_count) {
911 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
912 SILC_STATUS_ERR_NO_SUCH_NICK,
913 3, nick, strlen(nick));
915 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
916 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
917 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
918 2, idp->data, idp->len);
919 silc_buffer_free(idp);
924 /* Router always finds the client entry if it exists in the SILC network.
925 However, it might be incomplete entry and does not include all the
926 mandatory fields that WHOIS command reply requires. Check for these and
927 make query from the server who owns the client if some fields are
929 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
934 /* Send the command reply */
935 silc_server_command_whois_send_reply(cmd, clients, clients_count,
939 if (client_id_count) {
940 for (i = 0; i < client_id_count; i++)
941 silc_free(client_id[i]);
942 silc_free(client_id);
946 silc_free(server_name);
951 /* Server side of command WHOIS. Processes user's query and sends found
952 results as command replies back to the client. */
954 SILC_SERVER_CMD_FUNC(whois)
956 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
959 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 3328);
961 ret = silc_server_command_whois_process(cmd);
964 silc_server_command_free(cmd);
967 /******************************************************************************
971 ******************************************************************************/
974 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
982 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
984 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
985 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
989 /* Get the nickname@server string and parse it. */
990 silc_parse_userfqdn(tmp, nickname, server_name);
992 /* Get the max count of reply messages allowed */
993 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1003 silc_server_command_whowas_check(SilcServerCommandContext cmd,
1004 SilcClientEntry *clients,
1005 uint32 clients_count)
1007 SilcServer server = cmd->server;
1009 SilcClientEntry entry;
1011 for (i = 0; i < clients_count; i++) {
1014 if (!entry->nickname || !entry->username) {
1021 old_ident = silc_command_get_ident(cmd->payload);
1022 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1023 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1025 /* Send WHOWAS command */
1026 silc_server_packet_send(server, entry->router->connection,
1027 SILC_PACKET_COMMAND, cmd->packet->flags,
1028 tmpbuf->data, tmpbuf->len, TRUE);
1030 /* Reprocess this packet after received reply */
1031 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1032 silc_command_get_ident(cmd->payload),
1033 silc_server_command_destructor,
1034 silc_server_command_whowas,
1035 silc_server_command_dup(cmd));
1036 cmd->pending = TRUE;
1038 silc_command_set_ident(cmd->payload, old_ident);
1040 silc_buffer_free(tmpbuf);
1049 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1050 SilcClientEntry *clients,
1051 uint32 clients_count)
1053 SilcServer server = cmd->server;
1055 int i, count = 0, len;
1056 SilcBuffer packet, idp;
1057 SilcClientEntry entry = NULL;
1058 SilcCommandStatus status;
1059 uint16 ident = silc_command_get_ident(cmd->payload);
1061 char nh[256], uh[256];
1063 status = SILC_STATUS_OK;
1064 if (clients_count > 1)
1065 status = SILC_STATUS_LIST_START;
1067 for (i = 0; i < clients_count; i++) {
1070 /* We will take only clients that are not valid anymore. They are the
1071 ones that are not registered anymore but still have a ID. They
1072 have disconnected us, and thus valid for WHOWAS. */
1073 if (entry->data.status & SILC_IDLIST_STATUS_REGISTERED)
1075 if (entry->id == NULL)
1078 if (count && i - 1 == count)
1083 if (clients_count > 2)
1084 status = SILC_STATUS_LIST_ITEM;
1086 if (clients_count > 1 && i == clients_count - 1)
1087 status = SILC_STATUS_LIST_END;
1089 /* Sanity check, however these should never fail. However, as
1090 this sanity check has been added here they have failed. */
1091 if (!entry->nickname || !entry->username)
1094 /* Send WHOWAS reply */
1095 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1096 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1098 memset(uh, 0, sizeof(uh));
1099 memset(nh, 0, sizeof(nh));
1101 strncat(nh, entry->nickname, strlen(entry->nickname));
1102 if (!strchr(entry->nickname, '@')) {
1103 strncat(nh, "@", 1);
1104 if (entry->servername) {
1105 strncat(nh, entry->servername, strlen(entry->servername));
1107 len = entry->router ? strlen(entry->router->server_name) :
1108 strlen(server->server_name);
1109 strncat(nh, entry->router ? entry->router->server_name :
1110 server->server_name, len);
1114 strncat(uh, entry->username, strlen(entry->username));
1115 if (!strchr(entry->username, '@')) {
1116 strncat(uh, "@", 1);
1117 strcat(uh, "*private*");
1120 if (entry->userinfo)
1122 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1124 2, idp->data, idp->len,
1128 strlen(entry->userinfo));
1131 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1133 2, idp->data, idp->len,
1137 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1138 0, packet->data, packet->len, FALSE);
1140 silc_buffer_free(packet);
1141 silc_buffer_free(idp);
1144 if (found == FALSE && entry)
1145 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1146 SILC_STATUS_ERR_NO_SUCH_NICK,
1148 strlen(entry->nickname));
1152 silc_server_command_whowas_process(SilcServerCommandContext cmd)
1154 SilcServer server = cmd->server;
1155 char *nick = NULL, *server_name = NULL;
1157 SilcClientEntry *clients = NULL;
1158 uint32 clients_count = 0;
1160 bool check_global = FALSE;
1162 /* Protocol dictates that we must always send the received WHOWAS request
1163 to our router if we are normal server, so let's do it now unless we
1164 are standalone. We will not send any replies to the client until we
1165 have received reply from the router. */
1166 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1167 server->server_type == SILC_SERVER && !cmd->pending &&
1168 !server->standalone) {
1172 old_ident = silc_command_get_ident(cmd->payload);
1173 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1174 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1176 /* Send WHOWAS command to our router */
1177 silc_server_packet_send(server, (SilcSocketConnection)
1178 server->router->connection,
1179 SILC_PACKET_COMMAND, cmd->packet->flags,
1180 tmpbuf->data, tmpbuf->len, TRUE);
1182 /* Reprocess this packet after received reply from router */
1183 silc_server_command_pending(server, SILC_COMMAND_WHOWAS,
1184 silc_command_get_ident(cmd->payload),
1185 silc_server_command_destructor,
1186 silc_server_command_whowas,
1187 silc_server_command_dup(cmd));
1188 cmd->pending = TRUE;
1190 silc_command_set_ident(cmd->payload, old_ident);
1192 silc_buffer_free(tmpbuf);
1197 /* We are ready to process the command request. Let's search for the
1198 requested client and send reply to the requesting client. */
1200 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1201 check_global = TRUE;
1202 else if (server->server_type != SILC_SERVER)
1203 check_global = TRUE;
1205 /* Parse the whowas request */
1206 if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1209 /* Get all clients matching that nickname from local list */
1210 if (!silc_idlist_get_clients_by_nickname(server->local_list,
1212 &clients, &clients_count))
1213 silc_idlist_get_clients_by_hash(server->local_list,
1214 nick, server->md5hash,
1215 &clients, &clients_count);
1217 /* Check global list as well */
1219 if (!silc_idlist_get_clients_by_nickname(server->global_list,
1221 &clients, &clients_count))
1222 silc_idlist_get_clients_by_hash(server->global_list,
1223 nick, server->md5hash,
1224 &clients, &clients_count);
1228 /* Such a client really does not exist in the SILC network. */
1229 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1230 SILC_STATUS_ERR_NO_SUCH_NICK,
1231 3, nick, strlen(nick));
1235 if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1240 /* Send the command reply to the client */
1241 silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1246 silc_free(server_name);
1251 /* Server side of command WHOWAS. */
1253 SILC_SERVER_CMD_FUNC(whowas)
1255 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1258 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1260 ret = silc_server_command_whowas_process(cmd);
1263 silc_server_command_free(cmd);
1266 /******************************************************************************
1270 ******************************************************************************/
1273 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1274 SilcClientEntry **clients,
1275 uint32 *clients_count,
1276 SilcServerEntry **servers,
1277 uint32 *servers_count,
1278 SilcChannelEntry **channels,
1279 uint32 *channels_count,
1282 SilcServer server = cmd->server;
1285 uint32 argc = silc_argument_get_arg_num(cmd->args);
1287 bool check_global = FALSE;
1292 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1293 check_global = TRUE;
1294 else if (server->server_type != SILC_SERVER)
1295 check_global = TRUE;
1297 /* If ID Payload is in the command it must be used instead of names */
1298 tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1300 /* No ID, get the names. */
1302 /* Try to get nickname@server. */
1303 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1306 char *nick_server = NULL;
1308 silc_parse_userfqdn(tmp, &nick, &nick_server);
1310 if (!silc_idlist_get_clients_by_hash(server->local_list,
1311 nick, server->md5hash,
1312 clients, clients_count))
1313 silc_idlist_get_clients_by_nickname(server->local_list,
1315 clients, clients_count);
1317 if (!silc_idlist_get_clients_by_hash(server->global_list,
1318 nick, server->md5hash,
1319 clients, clients_count))
1320 silc_idlist_get_clients_by_nickname(server->global_list,
1322 clients, clients_count);
1326 silc_free(nick_server);
1329 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1330 SILC_STATUS_ERR_NO_SUCH_NICK,
1331 3, tmp, strlen(tmp));
1336 /* Try to get server name */
1337 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1339 entry = silc_idlist_find_server_by_name(server->local_list,
1341 if (!entry && check_global)
1342 entry = silc_idlist_find_server_by_name(server->global_list,
1345 *servers = silc_realloc(*servers, sizeof(**servers) *
1346 (*servers_count + 1));
1347 (*servers)[(*servers_count)++] = entry;
1351 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1352 SILC_STATUS_ERR_NO_SUCH_SERVER,
1353 3, tmp, strlen(tmp));
1358 /* Try to get channel name */
1359 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1361 entry = silc_idlist_find_channel_by_name(server->local_list,
1363 if (!entry && check_global)
1364 entry = silc_idlist_find_channel_by_name(server->global_list,
1367 *channels = silc_realloc(*channels, sizeof(**channels) *
1368 (*channels_count + 1));
1369 (*channels)[(*channels_count)++] = entry;
1373 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1374 SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1375 3, tmp, strlen(tmp));
1380 if (!(*clients) && !(*servers) && !(*channels)) {
1381 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1382 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1386 /* Command includes ID, we must use that. Also check whether the command
1387 has more than one ID set - take them all. */
1389 /* Take all ID's from the command packet */
1390 for (i = 0; i < argc; i++) {
1393 tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
1397 idp = silc_id_payload_parse_data(tmp, len);
1399 silc_free(*clients);
1400 silc_free(*servers);
1401 silc_free(*channels);
1402 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1403 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1407 id = silc_id_payload_get_id(idp);
1409 switch (silc_id_payload_get_type(idp)) {
1411 case SILC_ID_CLIENT:
1412 entry = (void *)silc_idlist_find_client_by_id(server->local_list,
1414 if (!entry && check_global)
1415 entry = (void *)silc_idlist_find_client_by_id(server->global_list,
1418 *clients = silc_realloc(*clients, sizeof(**clients) *
1419 (*clients_count + 1));
1420 (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
1422 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1423 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1430 case SILC_ID_SERVER:
1431 entry = (void *)silc_idlist_find_server_by_id(server->local_list,
1433 if (!entry && check_global)
1434 entry = (void *)silc_idlist_find_server_by_id(server->global_list,
1437 *servers = silc_realloc(*servers, sizeof(**servers) *
1438 (*servers_count + 1));
1439 (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
1441 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1442 SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
1448 case SILC_ID_CHANNEL:
1449 entry = (void *)silc_idlist_find_channel_by_id(server->local_list,
1451 if (!entry && check_global)
1452 entry = (void *)silc_idlist_find_channel_by_id(server->global_list,
1455 *channels = silc_realloc(*channels, sizeof(**channels) *
1456 (*channels_count + 1));
1457 (*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
1459 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1460 SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
1472 silc_free(*clients);
1473 silc_free(*servers);
1474 silc_free(*channels);
1478 /* Get the max count of reply messages allowed */
1479 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1488 /* Checks that all mandatory fields in client entry are present. If not
1489 then send WHOIS request to the server who owns the client. We use
1490 WHOIS because we want to get as much information as possible at once. */
1493 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1494 SilcClientEntry *clients,
1495 uint32 clients_count)
1497 SilcServer server = cmd->server;
1498 SilcClientEntry entry;
1499 SilcServerResolveContext resolve = NULL, r = NULL;
1500 uint32 resolve_count = 0;
1504 for (i = 0; i < clients_count; i++) {
1507 if (!entry || entry->nickname ||
1508 !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
1512 /* We need to resolve this entry since it is not complete */
1514 if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1515 /* The entry is being resolved (and we are not the resolver) so attach
1516 to the command reply and we're done with this one. */
1517 silc_server_command_pending(server, SILC_COMMAND_NONE,
1518 entry->resolve_cmd_ident,
1519 silc_server_command_destructor,
1520 silc_server_command_identify,
1521 silc_server_command_dup(cmd));
1524 if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1525 /* We've resolved this and it still is not ready. We'll return
1526 and are that this will be handled again after it is resolved. */
1527 for (i = 0; i < resolve_count; i++) {
1528 for (k = 0; k < r->res_argc; k++)
1529 silc_free(r->res_argv[k]);
1530 silc_free(r->res_argv);
1531 silc_free(r->res_argv_lens);
1532 silc_free(r->res_argv_types);
1537 /* We'll resolve this client */
1541 for (k = 0; k < resolve_count; k++) {
1542 if (resolve[k].router == entry->router) {
1549 resolve = silc_realloc(resolve, sizeof(*resolve) *
1550 (resolve_count + 1));
1551 r = &resolve[resolve_count];
1552 memset(r, 0, sizeof(*r));
1553 r->router = entry->router;
1554 r->ident = ++server->cmd_ident;
1558 r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1560 r->res_argv_lens = silc_realloc(r->res_argv_lens,
1561 sizeof(*r->res_argv_lens) *
1563 r->res_argv_types = silc_realloc(r->res_argv_types,
1564 sizeof(*r->res_argv_types) *
1566 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1567 r->res_argv[r->res_argc] = silc_calloc(idp->len,
1568 sizeof(**r->res_argv));
1569 memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1570 r->res_argv_lens[r->res_argc] = idp->len;
1571 r->res_argv_types[r->res_argc] = r->res_argc + 3;
1573 silc_buffer_free(idp);
1575 entry->resolve_cmd_ident = r->ident;
1576 entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1577 entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1582 /* Do the resolving */
1583 for (i = 0; i < resolve_count; i++) {
1588 /* Send WHOIS request. We send WHOIS since we're doing the requesting
1589 now anyway so make it a good one. */
1590 res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1591 r->res_argc, r->res_argv,
1595 silc_server_packet_send(server, r->router->connection,
1596 SILC_PACKET_COMMAND, cmd->packet->flags,
1597 res_cmd->data, res_cmd->len, FALSE);
1599 /* Reprocess this packet after received reply */
1600 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
1602 silc_server_command_destructor,
1603 silc_server_command_identify,
1604 silc_server_command_dup(cmd));
1605 cmd->pending = TRUE;
1607 silc_buffer_free(res_cmd);
1608 for (k = 0; k < r->res_argc; k++)
1609 silc_free(r->res_argv[k]);
1610 silc_free(r->res_argv);
1611 silc_free(r->res_argv_lens);
1612 silc_free(r->res_argv_types);
1621 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1622 SilcClientEntry *clients,
1623 uint32 clients_count,
1624 SilcServerEntry *servers,
1625 uint32 servers_count,
1626 SilcChannelEntry *channels,
1627 uint32 channels_count,
1630 SilcServer server = cmd->server;
1632 SilcBuffer packet, idp;
1633 SilcCommandStatus status;
1634 uint16 ident = silc_command_get_ident(cmd->payload);
1635 char nh[256], uh[256];
1636 SilcSocketConnection hsock;
1638 status = SILC_STATUS_OK;
1641 SilcClientEntry entry;
1644 for (i = 0; i < clients_count; i++)
1645 if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1648 if (len == 0 && clients_count) {
1650 if (entry->nickname) {
1651 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1652 SILC_STATUS_ERR_NO_SUCH_NICK,
1654 strlen(entry->nickname));
1656 SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1657 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1658 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1659 2, idp->data, idp->len);
1660 silc_buffer_free(idp);
1667 status = SILC_STATUS_LIST_START;
1669 for (i = 0, k = 0; i < clients_count; i++) {
1672 if (!(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1673 if (clients_count == 1) {
1674 SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1675 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1676 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1677 2, idp->data, idp->len);
1678 silc_buffer_free(idp);
1684 status = SILC_STATUS_LIST_ITEM;
1685 if (clients_count > 1 && k == clients_count - 1
1686 && !servers_count && !channels_count)
1687 status = SILC_STATUS_LIST_END;
1688 if (count && k - 1 == count)
1689 status = SILC_STATUS_LIST_END;
1690 if (count && k - 1 > count)
1693 /* Send IDENTIFY reply */
1694 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1696 memset(uh, 0, sizeof(uh));
1697 memset(nh, 0, sizeof(nh));
1699 strncat(nh, entry->nickname, strlen(entry->nickname));
1700 if (!strchr(entry->nickname, '@')) {
1701 strncat(nh, "@", 1);
1702 if (entry->servername) {
1703 strncat(nh, entry->servername, strlen(entry->servername));
1705 len = entry->router ? strlen(entry->router->server_name) :
1706 strlen(server->server_name);
1707 strncat(nh, entry->router ? entry->router->server_name :
1708 server->server_name, len);
1712 if (!entry->username) {
1713 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1715 2, idp->data, idp->len,
1718 strncat(uh, entry->username, strlen(entry->username));
1719 if (!strchr(entry->username, '@')) {
1720 strncat(uh, "@", 1);
1721 hsock = (SilcSocketConnection)entry->connection;
1722 len = strlen(hsock->hostname);
1723 strncat(uh, hsock->hostname, len);
1726 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1728 2, idp->data, idp->len,
1733 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1734 0, packet->data, packet->len, FALSE);
1736 silc_buffer_free(packet);
1737 silc_buffer_free(idp);
1743 status = (status == SILC_STATUS_LIST_ITEM ?
1744 SILC_STATUS_LIST_ITEM : SILC_STATUS_OK);
1747 SilcServerEntry entry;
1749 if (status == SILC_STATUS_OK && servers_count > 1)
1750 status = SILC_STATUS_LIST_START;
1752 for (i = 0, k = 0; i < servers_count; i++) {
1756 status = SILC_STATUS_LIST_ITEM;
1757 if (servers_count > 1 && k == servers_count - 1 && !channels_count)
1758 status = SILC_STATUS_LIST_END;
1759 if (count && k - 1 == count)
1760 status = SILC_STATUS_LIST_END;
1761 if (count && k - 1 > count)
1764 /* Send IDENTIFY reply */
1765 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1766 if (entry->server_name) {
1768 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1770 2, idp->data, idp->len,
1771 3, entry->server_name,
1772 strlen(entry->server_name));
1774 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1776 2, idp->data, idp->len);
1779 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1780 0, packet->data, packet->len, FALSE);
1782 silc_buffer_free(packet);
1783 silc_buffer_free(idp);
1789 status = (status == SILC_STATUS_LIST_ITEM ?
1790 SILC_STATUS_LIST_ITEM : SILC_STATUS_OK);
1793 SilcChannelEntry entry;
1795 if (status == SILC_STATUS_OK && channels_count > 1)
1796 status = SILC_STATUS_LIST_START;
1798 for (i = 0, k = 0; i < channels_count; i++) {
1799 entry = channels[i];
1802 status = SILC_STATUS_LIST_ITEM;
1803 if (channels_count > 1 && k == channels_count - 1)
1804 status = SILC_STATUS_LIST_END;
1805 if (count && k - 1 == count)
1806 status = SILC_STATUS_LIST_END;
1807 if (count && k - 1 > count)
1810 /* Send IDENTIFY reply */
1811 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1812 if (entry->channel_name) {
1814 silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1816 2, idp->data, idp->len,
1817 3, entry->channel_name,
1818 strlen(entry->channel_name));
1820 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1822 2, idp->data, idp->len);
1825 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1826 0, packet->data, packet->len, FALSE);
1828 silc_buffer_free(packet);
1829 silc_buffer_free(idp);
1837 silc_server_command_identify_process(SilcServerCommandContext cmd)
1839 SilcServer server = cmd->server;
1842 SilcClientEntry *clients = NULL;
1843 SilcServerEntry *servers = NULL;
1844 SilcChannelEntry *channels = NULL;
1845 uint32 clients_count = 0, servers_count = 0, channels_count = 0;
1847 /* Protocol dictates that we must always send the received IDENTIFY request
1848 to our router if we are normal server, so let's do it now unless we
1849 are standalone. We will not send any replies to the client until we
1850 have received reply from the router. */
1851 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1852 server->server_type == SILC_SERVER && !cmd->pending &&
1853 !server->standalone) {
1857 old_ident = silc_command_get_ident(cmd->payload);
1858 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1859 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1861 /* Send IDENTIFY command to our router */
1862 silc_server_packet_send(server, (SilcSocketConnection)
1863 server->router->connection,
1864 SILC_PACKET_COMMAND, cmd->packet->flags,
1865 tmpbuf->data, tmpbuf->len, TRUE);
1867 /* Reprocess this packet after received reply from router */
1868 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1869 silc_command_get_ident(cmd->payload),
1870 silc_server_command_destructor,
1871 silc_server_command_identify,
1872 silc_server_command_dup(cmd));
1873 cmd->pending = TRUE;
1875 silc_command_set_ident(cmd->payload, old_ident);
1877 silc_buffer_free(tmpbuf);
1882 /* We are ready to process the command request. Let's search for the
1883 requested client and send reply to the requesting client. */
1885 /* Parse the IDENTIFY request */
1886 if (!silc_server_command_identify_parse(cmd,
1887 &clients, &clients_count,
1888 &servers, &servers_count,
1889 &channels, &channels_count,
1893 /* Check that all mandatory fields are present and request those data
1894 from the server who owns the client if necessary. */
1895 if (clients && !silc_server_command_identify_check_client(cmd, clients,
1901 /* Send the command reply to the client */
1902 silc_server_command_identify_send_reply(cmd,
1903 clients, clients_count,
1904 servers, servers_count,
1905 channels, channels_count,
1911 silc_free(channels);
1916 SILC_SERVER_CMD_FUNC(identify)
1918 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1921 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1923 ret = silc_server_command_identify_process(cmd);
1926 silc_server_command_free(cmd);
1929 /* Checks string for bad characters and returns TRUE if they are found. */
1931 static int silc_server_command_bad_chars(char *nick)
1935 for (i = 0; i < strlen(nick); i++) {
1936 if (!isascii(nick[i]))
1938 if (nick[i] <= 32) return TRUE;
1939 if (nick[i] == ' ') return TRUE;
1940 if (nick[i] == '\\') return TRUE;
1941 if (nick[i] == '\"') return TRUE;
1942 if (nick[i] == '*') return TRUE;
1943 if (nick[i] == '?') return TRUE;
1944 if (nick[i] == ',') return TRUE;
1945 if (nick[i] == '@') return TRUE;
1946 if (nick[i] == ':') return TRUE;
1947 if (nick[i] == '/') return TRUE;
1948 if (nick[i] == '[') return TRUE;
1949 if (nick[i] == '[') return TRUE;
1950 if (nick[i] == '(') return TRUE;
1951 if (nick[i] == ')') return TRUE;
1952 if (nick[i] == '{') return TRUE;
1953 if (nick[i] == '}') return TRUE;
1954 if (nick[i] == '<') return TRUE;
1955 if (nick[i] == '>') return TRUE;
1961 /* Server side of command NICK. Sets nickname for user. Setting
1962 nickname causes generation of a new client ID for the client. The
1963 new client ID is sent to the client after changing the nickname. */
1965 SILC_SERVER_CMD_FUNC(nick)
1967 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1968 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1969 SilcServer server = cmd->server;
1970 SilcBuffer packet, nidp, oidp = NULL;
1971 SilcClientID *new_id;
1973 uint16 ident = silc_command_get_ident(cmd->payload);
1976 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1979 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
1981 /* Check nickname */
1982 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1983 if (silc_server_command_bad_chars(nick) == TRUE) {
1984 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1985 SILC_STATUS_ERR_BAD_NICKNAME);
1989 if (strlen(nick) > 128)
1992 /* Check for same nickname */
1993 if (!strcmp(client->nickname, nick)) {
1994 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1998 /* Create new Client ID */
1999 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
2001 cmd->server->md5hash, nick,
2004 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2007 /* Send notify about nickname change to our router. We send the new
2008 ID and ask to replace it with the old one. If we are router the
2009 packet is broadcasted. Send NICK_CHANGE notify. */
2010 if (!server->standalone)
2011 silc_server_send_notify_nick_change(server, server->router->connection,
2012 server->server_type == SILC_SERVER ?
2013 FALSE : TRUE, client->id,
2016 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2018 /* Remove old cache entry */
2019 silc_idcache_del_by_context(server->local_list->clients, client);
2022 silc_free(client->id);
2024 /* Save the nickname as this client is our local client */
2025 silc_free(client->nickname);
2027 client->nickname = strdup(nick);
2028 client->id = new_id;
2030 /* Update client cache */
2031 silc_idcache_add(server->local_list->clients, client->nickname,
2032 client->id, (void *)client, FALSE);
2034 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2036 /* Send NICK_CHANGE notify to the client's channels */
2037 silc_server_send_notify_on_channels(server, NULL, client,
2038 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
2039 oidp->data, oidp->len,
2040 nidp->data, nidp->len);
2043 /* Send the new Client ID as reply command back to client */
2044 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
2045 SILC_STATUS_OK, ident, 1,
2046 2, nidp->data, nidp->len);
2047 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2048 0, packet->data, packet->len, FALSE);
2050 silc_buffer_free(packet);
2051 silc_buffer_free(nidp);
2053 silc_buffer_free(oidp);
2056 silc_server_command_free(cmd);
2059 /* Sends the LIST command reply */
2062 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2063 SilcChannelEntry *lch,
2065 SilcChannelEntry *gch,
2069 SilcBuffer packet, idp;
2070 SilcChannelEntry entry;
2071 SilcCommandStatus status;
2072 uint16 ident = silc_command_get_ident(cmd->payload);
2074 unsigned char usercount[4];
2077 for (i = 0; i < lch_count; i++)
2078 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2080 for (i = 0; i < gch_count; i++)
2081 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2084 status = SILC_STATUS_OK;
2085 if ((lch_count + gch_count) > 1)
2086 status = SILC_STATUS_LIST_START;
2089 for (i = 0; i < lch_count; i++) {
2096 status = SILC_STATUS_LIST_ITEM;
2098 if (lch_count > 1 && i == lch_count - 1 && !gch_count)
2099 status = SILC_STATUS_LIST_END;
2101 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2103 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2104 topic = "*private*";
2105 memset(usercount, 0, sizeof(usercount));
2107 topic = entry->topic;
2108 users = silc_hash_table_count(entry->user_list);
2109 SILC_PUT32_MSB(users, usercount);
2112 /* Send the reply */
2115 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2117 2, idp->data, idp->len,
2118 3, entry->channel_name,
2119 strlen(entry->channel_name),
2120 4, topic, strlen(topic),
2124 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2126 2, idp->data, idp->len,
2127 3, entry->channel_name,
2128 strlen(entry->channel_name),
2130 silc_server_packet_send(cmd->server, cmd->sock,
2131 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2132 packet->len, FALSE);
2133 silc_buffer_free(packet);
2134 silc_buffer_free(idp);
2137 status = i ? SILC_STATUS_LIST_ITEM : SILC_STATUS_OK;
2140 for (i = 0; i < gch_count; i++) {
2147 status = SILC_STATUS_LIST_ITEM;
2149 if (gch_count > 1 && i == lch_count - 1)
2150 status = SILC_STATUS_LIST_END;
2152 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2154 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2155 topic = "*private*";
2156 memset(usercount, 0, sizeof(usercount));
2158 topic = entry->topic;
2159 users = silc_hash_table_count(entry->user_list);
2160 SILC_PUT32_MSB(users, usercount);
2163 /* Send the reply */
2166 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2168 2, idp->data, idp->len,
2169 3, entry->channel_name,
2170 strlen(entry->channel_name),
2171 4, topic, strlen(topic),
2175 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2177 2, idp->data, idp->len,
2178 3, entry->channel_name,
2179 strlen(entry->channel_name),
2181 silc_server_packet_send(cmd->server, cmd->sock,
2182 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2183 packet->len, FALSE);
2184 silc_buffer_free(packet);
2185 silc_buffer_free(idp);
2189 /* Server side of LIST command. This lists the channel of the requested
2190 server. Secret channels are not listed. */
2192 SILC_SERVER_CMD_FUNC(list)
2194 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2195 SilcServer server = cmd->server;
2196 SilcChannelID *channel_id = NULL;
2199 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2200 uint32 lch_count = 0, gch_count = 0;
2202 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2204 /* If we are normal server, send the command to router, since we
2205 want to know all channels in the network. */
2206 if (!cmd->pending && server->server_type == SILC_SERVER &&
2207 !server->standalone) {
2211 old_ident = silc_command_get_ident(cmd->payload);
2212 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2213 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2214 silc_server_packet_send(server, server->router->connection,
2215 SILC_PACKET_COMMAND, cmd->packet->flags,
2216 tmpbuf->data, tmpbuf->len, TRUE);
2218 /* Reprocess this packet after received reply from router */
2219 silc_server_command_pending(server, SILC_COMMAND_LIST,
2220 silc_command_get_ident(cmd->payload),
2221 silc_server_command_destructor,
2222 silc_server_command_list,
2223 silc_server_command_dup(cmd));
2224 cmd->pending = TRUE;
2225 silc_command_set_ident(cmd->payload, old_ident);
2226 silc_buffer_free(tmpbuf);
2230 /* Get Channel ID */
2231 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2233 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2235 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2236 SILC_STATUS_ERR_NO_CHANNEL_ID);
2241 /* Get the channels from local list */
2242 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2245 /* Get the channels from global list */
2246 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2249 /* Send the reply */
2250 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2251 gchannels, gch_count);
2254 silc_server_command_free(cmd);
2257 /* Server side of TOPIC command. Sets topic for channel and/or returns
2258 current topic to client. */
2260 SILC_SERVER_CMD_FUNC(topic)
2262 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2263 SilcServer server = cmd->server;
2264 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2265 SilcChannelID *channel_id;
2266 SilcChannelEntry channel;
2267 SilcChannelClientEntry chl;
2268 SilcBuffer packet, idp;
2270 uint32 argc, tmp_len;
2271 uint16 ident = silc_command_get_ident(cmd->payload);
2273 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2275 argc = silc_argument_get_arg_num(cmd->args);
2277 /* Get Channel ID */
2278 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2280 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2281 SILC_STATUS_ERR_NO_CHANNEL_ID);
2284 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2286 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2287 SILC_STATUS_ERR_NO_CHANNEL_ID);
2291 /* Check whether the channel exists */
2292 channel = silc_idlist_find_channel_by_id(server->local_list,
2295 channel = silc_idlist_find_channel_by_id(server->global_list,
2298 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2299 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2306 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2308 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2309 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2313 if (strlen(tmp) > 256) {
2314 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2315 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2319 /* See whether the client is on channel and has rights to change topic */
2320 if (!silc_hash_table_find(channel->user_list, client, NULL,
2322 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2323 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2327 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2328 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2329 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2330 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2335 /* Set the topic for channel */
2336 silc_free(channel->topic);
2337 channel->topic = strdup(tmp);
2339 /* Send TOPIC_SET notify type to the network */
2340 if (!server->standalone)
2341 silc_server_send_notify_topic_set(server, server->router->connection,
2342 server->server_type == SILC_ROUTER ?
2343 TRUE : FALSE, channel, client->id,
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);
2359 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2360 SILC_STATUS_OK, ident, 2,
2361 2, idp->data, idp->len,
2363 strlen(channel->topic));
2365 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2366 SILC_STATUS_OK, ident, 1,
2367 2, idp->data, idp->len);
2368 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2369 0, packet->data, packet->len, FALSE);
2371 silc_buffer_free(packet);
2372 silc_buffer_free(idp);
2373 silc_free(channel_id);
2376 silc_server_command_free(cmd);
2379 /* Server side of INVITE command. Invites some client to join some channel.
2380 This command is also used to manage the invite list of the channel. */
2382 SILC_SERVER_CMD_FUNC(invite)
2384 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2385 SilcServer server = cmd->server;
2386 SilcSocketConnection sock = cmd->sock, dest_sock;
2387 SilcChannelClientEntry chl;
2388 SilcClientEntry sender, dest;
2389 SilcClientID *dest_id = NULL;
2390 SilcChannelEntry channel;
2391 SilcChannelID *channel_id = NULL;
2392 SilcIDListData idata;
2393 SilcBuffer idp, idp2, packet;
2394 unsigned char *tmp, *add, *del;
2396 uint16 ident = silc_command_get_ident(cmd->payload);
2398 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2400 /* Get Channel ID */
2401 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2403 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2404 SILC_STATUS_ERR_NO_CHANNEL_ID);
2407 channel_id = silc_id_payload_parse_id(tmp, len);
2409 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2410 SILC_STATUS_ERR_NO_CHANNEL_ID);
2414 /* Get the channel entry */
2415 channel = silc_idlist_find_channel_by_id(server->local_list,
2418 channel = silc_idlist_find_channel_by_id(server->global_list,
2421 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2422 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2427 /* Check whether the sender of this command is on the channel. */
2428 sender = (SilcClientEntry)sock->user_data;
2429 if (!silc_server_client_on_channel(sender, channel)) {
2430 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2431 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2435 /* Check whether the channel is invite-only channel. If yes then the
2436 sender of this command must be at least channel operator. */
2437 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2438 silc_hash_table_find(channel->user_list, sender, NULL, (void *)&chl);
2439 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2440 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2441 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2446 /* Get destination client ID */
2447 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2451 dest_id = silc_id_payload_parse_id(tmp, len);
2453 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2454 SILC_STATUS_ERR_NO_CLIENT_ID);
2458 /* Get the client entry */
2459 dest = silc_server_get_client_resolve(server, dest_id);
2461 if (server->server_type != SILC_SERVER) {
2462 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2463 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2467 /* The client info is being resolved. Reprocess this packet after
2468 receiving the reply to the query. */
2469 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2471 silc_server_command_destructor,
2472 silc_server_command_invite,
2473 silc_server_command_dup(cmd));
2474 cmd->pending = TRUE;
2475 silc_free(channel_id);
2480 /* Check whether the requested client is already on the channel. */
2481 if (silc_server_client_on_channel(dest, channel)) {
2482 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2483 SILC_STATUS_ERR_USER_ON_CHANNEL);
2487 /* Get route to the client */
2488 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2490 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2491 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2495 memset(invite, 0, sizeof(invite));
2496 strncat(invite, dest->nickname, strlen(dest->nickname));
2497 strncat(invite, "!", 1);
2498 strncat(invite, dest->username, strlen(dest->username));
2499 if (!strchr(dest->username, '@')) {
2500 strncat(invite, "@", 1);
2501 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2504 len = strlen(invite);
2505 if (!channel->invite_list)
2506 channel->invite_list = silc_calloc(len + 2,
2507 sizeof(*channel->invite_list));
2509 channel->invite_list = silc_realloc(channel->invite_list,
2510 sizeof(*channel->invite_list) *
2512 strlen(channel->invite_list) + 2));
2513 strncat(channel->invite_list, invite, len);
2514 strncat(channel->invite_list, ",", 1);
2516 /* Send notify to the client that is invited to the channel */
2517 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2518 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2519 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2521 SILC_NOTIFY_TYPE_INVITE, 3,
2522 idp->data, idp->len,
2523 channel->channel_name,
2524 strlen(channel->channel_name),
2525 idp2->data, idp2->len);
2526 silc_buffer_free(idp);
2527 silc_buffer_free(idp2);
2530 /* Add the client to the invite list of the channel */
2531 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2533 if (!channel->invite_list)
2534 channel->invite_list = silc_calloc(len + 2,
2535 sizeof(*channel->invite_list));
2537 channel->invite_list = silc_realloc(channel->invite_list,
2538 sizeof(*channel->invite_list) *
2540 strlen(channel->invite_list) + 2));
2541 if (add[len - 1] == ',')
2542 add[len - 1] = '\0';
2544 strncat(channel->invite_list, add, len);
2545 strncat(channel->invite_list, ",", 1);
2548 /* Get the invite to be removed and remove it from the list */
2549 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2550 if (del && channel->invite_list) {
2551 char *start, *end, *n;
2553 if (!strncmp(channel->invite_list, del,
2554 strlen(channel->invite_list) - 1)) {
2555 silc_free(channel->invite_list);
2556 channel->invite_list = NULL;
2558 start = strstr(channel->invite_list, del);
2559 if (start && strlen(start) >= len) {
2561 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2562 strncat(n, channel->invite_list, start - channel->invite_list);
2563 strncat(n, end + 1, ((channel->invite_list +
2564 strlen(channel->invite_list)) - end) - 1);
2565 silc_free(channel->invite_list);
2566 channel->invite_list = n;
2571 /* Send notify to the primary router */
2572 if (!server->standalone)
2573 silc_server_send_notify_invite(server, server->router->connection,
2574 server->server_type == SILC_ROUTER ?
2575 TRUE : FALSE, channel,
2576 sender->id, add, del);
2578 /* Send command reply */
2579 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2583 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2584 SILC_STATUS_OK, ident, 2,
2586 3, channel->invite_list,
2587 channel->invite_list ?
2588 strlen(channel->invite_list) : 0);
2591 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2592 SILC_STATUS_OK, ident, 1,
2594 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2595 packet->data, packet->len, FALSE);
2596 silc_buffer_free(packet);
2600 silc_free(channel_id);
2601 silc_server_command_free(cmd);
2606 SilcSocketConnection sock;
2610 /* Quits connection to client. This gets called if client won't
2611 close the connection even when it has issued QUIT command. */
2613 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2615 QuitInternal q = (QuitInternal)context;
2617 /* Free all client specific data, such as client entry and entires
2618 on channels this client may be on. */
2619 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2621 q->sock->user_data = NULL;
2623 /* Close the connection on our side */
2624 silc_server_close_connection(q->server, q->sock);
2626 silc_free(q->signoff);
2630 /* Quits SILC session. This is the normal way to disconnect client. */
2632 SILC_SERVER_CMD_FUNC(quit)
2634 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2635 SilcServer server = cmd->server;
2636 SilcSocketConnection sock = cmd->sock;
2638 unsigned char *tmp = NULL;
2641 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2643 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2646 /* Get destination ID */
2647 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2651 q = silc_calloc(1, sizeof(*q));
2654 q->signoff = tmp ? strdup(tmp) : NULL;
2656 /* We quit the connection with little timeout */
2657 silc_schedule_task_add(server->schedule, sock->sock,
2658 silc_server_command_quit_cb, (void *)q,
2659 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2662 silc_server_command_free(cmd);
2665 /* Server side of command KILL. This command is used by router operator
2666 to remove an client from the SILC Network temporarily. */
2668 SILC_SERVER_CMD_FUNC(kill)
2670 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2671 SilcServer server = cmd->server;
2672 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2673 SilcClientEntry remote_client;
2674 SilcClientID *client_id;
2675 unsigned char *tmp, *comment;
2676 uint32 tmp_len, tmp_len2;
2678 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2680 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2683 /* KILL command works only on router */
2684 if (server->server_type != SILC_ROUTER) {
2685 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2686 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2690 /* Check whether client has the permissions. */
2691 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2692 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2693 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2697 /* Get the client ID */
2698 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2700 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2701 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2704 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2706 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2707 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2711 /* Get the client entry */
2712 remote_client = silc_idlist_find_client_by_id(server->local_list,
2713 client_id, TRUE, NULL);
2714 if (!remote_client) {
2715 remote_client = silc_idlist_find_client_by_id(server->global_list,
2716 client_id, TRUE, NULL);
2717 if (!remote_client) {
2718 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2719 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2725 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2729 /* Send reply to the sender */
2730 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2733 /* Send the KILL notify packets. First send it to the channel, then
2734 to our primary router and then directly to the client who is being
2735 killed right now. */
2737 /* Send KILLED notify to the channels. It is not sent to the client
2738 as it will be sent differently destined directly to the client and not
2740 silc_server_send_notify_on_channels(server, remote_client,
2741 remote_client, SILC_NOTIFY_TYPE_KILLED,
2744 comment, comment ? tmp_len2 : 0);
2746 /* Send KILLED notify to primary route */
2747 if (!server->standalone)
2748 silc_server_send_notify_killed(server, server->router->connection, TRUE,
2749 remote_client->id, comment);
2751 /* Send KILLED notify to the client directly */
2752 silc_server_send_notify_killed(server, remote_client->connection ?
2753 remote_client->connection :
2754 remote_client->router->connection, FALSE,
2755 remote_client->id, comment);
2757 /* Remove the client from all channels. This generates new keys to the
2758 channels as well. */
2759 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2762 /* Remove the client entry, If it is locally connected then we will also
2763 disconnect the client here */
2764 if (remote_client->connection) {
2765 /* Remove locally conneted client */
2766 SilcSocketConnection sock = remote_client->connection;
2767 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2768 silc_server_close_connection(server, sock);
2770 /* Remove remote client */
2771 if (!silc_idlist_del_client(server->global_list, remote_client))
2772 silc_idlist_del_client(server->local_list, remote_client);
2776 silc_server_command_free(cmd);
2779 /* Server side of command INFO. This sends information about us to
2780 the client. If client requested specific server we will send the
2781 command to that server. */
2783 SILC_SERVER_CMD_FUNC(info)
2785 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2786 SilcServer server = cmd->server;
2787 SilcBuffer packet, idp;
2790 char *dest_server, *server_info = NULL, *server_name;
2791 uint16 ident = silc_command_get_ident(cmd->payload);
2792 SilcServerEntry entry = NULL;
2793 SilcServerID *server_id = NULL;
2795 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2797 /* Get server name */
2798 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2801 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2803 server_id = silc_id_payload_parse_id(tmp, tmp_len);
2805 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2806 SILC_STATUS_ERR_NO_SERVER_ID);
2812 /* Check whether we have this server cached */
2813 entry = silc_idlist_find_server_by_id(server->local_list,
2814 server_id, TRUE, NULL);
2816 entry = silc_idlist_find_server_by_id(server->global_list,
2817 server_id, TRUE, NULL);
2818 if (!entry && server->server_type != SILC_SERVER) {
2819 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2820 SILC_STATUS_ERR_NO_SUCH_SERVER);
2826 /* Some buggy servers has sent request to router about themselves. */
2827 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2830 if ((!dest_server && !server_id && !entry) || (entry &&
2831 entry == server->id_entry) ||
2832 (dest_server && !cmd->pending &&
2833 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2834 /* Send our reply */
2835 char info_string[256];
2837 memset(info_string, 0, sizeof(info_string));
2838 snprintf(info_string, sizeof(info_string),
2839 "location: %s server: %s admin: %s <%s>",
2840 server->config->admin_info->location,
2841 server->config->admin_info->server_type,
2842 server->config->admin_info->admin_name,
2843 server->config->admin_info->admin_email);
2845 server_info = info_string;
2846 entry = server->id_entry;
2848 /* Check whether we have this server cached */
2849 if (!entry && dest_server) {
2850 entry = silc_idlist_find_server_by_name(server->global_list,
2851 dest_server, TRUE, NULL);
2853 entry = silc_idlist_find_server_by_name(server->local_list,
2854 dest_server, TRUE, NULL);
2858 if (!cmd->pending &&
2859 server->server_type != SILC_SERVER && entry && !entry->server_info) {
2860 /* Send to the server */
2864 old_ident = silc_command_get_ident(cmd->payload);
2865 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2866 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2868 silc_server_packet_send(server, entry->connection,
2869 SILC_PACKET_COMMAND, cmd->packet->flags,
2870 tmpbuf->data, tmpbuf->len, TRUE);
2872 /* Reprocess this packet after received reply from router */
2873 silc_server_command_pending(server, SILC_COMMAND_INFO,
2874 silc_command_get_ident(cmd->payload),
2875 silc_server_command_destructor,
2876 silc_server_command_info,
2877 silc_server_command_dup(cmd));
2878 cmd->pending = TRUE;
2879 silc_command_set_ident(cmd->payload, old_ident);
2880 silc_buffer_free(tmpbuf);
2884 if (!entry && !cmd->pending && !server->standalone) {
2885 /* Send to the primary router */
2889 old_ident = silc_command_get_ident(cmd->payload);
2890 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2891 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2893 silc_server_packet_send(server, server->router->connection,
2894 SILC_PACKET_COMMAND, cmd->packet->flags,
2895 tmpbuf->data, tmpbuf->len, TRUE);
2897 /* Reprocess this packet after received reply from router */
2898 silc_server_command_pending(server, SILC_COMMAND_INFO,
2899 silc_command_get_ident(cmd->payload),
2900 silc_server_command_destructor,
2901 silc_server_command_info,
2902 silc_server_command_dup(cmd));
2903 cmd->pending = TRUE;
2904 silc_command_set_ident(cmd->payload, old_ident);
2905 silc_buffer_free(tmpbuf);
2910 silc_free(server_id);
2913 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2914 SILC_STATUS_ERR_NO_SUCH_SERVER);
2918 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2920 server_info = entry->server_info;
2921 server_name = entry->server_name;
2923 /* Send the reply */
2925 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2926 SILC_STATUS_OK, ident, 3,
2927 2, idp->data, idp->len,
2929 strlen(server_name),
2931 strlen(server_info));
2933 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2934 SILC_STATUS_OK, ident, 2,
2935 2, idp->data, idp->len,
2937 strlen(server_name));
2938 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2939 packet->data, packet->len, FALSE);
2941 silc_buffer_free(packet);
2942 silc_buffer_free(idp);
2945 silc_server_command_free(cmd);
2948 /* Server side of command PING. This just replies to the ping. */
2950 SILC_SERVER_CMD_FUNC(ping)
2952 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2953 SilcServer server = cmd->server;
2958 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
2961 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2963 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2964 SILC_STATUS_ERR_NO_SERVER_ID);
2967 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2971 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2972 /* Send our reply */
2973 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2976 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2977 SILC_STATUS_ERR_NO_SUCH_SERVER);
2984 silc_server_command_free(cmd);
2987 /* Internal routine to join channel. The channel sent to this function
2988 has been either created or resolved from ID lists. This joins the sent
2989 client to the channel. */
2991 static void silc_server_command_join_channel(SilcServer server,
2992 SilcServerCommandContext cmd,
2993 SilcChannelEntry channel,
2994 SilcClientID *client_id,
2999 SilcSocketConnection sock = cmd->sock;
3001 uint32 tmp_len, user_count;
3002 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
3003 SilcClientEntry client;
3004 SilcChannelClientEntry chl;
3005 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
3006 uint16 ident = silc_command_get_ident(cmd->payload);
3007 char check[512], check2[512];
3009 SILC_LOG_DEBUG(("Start"));
3014 /* Get the client entry */
3015 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3016 client = (SilcClientEntry)sock->user_data;
3018 client = silc_server_get_client_resolve(server, client_id);
3023 /* The client info is being resolved. Reprocess this packet after
3024 receiving the reply to the query. */
3025 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
3026 server->cmd_ident, NULL,
3027 silc_server_command_join,
3028 silc_server_command_dup(cmd));
3029 cmd->pending = TRUE;
3033 cmd->pending = FALSE;
3037 * Check channel modes
3040 memset(check, 0, sizeof(check));
3041 memset(check2, 0, sizeof(check2));
3042 strncat(check, client->nickname, strlen(client->nickname));
3043 strncat(check, "!", 1);
3044 strncat(check, client->username, strlen(client->username));
3045 if (!strchr(client->username, '@')) {
3046 strncat(check, "@", 1);
3047 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3050 strncat(check2, client->nickname, strlen(client->nickname));
3051 if (!strchr(client->nickname, '@')) {
3052 strncat(check2, "@", 1);
3053 strncat(check2, server->server_name, strlen(server->server_name));
3055 strncat(check2, "!", 1);
3056 strncat(check2, client->username, strlen(client->username));
3057 if (!strchr(client->username, '@')) {
3058 strncat(check2, "@", 1);
3059 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3062 /* Check invite list if channel is invite-only channel */
3063 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3064 if (!channel->invite_list ||
3065 (!silc_string_match(channel->invite_list, check) &&
3066 !silc_string_match(channel->invite_list, check2))) {
3067 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3068 SILC_STATUS_ERR_NOT_INVITED);
3073 /* Check ban list if it exists. If the client's nickname, server,
3074 username and/or hostname is in the ban list the access to the
3075 channel is denied. */
3076 if (channel->ban_list) {
3077 if (!channel->ban_list ||
3078 silc_string_match(channel->ban_list, check) ||
3079 silc_string_match(channel->ban_list, check2)) {
3080 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3081 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
3086 /* Get passphrase */
3087 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3089 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
3090 memcpy(passphrase, tmp, tmp_len);
3093 /* Check the channel passphrase if set. */
3094 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3095 if (!passphrase || !channel->passphrase ||
3096 memcmp(channel->passphrase, passphrase,
3097 strlen(channel->passphrase))) {
3098 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3099 SILC_STATUS_ERR_BAD_PASSWORD);
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 * Client is allowed to join to the channel. Make it happen.
3118 /* Check whether the client already is on the channel */
3119 if (silc_server_client_on_channel(client, channel)) {
3120 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3121 SILC_STATUS_ERR_USER_ON_CHANNEL);
3125 /* Generate new channel key as protocol dictates */
3127 if (!silc_server_create_channel_key(server, channel, 0))
3130 /* Send the channel key. This is broadcasted to the channel but is not
3131 sent to the client who is joining to the channel. */
3132 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3133 silc_server_send_channel_key(server, NULL, channel,
3134 server->server_type == SILC_ROUTER ?
3135 FALSE : !server->standalone);
3138 /* Join the client to the channel by adding it to channel's user list.
3139 Add also the channel to client entry's channels list for fast cross-
3141 chl = silc_calloc(1, sizeof(*chl));
3143 chl->client = client;
3144 chl->channel = channel;
3145 silc_hash_table_add(channel->user_list, client, chl);
3146 silc_hash_table_add(client->channels, channel, chl);
3148 /* Get users on the channel */
3149 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3152 /* Encode Client ID Payload of the original client who wants to join */
3153 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3155 /* Encode command reply packet */
3156 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3157 SILC_PUT32_MSB(channel->mode, mode);
3158 SILC_PUT32_MSB(created, tmp2);
3159 SILC_PUT32_MSB(user_count, tmp3);
3161 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3162 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3163 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
3164 strlen(channel->channel_key->
3166 channel->channel_key->cipher->name,
3167 channel->key_len / 8, channel->key);
3172 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3173 SILC_STATUS_OK, ident, 13,
3174 2, channel->channel_name,
3175 strlen(channel->channel_name),
3176 3, chidp->data, chidp->len,
3177 4, clidp->data, clidp->len,
3180 7, keyp ? keyp->data : NULL,
3181 keyp ? keyp->len : 0,
3182 8, channel->ban_list,
3184 strlen(channel->ban_list) : 0,
3185 9, channel->invite_list,
3186 channel->invite_list ?
3187 strlen(channel->invite_list) : 0,
3190 strlen(channel->topic) : 0,
3191 11, silc_hmac_get_name(channel->hmac),
3192 strlen(silc_hmac_get_name(channel->
3195 13, user_list->data, user_list->len,
3196 14, mode_list->data,
3199 /* Send command reply */
3200 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3201 reply->data, reply->len, FALSE);
3203 /* Send JOIN notify to locally connected clients on the channel. If
3204 we are normal server then router will send or have sent JOIN notify
3205 already. However since we've added the client already to our channel
3206 we'll ignore it (in packet_receive.c) so we must send it here. If
3207 we are router then this will send it to local clients and local
3209 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3210 SILC_NOTIFY_TYPE_JOIN, 2,
3211 clidp->data, clidp->len,
3212 chidp->data, chidp->len);
3214 if (!cmd->pending) {
3215 /* Send JOIN notify packet to our primary router */
3216 if (!server->standalone)
3217 silc_server_send_notify_join(server, server->router->connection,
3218 server->server_type == SILC_ROUTER ?
3219 TRUE : FALSE, channel, client->id);
3222 /* Distribute the channel key to all backup routers. */
3223 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3224 keyp->data, keyp->len, FALSE, TRUE);
3227 silc_buffer_free(reply);
3228 silc_buffer_free(clidp);
3229 silc_buffer_free(chidp);
3230 silc_buffer_free(keyp);
3231 silc_buffer_free(user_list);
3232 silc_buffer_free(mode_list);
3235 silc_free(passphrase);
3238 /* Server side of command JOIN. Joins client into requested channel. If
3239 the channel does not exist it will be created. */
3241 SILC_SERVER_CMD_FUNC(join)
3243 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3244 SilcServer server = cmd->server;
3246 char *tmp, *channel_name = NULL, *cipher, *hmac;
3247 SilcChannelEntry channel;
3249 bool created = FALSE, create_key = TRUE;
3250 SilcClientID *client_id;
3252 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 1, 4);
3254 /* Get channel name */
3255 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3257 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3258 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3263 if (strlen(channel_name) > 256)
3264 channel_name[255] = '\0';
3266 if (silc_server_command_bad_chars(channel_name) == TRUE) {
3267 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3268 SILC_STATUS_ERR_BAD_CHANNEL);
3272 /* Get Client ID of the client who is joining to the channel */
3273 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3275 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3276 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3279 client_id = silc_id_payload_parse_id(tmp, tmp_len);
3281 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3282 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3286 /* Get cipher and hmac name */
3287 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3288 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3290 /* See if the channel exists */
3291 channel = silc_idlist_find_channel_by_name(server->local_list,
3292 channel_name, NULL);
3294 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3295 /* If this is coming from client the Client ID in the command packet must
3296 be same as the client's ID. */
3297 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3298 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3299 if (!SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
3300 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3301 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3306 if (!channel || channel->disabled) {
3307 /* Channel not found */
3309 /* If we are standalone server we don't have a router, we just create
3310 the channel by ourselves. */
3311 if (server->standalone) {
3312 channel = silc_server_create_new_channel(server, server->id, cipher,
3313 hmac, channel_name, TRUE);
3315 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3316 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3320 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3326 /* The channel does not exist on our server. If we are normal server
3327 we will send JOIN command to our router which will handle the
3328 joining procedure (either creates the channel if it doesn't exist
3329 or joins the client to it). */
3330 if (server->server_type != SILC_ROUTER) {
3334 /* If this is pending command callback then we've resolved
3335 it and it didn't work, return since we've notified the
3336 client already in the command reply callback. */
3340 old_ident = silc_command_get_ident(cmd->payload);
3341 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3342 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3344 /* Send JOIN command to our router */
3345 silc_server_packet_send(server, (SilcSocketConnection)
3346 server->router->connection,
3347 SILC_PACKET_COMMAND, cmd->packet->flags,
3348 tmpbuf->data, tmpbuf->len, TRUE);
3350 /* Reprocess this packet after received reply from router */
3351 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3352 silc_command_get_ident(cmd->payload),
3353 silc_server_command_destructor,
3354 silc_server_command_join,
3355 silc_server_command_dup(cmd));
3356 cmd->pending = TRUE;
3360 /* We are router and the channel does not seem exist so we will check
3361 our global list as well for the channel. */
3362 channel = silc_idlist_find_channel_by_name(server->global_list,
3363 channel_name, NULL);
3365 /* Channel really does not exist, create it */
3366 channel = silc_server_create_new_channel(server, server->id, cipher,
3367 hmac, channel_name, TRUE);
3369 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3370 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3374 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3382 /* Channel not found */
3384 /* If the command came from router and we are normal server then
3385 something went wrong with the joining as the channel was not found.
3386 We can't do anything else but ignore this. */
3387 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3388 server->server_type != SILC_ROUTER)
3391 /* We are router and the channel does not seem exist so we will check
3392 our global list as well for the channel. */
3393 channel = silc_idlist_find_channel_by_name(server->global_list,
3394 channel_name, NULL);
3396 /* Channel really does not exist, create it */
3397 channel = silc_server_create_new_channel(server, server->id, cipher,
3398 hmac, channel_name, TRUE);
3400 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3401 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3405 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3412 /* Check whether the channel was created by our router */
3413 if (cmd->pending && context2) {
3414 SilcServerCommandReplyContext reply =
3415 (SilcServerCommandReplyContext)context2;
3416 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3417 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3418 SILC_GET32_MSB(created, tmp);
3419 create_key = FALSE; /* Router returned the key already */
3423 /* If the channel does not have global users and is also empty the client
3424 will be the channel founder and operator. */
3425 if (!channel->global_users && !silc_hash_table_count(channel->user_list))
3426 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3428 /* Join to the channel */
3429 silc_server_command_join_channel(server, cmd, channel, client_id,
3430 created, create_key, umode);
3432 silc_free(client_id);
3435 silc_server_command_free(cmd);
3438 /* Server side of command MOTD. Sends server's current "message of the
3439 day" to the client. */
3441 SILC_SERVER_CMD_FUNC(motd)
3443 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3444 SilcServer server = cmd->server;
3445 SilcBuffer packet, idp;
3446 char *motd, *dest_server;
3448 uint16 ident = silc_command_get_ident(cmd->payload);
3450 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3452 /* Get server name */
3453 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3455 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3456 SILC_STATUS_ERR_NO_SUCH_SERVER);
3460 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3463 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3465 if (server->config && server->config->motd &&
3466 server->config->motd->motd_file) {
3468 motd = silc_file_readfile(server->config->motd->motd_file, &motd_len);
3473 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3474 SILC_STATUS_OK, ident, 2,
3479 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3480 SILC_STATUS_OK, ident, 1,
3484 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3485 packet->data, packet->len, FALSE);
3486 silc_buffer_free(packet);
3487 silc_buffer_free(idp);
3489 SilcServerEntry entry;
3491 /* Check whether we have this server cached */
3492 entry = silc_idlist_find_server_by_name(server->global_list,
3493 dest_server, TRUE, NULL);
3495 entry = silc_idlist_find_server_by_name(server->local_list,
3496 dest_server, TRUE, NULL);
3499 if (server->server_type != SILC_SERVER && !cmd->pending &&
3500 entry && !entry->motd) {
3501 /* Send to the server */
3505 old_ident = silc_command_get_ident(cmd->payload);
3506 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3507 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3509 silc_server_packet_send(server, entry->connection,
3510 SILC_PACKET_COMMAND, cmd->packet->flags,
3511 tmpbuf->data, tmpbuf->len, TRUE);
3513 /* Reprocess this packet after received reply from router */
3514 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3515 silc_command_get_ident(cmd->payload),
3516 silc_server_command_destructor,
3517 silc_server_command_motd,
3518 silc_server_command_dup(cmd));
3519 cmd->pending = TRUE;
3520 silc_command_set_ident(cmd->payload, old_ident);
3521 silc_buffer_free(tmpbuf);
3525 if (!entry && !cmd->pending && !server->standalone) {
3526 /* Send to the primary router */
3530 old_ident = silc_command_get_ident(cmd->payload);
3531 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3532 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3534 silc_server_packet_send(server, server->router->connection,
3535 SILC_PACKET_COMMAND, cmd->packet->flags,
3536 tmpbuf->data, tmpbuf->len, TRUE);
3538 /* Reprocess this packet after received reply from router */
3539 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3540 silc_command_get_ident(cmd->payload),
3541 silc_server_command_destructor,
3542 silc_server_command_motd,
3543 silc_server_command_dup(cmd));
3544 cmd->pending = TRUE;
3545 silc_command_set_ident(cmd->payload, old_ident);
3546 silc_buffer_free(tmpbuf);
3551 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3552 SILC_STATUS_ERR_NO_SUCH_SERVER);
3556 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3559 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3560 SILC_STATUS_OK, ident, 2,
3563 strlen(entry->motd));
3565 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3566 SILC_STATUS_OK, ident, 1,
3569 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3570 packet->data, packet->len, FALSE);
3571 silc_buffer_free(packet);
3572 silc_buffer_free(idp);
3576 silc_server_command_free(cmd);
3579 /* Server side of command UMODE. Client can use this command to set/unset
3580 user mode. Client actually cannot set itself to be as server/router
3581 operator so this can be used only to unset the modes. */
3583 SILC_SERVER_CMD_FUNC(umode)
3585 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3586 SilcServer server = cmd->server;
3587 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3589 unsigned char *tmp_mask;
3591 uint16 ident = silc_command_get_ident(cmd->payload);
3593 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3596 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 2, 2);
3598 /* Get the client's mode mask */
3599 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3601 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3602 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3605 SILC_GET32_MSB(mask, tmp_mask);
3611 if (mask & SILC_UMODE_SERVER_OPERATOR) {
3612 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR)) {
3613 /* Cannot operator mode */
3614 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3615 SILC_STATUS_ERR_PERM_DENIED);
3619 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
3620 /* Remove the server operator rights */
3621 client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3624 if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3625 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
3626 /* Cannot operator mode */
3627 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3628 SILC_STATUS_ERR_PERM_DENIED);
3632 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
3633 /* Remove the router operator rights */
3634 client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3637 if (mask & SILC_UMODE_GONE) {
3638 client->mode |= SILC_UMODE_GONE;
3640 if (client->mode & SILC_UMODE_GONE)
3641 /* Remove the gone status */
3642 client->mode &= ~SILC_UMODE_GONE;
3645 /* Send UMODE change to primary router */
3646 if (!server->standalone)
3647 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3648 client->id, client->mode);
3650 /* Send command reply to sender */
3651 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3652 SILC_STATUS_OK, ident, 1,
3654 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3655 packet->data, packet->len, FALSE);
3656 silc_buffer_free(packet);
3659 silc_server_command_free(cmd);
3662 /* Checks that client has rights to add or remove channel modes. If any
3663 of the checks fails FALSE is returned. */
3665 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3666 SilcChannelClientEntry client,
3669 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3670 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3672 /* Check whether has rights to change anything */
3673 if (!is_op && !is_fo)
3676 /* Check whether has rights to change everything */
3680 /* We know that client is channel operator, check that they are not
3681 changing anything that requires channel founder rights. Rest of the
3682 modes are available automatically for channel operator. */
3684 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3685 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3686 if (is_op && !is_fo)
3689 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3690 if (is_op && !is_fo)
3695 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3696 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE))
3697 if (is_op && !is_fo)
3700 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3701 if (is_op && !is_fo)
3706 if (mode & SILC_CHANNEL_MODE_CIPHER) {
3707 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER))
3708 if (is_op && !is_fo)
3711 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3712 if (is_op && !is_fo)
3717 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3718 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH))
3719 if (is_op && !is_fo)
3722 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3723 if (is_op && !is_fo)
3731 /* Server side command of CMODE. Changes channel mode */
3733 SILC_SERVER_CMD_FUNC(cmode)
3735 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3736 SilcServer server = cmd->server;
3737 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3738 SilcIDListData idata = (SilcIDListData)client;
3739 SilcChannelID *channel_id;
3740 SilcChannelEntry channel;
3741 SilcChannelClientEntry chl;
3742 SilcBuffer packet, cidp;
3743 unsigned char *tmp, *tmp_id, *tmp_mask;
3744 char *cipher = NULL, *hmac = NULL;
3745 uint32 mode_mask, tmp_len, tmp_len2;
3746 uint16 ident = silc_command_get_ident(cmd->payload);
3748 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 2, 7);
3750 /* Get Channel ID */
3751 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3753 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3754 SILC_STATUS_ERR_NO_CHANNEL_ID);
3757 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3759 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3760 SILC_STATUS_ERR_NO_CHANNEL_ID);
3764 /* Get the channel mode mask */
3765 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3767 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3768 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3771 SILC_GET32_MSB(mode_mask, tmp_mask);
3773 /* Get channel entry */
3774 channel = silc_idlist_find_channel_by_id(server->local_list,
3777 channel = silc_idlist_find_channel_by_id(server->global_list,
3780 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3781 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3786 /* Check whether this client is on the channel */
3787 if (!silc_server_client_on_channel(client, channel)) {
3788 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3789 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3793 /* Get entry to the channel user list */
3794 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
3796 /* Check that client has rights to change any requested channel modes */
3797 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3798 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3799 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3804 * Check the modes. Modes that requires nothing special operation are
3808 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3809 /* Channel uses private keys to protect traffic. Client(s) has set the
3810 key locally they want to use, server does not know that key. */
3811 /* Nothing interesting to do here */
3813 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3814 /* The mode is removed and we need to generate and distribute
3815 new channel key. Clients are not using private channel keys
3816 anymore after this. */
3818 /* Re-generate channel key */
3819 if (!silc_server_create_channel_key(server, channel, 0))
3822 /* Send the channel key. This sends it to our local clients and if
3823 we are normal server to our router as well. */
3824 silc_server_send_channel_key(server, NULL, channel,
3825 server->server_type == SILC_ROUTER ?
3826 FALSE : !server->standalone);
3828 cipher = channel->channel_key->cipher->name;
3829 hmac = (char *)silc_hmac_get_name(channel->hmac);
3833 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3834 /* User limit is set on channel */
3837 /* Get user limit */
3838 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3840 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3841 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3842 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3846 SILC_GET32_MSB(user_limit, tmp);
3847 channel->user_limit = user_limit;
3850 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3851 /* User limit mode is unset. Remove user limit */
3852 channel->user_limit = 0;
3855 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3856 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3857 /* Passphrase has been set to channel */
3859 /* Get the passphrase */
3860 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3862 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3863 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3867 /* Save the passphrase */
3868 channel->passphrase = strdup(tmp);
3871 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3872 /* Passphrase mode is unset. remove the passphrase */
3873 if (channel->passphrase) {
3874 silc_free(channel->passphrase);
3875 channel->passphrase = NULL;
3880 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3881 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3882 /* Cipher to use protect the traffic */
3883 SilcCipher newkey, oldkey;
3886 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3888 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3889 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3893 /* Delete old cipher and allocate the new one */
3894 if (!silc_cipher_alloc(cipher, &newkey)) {
3895 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3896 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3900 oldkey = channel->channel_key;
3901 channel->channel_key = newkey;
3903 /* Re-generate channel key */
3904 if (!silc_server_create_channel_key(server, channel, 0)) {
3905 /* We don't have new key, revert to old one */
3906 channel->channel_key = oldkey;
3910 /* Remove old channel key for good */
3911 silc_cipher_free(oldkey);
3913 /* Send the channel key. This sends it to our local clients and if
3914 we are normal server to our router as well. */
3915 silc_server_send_channel_key(server, NULL, channel,
3916 server->server_type == SILC_ROUTER ?
3917 FALSE : !server->standalone);
3920 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3921 /* Cipher mode is unset. Remove the cipher and revert back to
3923 SilcCipher newkey, oldkey;
3924 cipher = channel->cipher;
3926 /* Delete old cipher and allocate default one */
3927 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
3928 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3929 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3933 oldkey = channel->channel_key;
3934 channel->channel_key = newkey;
3936 /* Re-generate channel key */
3937 if (!silc_server_create_channel_key(server, channel, 0)) {
3938 /* We don't have new key, revert to old one */
3939 channel->channel_key = oldkey;
3943 /* Remove old channel key for good */
3944 silc_cipher_free(oldkey);
3946 /* Send the channel key. This sends it to our local clients and if
3947 we are normal server to our router as well. */
3948 silc_server_send_channel_key(server, NULL, channel,
3949 server->server_type == SILC_ROUTER ?
3950 FALSE : !server->standalone);
3954 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3955 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3956 /* HMAC to use protect the traffic */
3957 unsigned char hash[32];
3961 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3963 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3964 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3968 /* Delete old hmac and allocate the new one */
3969 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
3970 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3971 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3975 silc_hmac_free(channel->hmac);
3976 channel->hmac = newhmac;
3978 /* Set the HMAC key out of current channel key. The client must do
3980 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
3981 channel->key_len / 8, hash);
3982 silc_hmac_set_key(channel->hmac, hash,
3983 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3984 memset(hash, 0, sizeof(hash));
3987 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
3988 /* Hmac mode is unset. Remove the hmac and revert back to
3991 unsigned char hash[32];
3992 hmac = channel->hmac_name;
3994 /* Delete old hmac and allocate default one */
3995 silc_hmac_free(channel->hmac);
3996 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
3997 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3998 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4002 silc_hmac_free(channel->hmac);
4003 channel->hmac = newhmac;
4005 /* Set the HMAC key out of current channel key. The client must do
4007 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4008 channel->key_len / 8,
4010 silc_hmac_set_key(channel->hmac, hash,
4011 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4012 memset(hash, 0, sizeof(hash));
4016 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4017 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4018 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4019 /* Set the founder authentication */
4020 SilcAuthPayload auth;
4022 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4024 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4025 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4029 auth = silc_auth_payload_parse(tmp, tmp_len);
4031 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4032 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4036 /* Save the public key */
4037 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
4038 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
4041 channel->founder_method = silc_auth_get_method(auth);
4043 if (channel->founder_method == SILC_AUTH_PASSWORD) {
4044 tmp = silc_auth_get_data(auth, &tmp_len);
4045 channel->founder_passwd =
4046 silc_calloc(tmp_len + 1, sizeof(*channel->founder_passwd));
4047 memcpy(channel->founder_passwd, tmp, tmp_len);
4048 channel->founder_passwd_len = tmp_len;
4050 /* Verify the payload before setting the mode */
4051 if (!silc_auth_verify(auth, channel->founder_method,
4052 channel->founder_key, 0, idata->hash,
4053 client->id, SILC_ID_CLIENT)) {
4054 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4055 SILC_STATUS_ERR_AUTH_FAILED);
4060 silc_auth_payload_free(auth);
4064 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4065 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4066 if (channel->founder_key)
4067 silc_pkcs_public_key_free(channel->founder_key);
4068 if (channel->founder_passwd) {
4069 silc_free(channel->founder_passwd);
4070 channel->founder_passwd = NULL;
4076 /* Finally, set the mode */
4077 channel->mode = mode_mask;
4079 /* Send CMODE_CHANGE notify */
4080 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4081 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4082 SILC_NOTIFY_TYPE_CMODE_CHANGE, 4,
4083 cidp->data, cidp->len,
4085 cipher, cipher ? strlen(cipher) : 0,
4086 hmac, hmac ? strlen(hmac) : 0);
4088 /* Set CMODE notify type to network */
4089 if (!server->standalone)
4090 silc_server_send_notify_cmode(server, server->router->connection,
4091 server->server_type == SILC_ROUTER ?
4092 TRUE : FALSE, channel,
4093 mode_mask, client->id, SILC_ID_CLIENT,
4096 /* Send command reply to sender */
4097 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4098 SILC_STATUS_OK, ident, 2,
4099 2, tmp_id, tmp_len2,
4101 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4102 packet->data, packet->len, FALSE);
4104 silc_buffer_free(packet);
4105 silc_free(channel_id);
4109 silc_server_command_free(cmd);
4112 /* Server side of CUMODE command. Changes client's mode on a channel. */
4114 SILC_SERVER_CMD_FUNC(cumode)
4116 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4117 SilcServer server = cmd->server;
4118 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4119 SilcIDListData idata = (SilcIDListData)client;
4120 SilcChannelID *channel_id;
4121 SilcClientID *client_id;
4122 SilcChannelEntry channel;
4123 SilcClientEntry target_client;
4124 SilcChannelClientEntry chl;
4125 SilcBuffer packet, idp;
4126 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4127 uint32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4129 uint16 ident = silc_command_get_ident(cmd->payload);
4131 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4133 /* Get Channel ID */
4134 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4136 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4137 SILC_STATUS_ERR_NO_CHANNEL_ID);
4140 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
4142 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4143 SILC_STATUS_ERR_NO_CHANNEL_ID);
4147 /* Get channel entry */
4148 channel = silc_idlist_find_channel_by_id(server->local_list,
4151 channel = silc_idlist_find_channel_by_id(server->global_list,
4154 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4155 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4160 /* Check whether sender is on the channel */
4161 if (!silc_server_client_on_channel(client, channel)) {
4162 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4163 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4167 /* Check that client has rights to change other's rights */
4168 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4169 sender_mask = chl->mode;
4171 /* Get the target client's channel mode mask */
4172 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4174 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4175 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4178 SILC_GET32_MSB(target_mask, tmp_mask);
4180 /* Get target Client ID */
4181 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4183 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4184 SILC_STATUS_ERR_NO_CLIENT_ID);
4187 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
4189 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4190 SILC_STATUS_ERR_NO_CLIENT_ID);
4194 /* Get target client's entry */
4195 target_client = silc_idlist_find_client_by_id(server->local_list,
4196 client_id, TRUE, NULL);
4197 if (!target_client) {
4198 target_client = silc_idlist_find_client_by_id(server->global_list,
4199 client_id, TRUE, NULL);
4202 if (target_client != client &&
4203 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4204 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4205 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4206 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4210 /* Check whether target client is on the channel */
4211 if (target_client != client) {
4212 if (!silc_server_client_on_channel(target_client, channel)) {
4213 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4214 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4218 /* Get entry to the channel user list */
4219 silc_hash_table_find(channel->user_list, target_client, NULL,
4227 /* If the target client is founder, no one else can change their mode
4229 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
4230 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4231 SILC_STATUS_ERR_NOT_YOU);
4235 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4236 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4237 /* The client tries to claim the founder rights. */
4238 unsigned char *tmp_auth;
4239 uint32 tmp_auth_len, auth_len;
4242 if (target_client != client) {
4243 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4244 SILC_STATUS_ERR_NOT_YOU);
4248 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4249 !channel->founder_key || !idata->public_key ||
4250 !silc_pkcs_public_key_compare(channel->founder_key,
4251 idata->public_key)) {
4252 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4253 SILC_STATUS_ERR_NOT_YOU);
4257 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4259 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4260 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4264 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4265 (void *)channel->founder_passwd : (void *)channel->founder_key);
4266 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4267 channel->founder_passwd_len : 0);
4269 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4270 channel->founder_method, auth, auth_len,
4271 idata->hash, client->id, SILC_ID_CLIENT)) {
4272 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4273 SILC_STATUS_ERR_AUTH_FAILED);
4277 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4281 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4282 if (target_client == client) {
4283 /* Remove channel founder rights from itself */
4284 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4287 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4288 SILC_STATUS_ERR_NOT_YOU);
4294 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4295 /* Promote to operator */
4296 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4297 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4298 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4299 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4300 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4304 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4308 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4309 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4310 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4311 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4312 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4316 /* Demote to normal user */
4317 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4322 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4323 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4325 /* Send notify to channel, notify only if mode was actually changed. */
4327 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4328 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4329 idp->data, idp->len,
4333 /* Set CUMODE notify type to network */
4334 if (!server->standalone)
4335 silc_server_send_notify_cumode(server, server->router->connection,
4336 server->server_type == SILC_ROUTER ?
4337 TRUE : FALSE, channel,
4338 target_mask, client->id,
4343 /* Send command reply to sender */
4344 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4345 SILC_STATUS_OK, ident, 3,
4347 3, tmp_ch_id, tmp_ch_len,
4348 4, tmp_id, tmp_len);
4349 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4350 packet->data, packet->len, FALSE);
4352 silc_buffer_free(packet);
4353 silc_free(channel_id);
4354 silc_free(client_id);
4355 silc_buffer_free(idp);
4358 silc_server_command_free(cmd);
4361 /* Server side of KICK command. Kicks client out of channel. */
4363 SILC_SERVER_CMD_FUNC(kick)
4365 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4366 SilcServer server = cmd->server;
4367 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4368 SilcClientEntry target_client;
4369 SilcChannelID *channel_id;
4370 SilcClientID *client_id;
4371 SilcChannelEntry channel;
4372 SilcChannelClientEntry chl;
4375 unsigned char *tmp, *comment;
4377 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4379 /* Get Channel ID */
4380 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4382 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4383 SILC_STATUS_ERR_NO_CHANNEL_ID);
4386 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
4388 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4389 SILC_STATUS_ERR_NO_CHANNEL_ID);
4393 /* Get channel entry */
4394 channel = silc_idlist_find_channel_by_id(server->local_list,
4397 channel = silc_idlist_find_channel_by_id(server->local_list,
4400 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4401 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4406 /* Check whether sender is on the channel */
4407 if (!silc_server_client_on_channel(client, channel)) {
4408 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4409 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4413 /* Check that the kicker is channel operator or channel founder */
4414 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4415 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4416 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4417 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4421 /* Get target Client ID */
4422 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4424 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4425 SILC_STATUS_ERR_NO_CLIENT_ID);
4428 client_id = silc_id_payload_parse_id(tmp, tmp_len);
4430 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4431 SILC_STATUS_ERR_NO_CLIENT_ID);
4435 /* Get target client's entry */
4436 target_client = silc_idlist_find_client_by_id(server->local_list,
4437 client_id, TRUE, NULL);
4438 if (!target_client) {
4439 target_client = silc_idlist_find_client_by_id(server->global_list,
4440 client_id, TRUE, NULL);
4443 /* Check that the target client is not channel founder. Channel founder
4444 cannot be kicked from the channel. */
4445 silc_hash_table_find(channel->user_list, target_client, NULL, (void *)&chl);
4446 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4447 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4448 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4452 /* Check whether target client is on the channel */
4453 if (!silc_server_client_on_channel(target_client, channel)) {
4454 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4455 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4461 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4465 /* Send command reply to sender */
4466 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4469 /* Send KICKED notify to local clients on the channel */
4470 idp = silc_id_payload_encode(target_client->id, SILC_ID_CLIENT);
4471 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4472 SILC_NOTIFY_TYPE_KICKED,
4474 idp->data, idp->len,
4475 comment, comment ? strlen(comment) : 0);
4476 silc_buffer_free(idp);
4478 /* Remove the client from the channel. If the channel does not exist
4479 after removing the client then the client kicked itself off the channel
4480 and we don't have to send anything after that. */
4481 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4482 target_client, FALSE))
4485 /* Send KICKED notify to primary route */
4486 if (!server->standalone)
4487 silc_server_send_notify_kicked(server, server->router->connection,
4488 server->server_type == SILC_ROUTER ?
4489 TRUE : FALSE, channel,
4490 target_client->id, comment);
4492 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4493 /* Re-generate channel key */
4494 if (!silc_server_create_channel_key(server, channel, 0))
4497 /* Send the channel key to the channel. The key of course is not sent
4498 to the client who was kicked off the channel. */
4499 silc_server_send_channel_key(server, target_client->connection, channel,
4500 server->server_type == SILC_ROUTER ?
4501 FALSE : !server->standalone);
4505 silc_server_command_free(cmd);
4508 /* Server side of OPER command. Client uses this comand to obtain server
4509 operator privileges to this server/router. */
4511 SILC_SERVER_CMD_FUNC(oper)
4513 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4514 SilcServer server = cmd->server;
4515 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4516 unsigned char *username, *auth;
4518 SilcServerConfigSectionAdminConnection *admin;
4519 SilcIDListData idata = (SilcIDListData)client;
4521 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4523 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4526 /* Get the username */
4527 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4529 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4530 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4534 /* Get the admin configuration */
4535 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4536 username, client->nickname);
4538 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4539 username, client->nickname);
4541 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4542 SILC_STATUS_ERR_AUTH_FAILED);
4547 /* Get the authentication payload */
4548 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4550 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4551 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4555 /* Verify the authentication data */
4556 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4557 admin->auth_data, admin->auth_data_len,
4558 idata->hash, client->id, SILC_ID_CLIENT)) {
4559 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4560 SILC_STATUS_ERR_AUTH_FAILED);
4564 /* Client is now server operator */
4565 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4567 /* Send UMODE change to primary router */
4568 if (!server->standalone)
4569 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4570 client->id, client->mode);
4572 /* Send reply to the sender */
4573 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4577 silc_server_command_free(cmd);
4580 /* Server side of SILCOPER command. Client uses this comand to obtain router
4581 operator privileges to this router. */
4583 SILC_SERVER_CMD_FUNC(silcoper)
4585 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4586 SilcServer server = cmd->server;
4587 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4588 unsigned char *username, *auth;
4590 SilcServerConfigSectionAdminConnection *admin;
4591 SilcIDListData idata = (SilcIDListData)client;
4593 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4595 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4598 if (server->server_type != SILC_ROUTER) {
4599 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4600 SILC_STATUS_ERR_AUTH_FAILED);
4604 /* Get the username */
4605 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4607 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4608 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4612 /* Get the admin configuration */
4613 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4614 username, client->nickname);
4616 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4617 username, client->nickname);
4619 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4620 SILC_STATUS_ERR_AUTH_FAILED);
4625 /* Get the authentication payload */
4626 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4628 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4629 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4633 /* Verify the authentication data */
4634 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4635 admin->auth_data, admin->auth_data_len,
4636 idata->hash, client->id, SILC_ID_CLIENT)) {
4637 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4638 SILC_STATUS_ERR_AUTH_FAILED);
4642 /* Client is now router operator */
4643 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4645 /* Send UMODE change to primary router */
4646 if (!server->standalone)
4647 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4648 client->id, client->mode);
4650 /* Send reply to the sender */
4651 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4655 silc_server_command_free(cmd);
4658 /* Server side command of CONNECT. Connects us to the specified remote
4659 server or router. */
4661 SILC_SERVER_CMD_FUNC(connect)
4663 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4664 SilcServer server = cmd->server;
4665 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4666 unsigned char *tmp, *host;
4668 uint32 port = SILC_PORT;
4670 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CONNECT, cmd, 1, 2);
4672 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4675 /* Check whether client has the permissions. */
4676 if (client->mode == SILC_UMODE_NONE) {
4677 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4678 SILC_STATUS_ERR_NO_SERVER_PRIV);
4682 if (server->server_type == SILC_ROUTER &&
4683 client->mode & SILC_UMODE_SERVER_OPERATOR) {
4684 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4685 SILC_STATUS_ERR_NO_ROUTER_PRIV);
4689 /* Get the remote server */
4690 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4692 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4693 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4698 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4700 SILC_GET32_MSB(port, tmp);
4702 /* Create the connection. It is done with timeout and is async. */
4703 silc_server_create_connection(server, host, port);
4705 /* Send reply to the sender */
4706 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4710 silc_server_command_free(cmd);
4713 /* Server side of command BAN. This is used to manage the ban list of the
4714 channel. To add clients and remove clients from the ban list. */
4716 SILC_SERVER_CMD_FUNC(ban)
4718 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4719 SilcServer server = cmd->server;
4720 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4722 SilcChannelEntry channel;
4723 SilcChannelClientEntry chl;
4724 SilcChannelID *channel_id = NULL;
4725 unsigned char *id, *add, *del;
4726 uint32 id_len, tmp_len;
4727 uint16 ident = silc_command_get_ident(cmd->payload);
4729 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4732 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4734 /* Get Channel ID */
4735 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4737 channel_id = silc_id_payload_parse_id(id, id_len);
4739 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4740 SILC_STATUS_ERR_NO_CHANNEL_ID);
4745 /* Get channel entry. The server must know about the channel since the
4746 client is expected to be on the channel. */
4747 channel = silc_idlist_find_channel_by_id(server->local_list,
4750 channel = silc_idlist_find_channel_by_id(server->global_list,
4753 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4754 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4759 /* Check whether this client is on the channel */
4760 if (!silc_server_client_on_channel(client, channel)) {
4761 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4762 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4766 /* Get entry to the channel user list */
4767 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4769 /* The client must be at least channel operator. */
4770 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4771 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4772 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4776 /* Get the new ban and add it to the ban list */
4777 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4779 if (!channel->ban_list)
4780 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4782 channel->ban_list = silc_realloc(channel->ban_list,
4783 sizeof(*channel->ban_list) *
4785 strlen(channel->ban_list) + 2));
4786 if (add[tmp_len - 1] == ',')
4787 add[tmp_len - 1] = '\0';
4789 strncat(channel->ban_list, add, tmp_len);
4790 strncat(channel->ban_list, ",", 1);
4793 /* Get the ban to be removed and remove it from the list */
4794 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4795 if (del && channel->ban_list) {
4796 char *start, *end, *n;
4798 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4799 silc_free(channel->ban_list);
4800 channel->ban_list = NULL;
4802 start = strstr(channel->ban_list, del);
4803 if (start && strlen(start) >= tmp_len) {
4804 end = start + tmp_len;
4805 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4806 strncat(n, channel->ban_list, start - channel->ban_list);
4807 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4809 silc_free(channel->ban_list);
4810 channel->ban_list = n;
4815 /* Send the BAN notify type to our primary router. */
4816 if (!server->standalone && (add || del))
4817 silc_server_send_notify_ban(server, server->router->connection,
4818 server->server_type == SILC_ROUTER ?
4819 TRUE : FALSE, channel, add, del);
4821 /* Send the reply back to the client */
4822 if (channel->ban_list)
4824 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4825 SILC_STATUS_OK, ident, 2,
4827 3, channel->ban_list,
4828 strlen(channel->ban_list) - 1);
4831 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4832 SILC_STATUS_OK, ident, 1,
4835 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4836 packet->data, packet->len, FALSE);
4838 silc_buffer_free(packet);
4841 silc_free(channel_id);
4842 silc_server_command_free(cmd);
4845 /* Server side command of CLOSE. Closes connection to a specified server. */
4847 SILC_SERVER_CMD_FUNC(close)
4849 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4850 SilcServer server = cmd->server;
4851 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4852 SilcServerEntry server_entry;
4853 SilcSocketConnection sock;
4856 unsigned char *name;
4857 uint32 port = SILC_PORT;
4859 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CLOSE, cmd, 1, 2);
4861 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4864 /* Check whether client has the permissions. */
4865 if (client->mode == SILC_UMODE_NONE) {
4866 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4867 SILC_STATUS_ERR_NO_SERVER_PRIV);
4871 /* Get the remote server */
4872 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4874 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4875 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4880 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4882 SILC_GET32_MSB(port, tmp);
4884 server_entry = silc_idlist_find_server_by_conn(server->local_list,
4885 name, port, FALSE, NULL);
4887 server_entry = silc_idlist_find_server_by_conn(server->global_list,
4888 name, port, FALSE, NULL);
4889 if (!server_entry) {
4890 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4891 SILC_STATUS_ERR_NO_SERVER_ID);
4895 /* Send reply to the sender */
4896 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4899 /* Close the connection to the server */
4900 sock = (SilcSocketConnection)server_entry->connection;
4902 /* If we shutdown primary router connection manually then don't trigger
4903 any reconnect or backup router connections, by setting the router
4905 if (server->router == server_entry) {
4906 server->id_entry->router = NULL;
4907 server->router = NULL;
4908 server->standalone = TRUE;
4910 silc_server_free_sock_user_data(server, sock);
4911 silc_server_close_connection(server, sock);
4914 silc_server_command_free(cmd);
4917 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4918 active connections. */
4920 SILC_SERVER_CMD_FUNC(shutdown)
4922 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4923 SilcServer server = cmd->server;
4924 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4926 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4928 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4931 /* Check whether client has the permission. */
4932 if (client->mode == SILC_UMODE_NONE) {
4933 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4934 SILC_STATUS_ERR_NO_SERVER_PRIV);
4938 /* Send reply to the sender */
4939 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4942 /* Then, gracefully, or not, bring the server down. */
4943 silc_server_stop(server);
4947 silc_server_command_free(cmd);
4950 /* Server side command of LEAVE. Removes client from a channel. */
4952 SILC_SERVER_CMD_FUNC(leave)
4954 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4955 SilcServer server = cmd->server;
4956 SilcSocketConnection sock = cmd->sock;
4957 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4958 SilcChannelID *id = NULL;
4959 SilcChannelEntry channel;
4963 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4965 /* Get Channel ID */
4966 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4968 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4969 SILC_STATUS_ERR_NO_CHANNEL_ID);
4972 id = silc_id_payload_parse_id(tmp, len);
4974 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4975 SILC_STATUS_ERR_NO_CHANNEL_ID);
4979 /* Get channel entry */
4980 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4982 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4984 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4985 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4990 /* Check whether this client is on the channel */
4991 if (!silc_server_client_on_channel(id_entry, channel)) {
4992 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4993 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4997 /* Notify routers that they should remove this client from their list
4998 of clients on the channel. Send LEAVE notify type. */
4999 if (!server->standalone)
5000 silc_server_send_notify_leave(server, server->router->connection,
5001 server->server_type == SILC_ROUTER ?
5002 TRUE : FALSE, channel, id_entry->id);
5004 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5007 /* Remove client from channel */
5008 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5010 /* If the channel does not exist anymore we won't send anything */
5013 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5014 /* Re-generate channel key */
5015 if (!silc_server_create_channel_key(server, channel, 0))
5018 /* Send the channel key */
5019 silc_server_send_channel_key(server, NULL, channel,
5020 server->server_type == SILC_ROUTER ?
5021 FALSE : !server->standalone);
5026 silc_server_command_free(cmd);
5029 /* Server side of command USERS. Resolves clients and their USERS currently
5030 joined on the requested channel. The list of Client ID's and their modes
5031 on the channel is sent back. */
5033 SILC_SERVER_CMD_FUNC(users)
5035 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5036 SilcServer server = cmd->server;
5037 SilcChannelEntry channel;
5038 SilcChannelID *id = NULL;
5039 SilcBuffer packet, idp;
5040 unsigned char *channel_id;
5041 uint32 channel_id_len;
5042 SilcBuffer client_id_list;
5043 SilcBuffer client_mode_list;
5044 unsigned char lc[4];
5045 uint32 list_count = 0;
5046 uint16 ident = silc_command_get_ident(cmd->payload);
5049 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5051 /* Get Channel ID */
5052 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5054 /* Get channel name */
5055 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5057 if (!channel_id && !channel_name) {
5058 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5059 SILC_STATUS_ERR_NO_CHANNEL_ID);
5064 id = silc_id_payload_parse_id(channel_id, channel_id_len);
5066 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5067 SILC_STATUS_ERR_NO_CHANNEL_ID);
5072 /* If we are server and we don't know about this channel we will send
5073 the command to our router. If we know about the channel then we also
5074 have the list of users already. */
5076 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5078 channel = silc_idlist_find_channel_by_name(server->local_list,
5079 channel_name, NULL);
5081 if (!channel || channel->disabled) {
5082 if (server->server_type != SILC_ROUTER && !server->standalone &&
5086 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5087 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5089 /* Send USERS command */
5090 silc_server_packet_send(server, server->router->connection,
5091 SILC_PACKET_COMMAND, cmd->packet->flags,
5092 tmpbuf->data, tmpbuf->len, TRUE);
5094 /* Reprocess this packet after received reply */
5095 silc_server_command_pending(server, SILC_COMMAND_USERS,
5096 silc_command_get_ident(cmd->payload),
5097 silc_server_command_destructor,
5098 silc_server_command_users,
5099 silc_server_command_dup(cmd));
5100 cmd->pending = TRUE;
5101 silc_command_set_ident(cmd->payload, ident);
5103 silc_buffer_free(tmpbuf);
5108 /* Check the global list as well. */
5110 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5112 channel = silc_idlist_find_channel_by_name(server->global_list,
5113 channel_name, NULL);
5115 /* Channel really does not exist */
5116 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5117 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5122 /* If the channel is private or secret do not send anything, unless the
5123 user requesting this command is on the channel. */
5124 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5125 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5126 && !silc_server_client_on_channel(cmd->sock->user_data, channel)) {
5127 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5128 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5133 (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
5134 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5135 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5140 /* Get the users list */
5141 silc_server_get_users_on_channel(server, channel, &client_id_list,
5142 &client_mode_list, &list_count);
5145 SILC_PUT32_MSB(list_count, lc);
5148 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5149 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5150 SILC_STATUS_OK, ident, 4,
5151 2, idp->data, idp->len,
5153 4, client_id_list->data,
5154 client_id_list->len,
5155 5, client_mode_list->data,
5156 client_mode_list->len);
5157 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5158 packet->data, packet->len, FALSE);
5160 silc_buffer_free(idp);
5161 silc_buffer_free(packet);
5162 silc_buffer_free(client_id_list);
5163 silc_buffer_free(client_mode_list);
5167 silc_server_command_free(cmd);
5170 /* Server side of command GETKEY. This fetches the client's public key
5171 from the server where to the client is connected. */
5173 SILC_SERVER_CMD_FUNC(getkey)
5175 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5176 SilcServer server = cmd->server;
5178 SilcClientEntry client;
5179 SilcServerEntry server_entry;
5180 SilcClientID *client_id = NULL;
5181 SilcServerID *server_id = NULL;
5182 SilcIDPayload idp = NULL;
5183 uint16 ident = silc_command_get_ident(cmd->payload);
5184 unsigned char *tmp, *pkdata;
5185 uint32 tmp_len, pklen;
5186 SilcBuffer pk = NULL;
5189 SILC_LOG_DEBUG(("Start"));
5191 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5193 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5194 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5197 idp = silc_id_payload_parse_data(tmp, tmp_len);
5199 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5200 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5204 id_type = silc_id_payload_get_type(idp);
5205 if (id_type == SILC_ID_CLIENT) {
5206 client_id = silc_id_payload_get_id(idp);
5208 /* If the client is not found from local list there is no chance it
5209 would be locally connected client so send the command further. */
5210 client = silc_idlist_find_client_by_id(server->local_list,
5211 client_id, TRUE, NULL);
5213 client = silc_idlist_find_client_by_id(server->global_list,
5214 client_id, TRUE, NULL);
5216 if ((!client && !cmd->pending && !server->standalone) ||
5217 (client && !client->connection && !cmd->pending) ||
5218 (client && !client->data.public_key && !cmd->pending)) {
5221 SilcSocketConnection dest_sock;
5223 dest_sock = silc_server_get_client_route(server, NULL, 0,
5228 old_ident = silc_command_get_ident(cmd->payload);
5229 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5230 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5232 silc_server_packet_send(server, dest_sock,
5233 SILC_PACKET_COMMAND, cmd->packet->flags,
5234 tmpbuf->data, tmpbuf->len, TRUE);
5236 /* Reprocess this packet after received reply from router */
5237 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5238 silc_command_get_ident(cmd->payload),
5239 silc_server_command_destructor,
5240 silc_server_command_getkey,
5241 silc_server_command_dup(cmd));
5242 cmd->pending = TRUE;
5244 silc_command_set_ident(cmd->payload, old_ident);
5245 silc_buffer_free(tmpbuf);
5250 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5251 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5255 /* The client is locally connected, just get the public key and
5256 send it back. If they key does not exist then do not send it,
5257 send just OK reply */
5258 if (!client->data.public_key) {
5262 tmp = silc_pkcs_public_key_encode(client->data.public_key, &tmp_len);
5263 pk = silc_buffer_alloc(4 + tmp_len);
5264 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5265 silc_buffer_format(pk,
5266 SILC_STR_UI_SHORT(tmp_len),
5267 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5268 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5274 } else if (id_type == SILC_ID_SERVER) {
5275 server_id = silc_id_payload_get_id(idp);
5277 /* If the server is not found from local list there is no chance it
5278 would be locally connected server so send the command further. */
5279 server_entry = silc_idlist_find_server_by_id(server->local_list,
5280 server_id, TRUE, NULL);
5282 server_entry = silc_idlist_find_server_by_id(server->global_list,
5283 server_id, TRUE, NULL);
5285 if (server_entry != server->id_entry &&
5286 ((!server_entry && !cmd->pending && !server->standalone) ||
5287 (server_entry && !server_entry->connection && !cmd->pending &&
5288 !server->standalone) ||
5289 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5290 !server->standalone))) {
5294 old_ident = silc_command_get_ident(cmd->payload);
5295 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5296 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5298 silc_server_packet_send(server, server->router->connection,
5299 SILC_PACKET_COMMAND, cmd->packet->flags,
5300 tmpbuf->data, tmpbuf->len, TRUE);
5302 /* Reprocess this packet after received reply from router */
5303 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5304 silc_command_get_ident(cmd->payload),
5305 silc_server_command_destructor,
5306 silc_server_command_getkey,
5307 silc_server_command_dup(cmd));
5308 cmd->pending = TRUE;
5310 silc_command_set_ident(cmd->payload, old_ident);
5311 silc_buffer_free(tmpbuf);
5315 if (!server_entry) {
5316 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5317 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5321 /* If they key does not exist then do not send it, send just OK reply */
5322 if (!server_entry->data.public_key) {
5326 tmp = silc_pkcs_public_key_encode(server_entry->data.public_key,
5328 pk = silc_buffer_alloc(4 + tmp_len);
5329 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5330 silc_buffer_format(pk,
5331 SILC_STR_UI_SHORT(tmp_len),
5332 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5333 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5343 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5344 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5345 SILC_STATUS_OK, ident,
5349 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5350 packet->data, packet->len, FALSE);
5351 silc_buffer_free(packet);
5354 silc_buffer_free(pk);
5358 silc_id_payload_free(idp);
5359 silc_free(client_id);
5360 silc_free(server_id);
5361 silc_server_command_free(cmd);