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;
1959 /* Server side of command NICK. Sets nickname for user. Setting
1960 nickname causes generation of a new client ID for the client. The
1961 new client ID is sent to the client after changing the nickname. */
1963 SILC_SERVER_CMD_FUNC(nick)
1965 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1966 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1967 SilcServer server = cmd->server;
1968 SilcBuffer packet, nidp, oidp = NULL;
1969 SilcClientID *new_id;
1971 uint16 ident = silc_command_get_ident(cmd->payload);
1974 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1977 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
1979 /* Check nickname */
1980 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1981 if (silc_server_command_bad_chars(nick) == TRUE) {
1982 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1983 SILC_STATUS_ERR_BAD_NICKNAME);
1987 if (strlen(nick) > 128)
1990 /* Check for same nickname */
1991 if (!strcmp(client->nickname, nick)) {
1992 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1996 /* Create new Client ID */
1997 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
1999 cmd->server->md5hash, nick,
2002 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2005 /* Send notify about nickname change to our router. We send the new
2006 ID and ask to replace it with the old one. If we are router the
2007 packet is broadcasted. Send NICK_CHANGE notify. */
2008 if (!server->standalone)
2009 silc_server_send_notify_nick_change(server, server->router->connection,
2010 server->server_type == SILC_SERVER ?
2011 FALSE : TRUE, client->id,
2014 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2016 /* Remove old cache entry */
2017 silc_idcache_del_by_context(server->local_list->clients, client);
2020 silc_free(client->id);
2022 /* Save the nickname as this client is our local client */
2023 silc_free(client->nickname);
2025 client->nickname = strdup(nick);
2026 client->id = new_id;
2028 /* Update client cache */
2029 silc_idcache_add(server->local_list->clients, client->nickname,
2030 client->id, (void *)client, FALSE);
2032 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2034 /* Send NICK_CHANGE notify to the client's channels */
2035 silc_server_send_notify_on_channels(server, NULL, client,
2036 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
2037 oidp->data, oidp->len,
2038 nidp->data, nidp->len);
2041 /* Send the new Client ID as reply command back to client */
2042 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
2043 SILC_STATUS_OK, ident, 1,
2044 2, nidp->data, nidp->len);
2045 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2046 0, packet->data, packet->len, FALSE);
2048 silc_buffer_free(packet);
2049 silc_buffer_free(nidp);
2051 silc_buffer_free(oidp);
2054 silc_server_command_free(cmd);
2057 /* Sends the LIST command reply */
2060 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2061 SilcChannelEntry *lch,
2063 SilcChannelEntry *gch,
2067 SilcBuffer packet, idp;
2068 SilcChannelEntry entry;
2069 SilcCommandStatus status;
2070 uint16 ident = silc_command_get_ident(cmd->payload);
2072 unsigned char usercount[4];
2075 for (i = 0; i < lch_count; i++)
2076 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2078 for (i = 0; i < gch_count; i++)
2079 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2082 status = SILC_STATUS_OK;
2083 if ((lch_count + gch_count) > 1)
2084 status = SILC_STATUS_LIST_START;
2087 for (i = 0; i < lch_count; i++) {
2094 status = SILC_STATUS_LIST_ITEM;
2096 if (lch_count > 1 && i == lch_count - 1 && !gch_count)
2097 status = SILC_STATUS_LIST_END;
2099 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2101 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2102 topic = "*private*";
2103 memset(usercount, 0, sizeof(usercount));
2105 topic = entry->topic;
2106 users = silc_hash_table_count(entry->user_list);
2107 SILC_PUT32_MSB(users, usercount);
2110 /* Send the reply */
2113 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2115 2, idp->data, idp->len,
2116 3, entry->channel_name,
2117 strlen(entry->channel_name),
2118 4, topic, strlen(topic),
2122 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2124 2, idp->data, idp->len,
2125 3, entry->channel_name,
2126 strlen(entry->channel_name),
2128 silc_server_packet_send(cmd->server, cmd->sock,
2129 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2130 packet->len, FALSE);
2131 silc_buffer_free(packet);
2132 silc_buffer_free(idp);
2135 status = i ? SILC_STATUS_LIST_ITEM : SILC_STATUS_OK;
2138 for (i = 0; i < gch_count; i++) {
2145 status = SILC_STATUS_LIST_ITEM;
2147 if (gch_count > 1 && i == lch_count - 1)
2148 status = SILC_STATUS_LIST_END;
2150 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2152 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2153 topic = "*private*";
2154 memset(usercount, 0, sizeof(usercount));
2156 topic = entry->topic;
2157 users = silc_hash_table_count(entry->user_list);
2158 SILC_PUT32_MSB(users, usercount);
2161 /* Send the reply */
2164 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2166 2, idp->data, idp->len,
2167 3, entry->channel_name,
2168 strlen(entry->channel_name),
2169 4, topic, strlen(topic),
2173 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2175 2, idp->data, idp->len,
2176 3, entry->channel_name,
2177 strlen(entry->channel_name),
2179 silc_server_packet_send(cmd->server, cmd->sock,
2180 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2181 packet->len, FALSE);
2182 silc_buffer_free(packet);
2183 silc_buffer_free(idp);
2187 /* Server side of LIST command. This lists the channel of the requested
2188 server. Secret channels are not listed. */
2190 SILC_SERVER_CMD_FUNC(list)
2192 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2193 SilcServer server = cmd->server;
2194 SilcChannelID *channel_id = NULL;
2197 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2198 uint32 lch_count = 0, gch_count = 0;
2200 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2202 /* If we are normal server, send the command to router, since we
2203 want to know all channels in the network. */
2204 if (!cmd->pending && server->server_type == SILC_SERVER &&
2205 !server->standalone) {
2209 old_ident = silc_command_get_ident(cmd->payload);
2210 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2211 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2212 silc_server_packet_send(server, server->router->connection,
2213 SILC_PACKET_COMMAND, cmd->packet->flags,
2214 tmpbuf->data, tmpbuf->len, TRUE);
2216 /* Reprocess this packet after received reply from router */
2217 silc_server_command_pending(server, SILC_COMMAND_LIST,
2218 silc_command_get_ident(cmd->payload),
2219 silc_server_command_destructor,
2220 silc_server_command_list,
2221 silc_server_command_dup(cmd));
2222 cmd->pending = TRUE;
2223 silc_command_set_ident(cmd->payload, old_ident);
2224 silc_buffer_free(tmpbuf);
2228 /* Get Channel ID */
2229 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2231 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2233 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2234 SILC_STATUS_ERR_NO_CHANNEL_ID);
2239 /* Get the channels from local list */
2240 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2243 /* Get the channels from global list */
2244 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2247 /* Send the reply */
2248 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2249 gchannels, gch_count);
2252 silc_server_command_free(cmd);
2255 /* Server side of TOPIC command. Sets topic for channel and/or returns
2256 current topic to client. */
2258 SILC_SERVER_CMD_FUNC(topic)
2260 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2261 SilcServer server = cmd->server;
2262 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2263 SilcChannelID *channel_id;
2264 SilcChannelEntry channel;
2265 SilcChannelClientEntry chl;
2266 SilcBuffer packet, idp;
2268 uint32 argc, tmp_len;
2269 uint16 ident = silc_command_get_ident(cmd->payload);
2271 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2273 argc = silc_argument_get_arg_num(cmd->args);
2275 /* Get Channel ID */
2276 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2278 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2279 SILC_STATUS_ERR_NO_CHANNEL_ID);
2282 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2284 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2285 SILC_STATUS_ERR_NO_CHANNEL_ID);
2289 /* Check whether the channel exists */
2290 channel = silc_idlist_find_channel_by_id(server->local_list,
2293 channel = silc_idlist_find_channel_by_id(server->global_list,
2296 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2297 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2304 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2306 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2307 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2311 if (strlen(tmp) > 256) {
2312 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2313 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2317 /* See whether the client is on channel and has rights to change topic */
2318 if (!silc_hash_table_find(channel->user_list, client, NULL,
2320 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2321 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2325 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2326 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2327 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2328 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2333 /* Set the topic for channel */
2334 silc_free(channel->topic);
2335 channel->topic = strdup(tmp);
2337 /* Send TOPIC_SET notify type to the network */
2338 if (!server->standalone)
2339 silc_server_send_notify_topic_set(server, server->router->connection,
2340 server->server_type == SILC_ROUTER ?
2341 TRUE : FALSE, channel, client->id,
2344 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2346 /* Send notify about topic change to all clients on the channel */
2347 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2348 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2349 idp->data, idp->len,
2350 channel->topic, strlen(channel->topic));
2351 silc_buffer_free(idp);
2354 /* Send the topic to client as reply packet */
2355 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2357 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2358 SILC_STATUS_OK, ident, 2,
2359 2, idp->data, idp->len,
2361 strlen(channel->topic));
2363 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2364 SILC_STATUS_OK, ident, 1,
2365 2, idp->data, idp->len);
2366 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2367 0, packet->data, packet->len, FALSE);
2369 silc_buffer_free(packet);
2370 silc_buffer_free(idp);
2371 silc_free(channel_id);
2374 silc_server_command_free(cmd);
2377 /* Server side of INVITE command. Invites some client to join some channel.
2378 This command is also used to manage the invite list of the channel. */
2380 SILC_SERVER_CMD_FUNC(invite)
2382 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2383 SilcServer server = cmd->server;
2384 SilcSocketConnection sock = cmd->sock, dest_sock;
2385 SilcChannelClientEntry chl;
2386 SilcClientEntry sender, dest;
2387 SilcClientID *dest_id = NULL;
2388 SilcChannelEntry channel;
2389 SilcChannelID *channel_id = NULL;
2390 SilcIDListData idata;
2391 SilcBuffer idp, idp2, packet;
2392 unsigned char *tmp, *add, *del;
2394 uint16 ident = silc_command_get_ident(cmd->payload);
2396 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2398 /* Get Channel ID */
2399 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2401 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2402 SILC_STATUS_ERR_NO_CHANNEL_ID);
2405 channel_id = silc_id_payload_parse_id(tmp, len);
2407 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2408 SILC_STATUS_ERR_NO_CHANNEL_ID);
2412 /* Get the channel entry */
2413 channel = silc_idlist_find_channel_by_id(server->local_list,
2416 channel = silc_idlist_find_channel_by_id(server->global_list,
2419 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2420 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2425 /* Check whether the sender of this command is on the channel. */
2426 sender = (SilcClientEntry)sock->user_data;
2427 if (!silc_server_client_on_channel(sender, channel)) {
2428 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2429 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2433 /* Check whether the channel is invite-only channel. If yes then the
2434 sender of this command must be at least channel operator. */
2435 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2436 silc_hash_table_find(channel->user_list, sender, NULL, (void *)&chl);
2437 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2438 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2439 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2444 /* Get destination client ID */
2445 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2449 dest_id = silc_id_payload_parse_id(tmp, len);
2451 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2452 SILC_STATUS_ERR_NO_CLIENT_ID);
2456 /* Get the client entry */
2457 dest = silc_server_get_client_resolve(server, dest_id);
2459 if (server->server_type != SILC_SERVER) {
2460 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2461 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2465 /* The client info is being resolved. Reprocess this packet after
2466 receiving the reply to the query. */
2467 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2469 silc_server_command_destructor,
2470 silc_server_command_invite,
2471 silc_server_command_dup(cmd));
2472 cmd->pending = TRUE;
2473 silc_free(channel_id);
2478 /* Check whether the requested client is already on the channel. */
2479 if (silc_server_client_on_channel(dest, channel)) {
2480 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2481 SILC_STATUS_ERR_USER_ON_CHANNEL);
2485 /* Get route to the client */
2486 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2488 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2489 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2493 memset(invite, 0, sizeof(invite));
2494 strncat(invite, dest->nickname, strlen(dest->nickname));
2495 strncat(invite, "!", 1);
2496 strncat(invite, dest->username, strlen(dest->username));
2497 if (!strchr(dest->username, '@')) {
2498 strncat(invite, "@", 1);
2499 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2502 len = strlen(invite);
2503 if (!channel->invite_list)
2504 channel->invite_list = silc_calloc(len + 2,
2505 sizeof(*channel->invite_list));
2507 channel->invite_list = silc_realloc(channel->invite_list,
2508 sizeof(*channel->invite_list) *
2510 strlen(channel->invite_list) + 2));
2511 strncat(channel->invite_list, invite, len);
2512 strncat(channel->invite_list, ",", 1);
2514 /* Send notify to the client that is invited to the channel */
2515 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2516 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2517 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2519 SILC_NOTIFY_TYPE_INVITE, 3,
2520 idp->data, idp->len,
2521 channel->channel_name,
2522 strlen(channel->channel_name),
2523 idp2->data, idp2->len);
2524 silc_buffer_free(idp);
2525 silc_buffer_free(idp2);
2528 /* Add the client to the invite list of the channel */
2529 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2531 if (!channel->invite_list)
2532 channel->invite_list = silc_calloc(len + 2,
2533 sizeof(*channel->invite_list));
2535 channel->invite_list = silc_realloc(channel->invite_list,
2536 sizeof(*channel->invite_list) *
2538 strlen(channel->invite_list) + 2));
2539 if (add[len - 1] == ',')
2540 add[len - 1] = '\0';
2542 strncat(channel->invite_list, add, len);
2543 strncat(channel->invite_list, ",", 1);
2546 /* Get the invite to be removed and remove it from the list */
2547 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2548 if (del && channel->invite_list) {
2549 char *start, *end, *n;
2551 if (!strncmp(channel->invite_list, del,
2552 strlen(channel->invite_list) - 1)) {
2553 silc_free(channel->invite_list);
2554 channel->invite_list = NULL;
2556 start = strstr(channel->invite_list, del);
2557 if (start && strlen(start) >= len) {
2559 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2560 strncat(n, channel->invite_list, start - channel->invite_list);
2561 strncat(n, end + 1, ((channel->invite_list +
2562 strlen(channel->invite_list)) - end) - 1);
2563 silc_free(channel->invite_list);
2564 channel->invite_list = n;
2569 /* Send notify to the primary router */
2570 if (!server->standalone)
2571 silc_server_send_notify_invite(server, server->router->connection,
2572 server->server_type == SILC_ROUTER ?
2573 TRUE : FALSE, channel,
2574 sender->id, add, del);
2576 /* Send command reply */
2577 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2581 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2582 SILC_STATUS_OK, ident, 2,
2584 3, channel->invite_list,
2585 channel->invite_list ?
2586 strlen(channel->invite_list) : 0);
2589 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2590 SILC_STATUS_OK, ident, 1,
2592 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2593 packet->data, packet->len, FALSE);
2594 silc_buffer_free(packet);
2598 silc_free(channel_id);
2599 silc_server_command_free(cmd);
2604 SilcSocketConnection sock;
2608 /* Quits connection to client. This gets called if client won't
2609 close the connection even when it has issued QUIT command. */
2611 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2613 QuitInternal q = (QuitInternal)context;
2615 /* Free all client specific data, such as client entry and entires
2616 on channels this client may be on. */
2617 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2619 q->sock->user_data = NULL;
2621 /* Close the connection on our side */
2622 silc_server_close_connection(q->server, q->sock);
2624 silc_free(q->signoff);
2628 /* Quits SILC session. This is the normal way to disconnect client. */
2630 SILC_SERVER_CMD_FUNC(quit)
2632 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2633 SilcServer server = cmd->server;
2634 SilcSocketConnection sock = cmd->sock;
2636 unsigned char *tmp = NULL;
2639 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2641 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2644 /* Get destination ID */
2645 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2649 q = silc_calloc(1, sizeof(*q));
2652 q->signoff = tmp ? strdup(tmp) : NULL;
2654 /* We quit the connection with little timeout */
2655 silc_schedule_task_add(server->schedule, sock->sock,
2656 silc_server_command_quit_cb, (void *)q,
2657 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2660 silc_server_command_free(cmd);
2663 /* Server side of command KILL. This command is used by router operator
2664 to remove an client from the SILC Network temporarily. */
2666 SILC_SERVER_CMD_FUNC(kill)
2668 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2669 SilcServer server = cmd->server;
2670 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2671 SilcClientEntry remote_client;
2672 SilcClientID *client_id;
2673 unsigned char *tmp, *comment;
2674 uint32 tmp_len, tmp_len2;
2676 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2678 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2681 /* KILL command works only on router */
2682 if (server->server_type != SILC_ROUTER) {
2683 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2684 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2688 /* Check whether client has the permissions. */
2689 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2690 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2691 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2695 /* Get the client ID */
2696 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2698 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2699 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2702 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2704 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2705 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2709 /* Get the client entry */
2710 remote_client = silc_idlist_find_client_by_id(server->local_list,
2711 client_id, TRUE, NULL);
2712 if (!remote_client) {
2713 remote_client = silc_idlist_find_client_by_id(server->global_list,
2714 client_id, TRUE, NULL);
2715 if (!remote_client) {
2716 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2717 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2723 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2727 /* Send reply to the sender */
2728 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2731 /* Send the KILL notify packets. First send it to the channel, then
2732 to our primary router and then directly to the client who is being
2733 killed right now. */
2735 /* Send KILLED notify to the channels. It is not sent to the client
2736 as it will be sent differently destined directly to the client and not
2738 silc_server_send_notify_on_channels(server, remote_client,
2739 remote_client, SILC_NOTIFY_TYPE_KILLED,
2742 comment, comment ? tmp_len2 : 0);
2744 /* Send KILLED notify to primary route */
2745 if (!server->standalone)
2746 silc_server_send_notify_killed(server, server->router->connection, TRUE,
2747 remote_client->id, comment);
2749 /* Send KILLED notify to the client directly */
2750 silc_server_send_notify_killed(server, remote_client->connection ?
2751 remote_client->connection :
2752 remote_client->router->connection, FALSE,
2753 remote_client->id, comment);
2755 /* Remove the client from all channels. This generates new keys to the
2756 channels as well. */
2757 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2760 /* Remove the client entry, If it is locally connected then we will also
2761 disconnect the client here */
2762 if (remote_client->connection) {
2763 /* Remove locally conneted client */
2764 SilcSocketConnection sock = remote_client->connection;
2765 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2766 silc_server_close_connection(server, sock);
2768 /* Remove remote client */
2769 if (!silc_idlist_del_client(server->global_list, remote_client))
2770 silc_idlist_del_client(server->local_list, remote_client);
2774 silc_server_command_free(cmd);
2777 /* Server side of command INFO. This sends information about us to
2778 the client. If client requested specific server we will send the
2779 command to that server. */
2781 SILC_SERVER_CMD_FUNC(info)
2783 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2784 SilcServer server = cmd->server;
2785 SilcBuffer packet, idp;
2788 char *dest_server, *server_info = NULL, *server_name;
2789 uint16 ident = silc_command_get_ident(cmd->payload);
2790 SilcServerEntry entry = NULL;
2791 SilcServerID *server_id = NULL;
2793 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2795 /* Get server name */
2796 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2799 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2801 server_id = silc_id_payload_parse_id(tmp, tmp_len);
2803 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2804 SILC_STATUS_ERR_NO_SERVER_ID);
2810 /* Check whether we have this server cached */
2811 entry = silc_idlist_find_server_by_id(server->local_list,
2812 server_id, TRUE, NULL);
2814 entry = silc_idlist_find_server_by_id(server->global_list,
2815 server_id, TRUE, NULL);
2816 if (!entry && server->server_type != SILC_SERVER) {
2817 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2818 SILC_STATUS_ERR_NO_SUCH_SERVER);
2824 /* Some buggy servers has sent request to router about themselves. */
2825 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2828 if ((!dest_server && !server_id && !entry) || (entry &&
2829 entry == server->id_entry) ||
2830 (dest_server && !cmd->pending &&
2831 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2832 /* Send our reply */
2833 char info_string[256];
2835 memset(info_string, 0, sizeof(info_string));
2836 snprintf(info_string, sizeof(info_string),
2837 "location: %s server: %s admin: %s <%s>",
2838 server->config->admin_info->location,
2839 server->config->admin_info->server_type,
2840 server->config->admin_info->admin_name,
2841 server->config->admin_info->admin_email);
2843 server_info = info_string;
2844 entry = server->id_entry;
2846 /* Check whether we have this server cached */
2847 if (!entry && dest_server) {
2848 entry = silc_idlist_find_server_by_name(server->global_list,
2849 dest_server, TRUE, NULL);
2851 entry = silc_idlist_find_server_by_name(server->local_list,
2852 dest_server, TRUE, NULL);
2856 if (!cmd->pending &&
2857 server->server_type != SILC_SERVER && entry && !entry->server_info) {
2858 /* Send to the server */
2862 old_ident = silc_command_get_ident(cmd->payload);
2863 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2864 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2866 silc_server_packet_send(server, entry->connection,
2867 SILC_PACKET_COMMAND, cmd->packet->flags,
2868 tmpbuf->data, tmpbuf->len, TRUE);
2870 /* Reprocess this packet after received reply from router */
2871 silc_server_command_pending(server, SILC_COMMAND_INFO,
2872 silc_command_get_ident(cmd->payload),
2873 silc_server_command_destructor,
2874 silc_server_command_info,
2875 silc_server_command_dup(cmd));
2876 cmd->pending = TRUE;
2877 silc_command_set_ident(cmd->payload, old_ident);
2878 silc_buffer_free(tmpbuf);
2882 if (!entry && !cmd->pending && !server->standalone) {
2883 /* Send to the primary router */
2887 old_ident = silc_command_get_ident(cmd->payload);
2888 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2889 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2891 silc_server_packet_send(server, server->router->connection,
2892 SILC_PACKET_COMMAND, cmd->packet->flags,
2893 tmpbuf->data, tmpbuf->len, TRUE);
2895 /* Reprocess this packet after received reply from router */
2896 silc_server_command_pending(server, SILC_COMMAND_INFO,
2897 silc_command_get_ident(cmd->payload),
2898 silc_server_command_destructor,
2899 silc_server_command_info,
2900 silc_server_command_dup(cmd));
2901 cmd->pending = TRUE;
2902 silc_command_set_ident(cmd->payload, old_ident);
2903 silc_buffer_free(tmpbuf);
2908 silc_free(server_id);
2911 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2912 SILC_STATUS_ERR_NO_SUCH_SERVER);
2916 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2918 server_info = entry->server_info;
2919 server_name = entry->server_name;
2921 /* Send the reply */
2923 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2924 SILC_STATUS_OK, ident, 3,
2925 2, idp->data, idp->len,
2927 strlen(server_name),
2929 strlen(server_info));
2931 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2932 SILC_STATUS_OK, ident, 2,
2933 2, idp->data, idp->len,
2935 strlen(server_name));
2936 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2937 packet->data, packet->len, FALSE);
2939 silc_buffer_free(packet);
2940 silc_buffer_free(idp);
2943 silc_server_command_free(cmd);
2946 /* Server side of command PING. This just replies to the ping. */
2948 SILC_SERVER_CMD_FUNC(ping)
2950 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2951 SilcServer server = cmd->server;
2956 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
2959 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2961 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2962 SILC_STATUS_ERR_NO_SERVER_ID);
2965 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2969 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2970 /* Send our reply */
2971 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2974 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2975 SILC_STATUS_ERR_NO_SUCH_SERVER);
2982 silc_server_command_free(cmd);
2985 /* Internal routine to join channel. The channel sent to this function
2986 has been either created or resolved from ID lists. This joins the sent
2987 client to the channel. */
2989 static void silc_server_command_join_channel(SilcServer server,
2990 SilcServerCommandContext cmd,
2991 SilcChannelEntry channel,
2992 SilcClientID *client_id,
2997 SilcSocketConnection sock = cmd->sock;
2999 uint32 tmp_len, user_count;
3000 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
3001 SilcClientEntry client;
3002 SilcChannelClientEntry chl;
3003 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
3004 uint16 ident = silc_command_get_ident(cmd->payload);
3005 char check[512], check2[512];
3007 SILC_LOG_DEBUG(("Start"));
3012 /* Get the client entry */
3013 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3014 client = (SilcClientEntry)sock->user_data;
3016 client = silc_server_get_client_resolve(server, client_id);
3021 /* The client info is being resolved. Reprocess this packet after
3022 receiving the reply to the query. */
3023 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
3024 server->cmd_ident, NULL,
3025 silc_server_command_join,
3026 silc_server_command_dup(cmd));
3027 cmd->pending = TRUE;
3031 cmd->pending = FALSE;
3035 * Check channel modes
3038 memset(check, 0, sizeof(check));
3039 memset(check2, 0, sizeof(check2));
3040 strncat(check, client->nickname, strlen(client->nickname));
3041 strncat(check, "!", 1);
3042 strncat(check, client->username, strlen(client->username));
3043 if (!strchr(client->username, '@')) {
3044 strncat(check, "@", 1);
3045 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3048 strncat(check2, client->nickname, strlen(client->nickname));
3049 if (!strchr(client->nickname, '@')) {
3050 strncat(check2, "@", 1);
3051 strncat(check2, server->server_name, strlen(server->server_name));
3053 strncat(check2, "!", 1);
3054 strncat(check2, client->username, strlen(client->username));
3055 if (!strchr(client->username, '@')) {
3056 strncat(check2, "@", 1);
3057 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3060 /* Check invite list if channel is invite-only channel */
3061 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3062 if (!channel->invite_list ||
3063 (!silc_string_match(channel->invite_list, check) &&
3064 !silc_string_match(channel->invite_list, check2))) {
3065 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3066 SILC_STATUS_ERR_NOT_INVITED);
3071 /* Check ban list if it exists. If the client's nickname, server,
3072 username and/or hostname is in the ban list the access to the
3073 channel is denied. */
3074 if (channel->ban_list) {
3075 if (!channel->ban_list ||
3076 silc_string_match(channel->ban_list, check) ||
3077 silc_string_match(channel->ban_list, check2)) {
3078 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3079 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
3084 /* Get passphrase */
3085 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3087 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
3088 memcpy(passphrase, tmp, tmp_len);
3091 /* Check the channel passphrase if set. */
3092 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3093 if (!passphrase || !channel->passphrase ||
3094 memcmp(channel->passphrase, passphrase,
3095 strlen(channel->passphrase))) {
3096 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3097 SILC_STATUS_ERR_BAD_PASSWORD);
3102 /* Check user count limit if set. */
3103 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3104 if (silc_hash_table_count(channel->user_list) + 1 >
3105 channel->user_limit) {
3106 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3107 SILC_STATUS_ERR_CHANNEL_IS_FULL);
3113 * Client is allowed to join to the channel. Make it happen.
3116 /* Check whether the client already is on the channel */
3117 if (silc_server_client_on_channel(client, channel)) {
3118 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3119 SILC_STATUS_ERR_USER_ON_CHANNEL);
3123 /* Generate new channel key as protocol dictates */
3125 if (!silc_server_create_channel_key(server, channel, 0))
3128 /* Send the channel key. This is broadcasted to the channel but is not
3129 sent to the client who is joining to the channel. */
3130 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3131 silc_server_send_channel_key(server, NULL, channel,
3132 server->server_type == SILC_ROUTER ?
3133 FALSE : !server->standalone);
3136 /* Join the client to the channel by adding it to channel's user list.
3137 Add also the channel to client entry's channels list for fast cross-
3139 chl = silc_calloc(1, sizeof(*chl));
3141 chl->client = client;
3142 chl->channel = channel;
3143 silc_hash_table_add(channel->user_list, client, chl);
3144 silc_hash_table_add(client->channels, channel, chl);
3146 /* Get users on the channel */
3147 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3150 /* Encode Client ID Payload of the original client who wants to join */
3151 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3153 /* Encode command reply packet */
3154 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3155 SILC_PUT32_MSB(channel->mode, mode);
3156 SILC_PUT32_MSB(created, tmp2);
3157 SILC_PUT32_MSB(user_count, tmp3);
3159 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3160 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3161 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
3162 strlen(channel->channel_key->
3164 channel->channel_key->cipher->name,
3165 channel->key_len / 8, channel->key);
3170 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3171 SILC_STATUS_OK, ident, 13,
3172 2, channel->channel_name,
3173 strlen(channel->channel_name),
3174 3, chidp->data, chidp->len,
3175 4, clidp->data, clidp->len,
3178 7, keyp ? keyp->data : NULL,
3179 keyp ? keyp->len : 0,
3180 8, channel->ban_list,
3182 strlen(channel->ban_list) : 0,
3183 9, channel->invite_list,
3184 channel->invite_list ?
3185 strlen(channel->invite_list) : 0,
3188 strlen(channel->topic) : 0,
3189 11, silc_hmac_get_name(channel->hmac),
3190 strlen(silc_hmac_get_name(channel->
3193 13, user_list->data, user_list->len,
3194 14, mode_list->data,
3197 /* Send command reply */
3198 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3199 reply->data, reply->len, FALSE);
3201 /* Send JOIN notify to locally connected clients on the channel. If
3202 we are normal server then router will send or have sent JOIN notify
3203 already. However since we've added the client already to our channel
3204 we'll ignore it (in packet_receive.c) so we must send it here. If
3205 we are router then this will send it to local clients and local
3207 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3208 SILC_NOTIFY_TYPE_JOIN, 2,
3209 clidp->data, clidp->len,
3210 chidp->data, chidp->len);
3212 if (!cmd->pending) {
3213 /* Send JOIN notify packet to our primary router */
3214 if (!server->standalone)
3215 silc_server_send_notify_join(server, server->router->connection,
3216 server->server_type == SILC_ROUTER ?
3217 TRUE : FALSE, channel, client->id);
3220 /* Distribute the channel key to all backup routers. */
3221 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3222 keyp->data, keyp->len, FALSE, TRUE);
3225 silc_buffer_free(reply);
3226 silc_buffer_free(clidp);
3227 silc_buffer_free(chidp);
3228 silc_buffer_free(keyp);
3229 silc_buffer_free(user_list);
3230 silc_buffer_free(mode_list);
3233 silc_free(passphrase);
3236 /* Server side of command JOIN. Joins client into requested channel. If
3237 the channel does not exist it will be created. */
3239 SILC_SERVER_CMD_FUNC(join)
3241 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3242 SilcServer server = cmd->server;
3244 char *tmp, *channel_name = NULL, *cipher, *hmac;
3245 SilcChannelEntry channel;
3247 bool created = FALSE, create_key = TRUE;
3248 SilcClientID *client_id;
3250 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 1, 4);
3252 /* Get channel name */
3253 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3255 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3256 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3261 if (strlen(channel_name) > 256)
3262 channel_name[255] = '\0';
3264 if (silc_server_command_bad_chars(channel_name) == TRUE) {
3265 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3266 SILC_STATUS_ERR_BAD_CHANNEL);
3270 /* Get Client ID of the client who is joining to the channel */
3271 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3273 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3274 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3277 client_id = silc_id_payload_parse_id(tmp, tmp_len);
3279 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3280 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3284 /* Get cipher and hmac name */
3285 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3286 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3288 /* See if the channel exists */
3289 channel = silc_idlist_find_channel_by_name(server->local_list,
3290 channel_name, NULL);
3292 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3293 /* If this is coming from client the Client ID in the command packet must
3294 be same as the client's ID. */
3295 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3296 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3297 if (!SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
3298 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3299 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3304 if (!channel || channel->disabled) {
3305 /* Channel not found */
3307 /* If we are standalone server we don't have a router, we just create
3308 the channel by ourselves. */
3309 if (server->standalone) {
3310 channel = silc_server_create_new_channel(server, server->id, cipher,
3311 hmac, channel_name, TRUE);
3313 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3314 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3318 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3324 /* The channel does not exist on our server. If we are normal server
3325 we will send JOIN command to our router which will handle the
3326 joining procedure (either creates the channel if it doesn't exist
3327 or joins the client to it). */
3328 if (server->server_type != SILC_ROUTER) {
3332 /* If this is pending command callback then we've resolved
3333 it and it didn't work, return since we've notified the
3334 client already in the command reply callback. */
3338 old_ident = silc_command_get_ident(cmd->payload);
3339 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3340 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3342 /* Send JOIN command to our router */
3343 silc_server_packet_send(server, (SilcSocketConnection)
3344 server->router->connection,
3345 SILC_PACKET_COMMAND, cmd->packet->flags,
3346 tmpbuf->data, tmpbuf->len, TRUE);
3348 /* Reprocess this packet after received reply from router */
3349 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3350 silc_command_get_ident(cmd->payload),
3351 silc_server_command_destructor,
3352 silc_server_command_join,
3353 silc_server_command_dup(cmd));
3354 cmd->pending = TRUE;
3358 /* We are router and the channel does not seem exist so we will check
3359 our global list as well for the channel. */
3360 channel = silc_idlist_find_channel_by_name(server->global_list,
3361 channel_name, NULL);
3363 /* Channel really does not exist, create it */
3364 channel = silc_server_create_new_channel(server, server->id, cipher,
3365 hmac, channel_name, TRUE);
3367 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3368 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3372 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3380 /* Channel not found */
3382 /* If the command came from router and we are normal server then
3383 something went wrong with the joining as the channel was not found.
3384 We can't do anything else but ignore this. */
3385 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3386 server->server_type != SILC_ROUTER)
3389 /* We are router and the channel does not seem exist so we will check
3390 our global list as well for the channel. */
3391 channel = silc_idlist_find_channel_by_name(server->global_list,
3392 channel_name, NULL);
3394 /* Channel really does not exist, create it */
3395 channel = silc_server_create_new_channel(server, server->id, cipher,
3396 hmac, channel_name, TRUE);
3398 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3399 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3403 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3410 /* Check whether the channel was created by our router */
3411 if (cmd->pending && context2) {
3412 SilcServerCommandReplyContext reply =
3413 (SilcServerCommandReplyContext)context2;
3414 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3415 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3416 SILC_GET32_MSB(created, tmp);
3417 create_key = FALSE; /* Router returned the key already */
3421 /* If the channel does not have global users and is also empty the client
3422 will be the channel founder and operator. */
3423 if (!channel->global_users && !silc_hash_table_count(channel->user_list))
3424 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3426 /* Join to the channel */
3427 silc_server_command_join_channel(server, cmd, channel, client_id,
3428 created, create_key, umode);
3430 silc_free(client_id);
3433 silc_server_command_free(cmd);
3436 /* Server side of command MOTD. Sends server's current "message of the
3437 day" to the client. */
3439 SILC_SERVER_CMD_FUNC(motd)
3441 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3442 SilcServer server = cmd->server;
3443 SilcBuffer packet, idp;
3444 char *motd, *dest_server;
3446 uint16 ident = silc_command_get_ident(cmd->payload);
3448 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3450 /* Get server name */
3451 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3453 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3454 SILC_STATUS_ERR_NO_SUCH_SERVER);
3458 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3461 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3463 if (server->config && server->config->motd &&
3464 server->config->motd->motd_file) {
3466 motd = silc_file_readfile(server->config->motd->motd_file, &motd_len);
3471 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3472 SILC_STATUS_OK, ident, 2,
3478 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3479 SILC_STATUS_OK, ident, 1,
3483 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3484 packet->data, packet->len, FALSE);
3485 silc_buffer_free(packet);
3486 silc_buffer_free(idp);
3488 SilcServerEntry entry;
3490 /* Check whether we have this server cached */
3491 entry = silc_idlist_find_server_by_name(server->global_list,
3492 dest_server, TRUE, NULL);
3494 entry = silc_idlist_find_server_by_name(server->local_list,
3495 dest_server, TRUE, NULL);
3498 if (server->server_type != SILC_SERVER && !cmd->pending &&
3499 entry && !entry->motd) {
3500 /* Send to the server */
3504 old_ident = silc_command_get_ident(cmd->payload);
3505 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3506 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3508 silc_server_packet_send(server, entry->connection,
3509 SILC_PACKET_COMMAND, cmd->packet->flags,
3510 tmpbuf->data, tmpbuf->len, TRUE);
3512 /* Reprocess this packet after received reply from router */
3513 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3514 silc_command_get_ident(cmd->payload),
3515 silc_server_command_destructor,
3516 silc_server_command_motd,
3517 silc_server_command_dup(cmd));
3518 cmd->pending = TRUE;
3519 silc_command_set_ident(cmd->payload, old_ident);
3520 silc_buffer_free(tmpbuf);
3524 if (!entry && !cmd->pending && !server->standalone) {
3525 /* Send to the primary router */
3529 old_ident = silc_command_get_ident(cmd->payload);
3530 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3531 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3533 silc_server_packet_send(server, server->router->connection,
3534 SILC_PACKET_COMMAND, cmd->packet->flags,
3535 tmpbuf->data, tmpbuf->len, TRUE);
3537 /* Reprocess this packet after received reply from router */
3538 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3539 silc_command_get_ident(cmd->payload),
3540 silc_server_command_destructor,
3541 silc_server_command_motd,
3542 silc_server_command_dup(cmd));
3543 cmd->pending = TRUE;
3544 silc_command_set_ident(cmd->payload, old_ident);
3545 silc_buffer_free(tmpbuf);
3550 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3551 SILC_STATUS_ERR_NO_SUCH_SERVER);
3555 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3558 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3559 SILC_STATUS_OK, ident, 2,
3562 strlen(entry->motd));
3564 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3565 SILC_STATUS_OK, ident, 1,
3568 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3569 packet->data, packet->len, FALSE);
3570 silc_buffer_free(packet);
3571 silc_buffer_free(idp);
3575 silc_server_command_free(cmd);
3578 /* Server side of command UMODE. Client can use this command to set/unset
3579 user mode. Client actually cannot set itself to be as server/router
3580 operator so this can be used only to unset the modes. */
3582 SILC_SERVER_CMD_FUNC(umode)
3584 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3585 SilcServer server = cmd->server;
3586 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3588 unsigned char *tmp_mask;
3590 uint16 ident = silc_command_get_ident(cmd->payload);
3592 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3595 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 2, 2);
3597 /* Get the client's mode mask */
3598 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3600 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3601 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3604 SILC_GET32_MSB(mask, tmp_mask);
3610 if (mask & SILC_UMODE_SERVER_OPERATOR) {
3611 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR)) {
3612 /* Cannot operator mode */
3613 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3614 SILC_STATUS_ERR_PERM_DENIED);
3618 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
3619 /* Remove the server operator rights */
3620 client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3623 if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3624 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
3625 /* Cannot operator mode */
3626 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3627 SILC_STATUS_ERR_PERM_DENIED);
3631 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
3632 /* Remove the router operator rights */
3633 client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3636 if (mask & SILC_UMODE_GONE) {
3637 client->mode |= SILC_UMODE_GONE;
3639 if (client->mode & SILC_UMODE_GONE)
3640 /* Remove the gone status */
3641 client->mode &= ~SILC_UMODE_GONE;
3644 /* Send UMODE change to primary router */
3645 if (!server->standalone)
3646 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3647 client->id, client->mode);
3649 /* Send command reply to sender */
3650 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3651 SILC_STATUS_OK, ident, 1,
3653 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3654 packet->data, packet->len, FALSE);
3655 silc_buffer_free(packet);
3658 silc_server_command_free(cmd);
3661 /* Checks that client has rights to add or remove channel modes. If any
3662 of the checks fails FALSE is returned. */
3664 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3665 SilcChannelClientEntry client,
3668 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3669 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3671 /* Check whether has rights to change anything */
3672 if (!is_op && !is_fo)
3675 /* Check whether has rights to change everything */
3679 /* We know that client is channel operator, check that they are not
3680 changing anything that requires channel founder rights. Rest of the
3681 modes are available automatically for channel operator. */
3683 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3684 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3685 if (is_op && !is_fo)
3688 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3689 if (is_op && !is_fo)
3694 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3695 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE))
3696 if (is_op && !is_fo)
3699 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3700 if (is_op && !is_fo)
3705 if (mode & SILC_CHANNEL_MODE_CIPHER) {
3706 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER))
3707 if (is_op && !is_fo)
3710 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3711 if (is_op && !is_fo)
3716 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3717 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH))
3718 if (is_op && !is_fo)
3721 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3722 if (is_op && !is_fo)
3730 /* Server side command of CMODE. Changes channel mode */
3732 SILC_SERVER_CMD_FUNC(cmode)
3734 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3735 SilcServer server = cmd->server;
3736 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3737 SilcIDListData idata = (SilcIDListData)client;
3738 SilcChannelID *channel_id;
3739 SilcChannelEntry channel;
3740 SilcChannelClientEntry chl;
3741 SilcBuffer packet, cidp;
3742 unsigned char *tmp, *tmp_id, *tmp_mask;
3743 char *cipher = NULL, *hmac = NULL;
3744 uint32 mode_mask, tmp_len, tmp_len2;
3745 uint16 ident = silc_command_get_ident(cmd->payload);
3747 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 2, 7);
3749 /* Get Channel ID */
3750 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3752 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3753 SILC_STATUS_ERR_NO_CHANNEL_ID);
3756 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3758 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3759 SILC_STATUS_ERR_NO_CHANNEL_ID);
3763 /* Get the channel mode mask */
3764 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3766 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3767 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3770 SILC_GET32_MSB(mode_mask, tmp_mask);
3772 /* Get channel entry */
3773 channel = silc_idlist_find_channel_by_id(server->local_list,
3776 channel = silc_idlist_find_channel_by_id(server->global_list,
3779 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3780 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3785 /* Check whether this client is on the channel */
3786 if (!silc_server_client_on_channel(client, channel)) {
3787 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3788 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3792 /* Get entry to the channel user list */
3793 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
3795 /* Check that client has rights to change any requested channel modes */
3796 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3797 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3798 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3803 * Check the modes. Modes that requires nothing special operation are
3807 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3808 /* Channel uses private keys to protect traffic. Client(s) has set the
3809 key locally they want to use, server does not know that key. */
3810 /* Nothing interesting to do here */
3812 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3813 /* The mode is removed and we need to generate and distribute
3814 new channel key. Clients are not using private channel keys
3815 anymore after this. */
3817 /* Re-generate channel key */
3818 if (!silc_server_create_channel_key(server, channel, 0))
3821 /* Send the channel key. This sends it to our local clients and if
3822 we are normal server to our router as well. */
3823 silc_server_send_channel_key(server, NULL, channel,
3824 server->server_type == SILC_ROUTER ?
3825 FALSE : !server->standalone);
3827 cipher = channel->channel_key->cipher->name;
3828 hmac = (char *)silc_hmac_get_name(channel->hmac);
3832 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3833 /* User limit is set on channel */
3836 /* Get user limit */
3837 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3839 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3840 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3841 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3845 SILC_GET32_MSB(user_limit, tmp);
3846 channel->user_limit = user_limit;
3849 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3850 /* User limit mode is unset. Remove user limit */
3851 channel->user_limit = 0;
3854 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3855 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3856 /* Passphrase has been set to channel */
3858 /* Get the passphrase */
3859 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3861 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3862 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3866 /* Save the passphrase */
3867 channel->passphrase = strdup(tmp);
3870 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3871 /* Passphrase mode is unset. remove the passphrase */
3872 if (channel->passphrase) {
3873 silc_free(channel->passphrase);
3874 channel->passphrase = NULL;
3879 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3880 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3881 /* Cipher to use protect the traffic */
3882 SilcCipher newkey, oldkey;
3885 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3887 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3888 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3892 /* Delete old cipher and allocate the new one */
3893 if (!silc_cipher_alloc(cipher, &newkey)) {
3894 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3895 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3899 oldkey = channel->channel_key;
3900 channel->channel_key = newkey;
3902 /* Re-generate channel key */
3903 if (!silc_server_create_channel_key(server, channel, 0)) {
3904 /* We don't have new key, revert to old one */
3905 channel->channel_key = oldkey;
3909 /* Remove old channel key for good */
3910 silc_cipher_free(oldkey);
3912 /* Send the channel key. This sends it to our local clients and if
3913 we are normal server to our router as well. */
3914 silc_server_send_channel_key(server, NULL, channel,
3915 server->server_type == SILC_ROUTER ?
3916 FALSE : !server->standalone);
3919 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3920 /* Cipher mode is unset. Remove the cipher and revert back to
3922 SilcCipher newkey, oldkey;
3923 cipher = channel->cipher;
3925 /* Delete old cipher and allocate default one */
3926 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
3927 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3928 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3932 oldkey = channel->channel_key;
3933 channel->channel_key = newkey;
3935 /* Re-generate channel key */
3936 if (!silc_server_create_channel_key(server, channel, 0)) {
3937 /* We don't have new key, revert to old one */
3938 channel->channel_key = oldkey;
3942 /* Remove old channel key for good */
3943 silc_cipher_free(oldkey);
3945 /* Send the channel key. This sends it to our local clients and if
3946 we are normal server to our router as well. */
3947 silc_server_send_channel_key(server, NULL, channel,
3948 server->server_type == SILC_ROUTER ?
3949 FALSE : !server->standalone);
3953 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3954 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3955 /* HMAC to use protect the traffic */
3956 unsigned char hash[32];
3960 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3962 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3963 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3967 /* Delete old hmac and allocate the new one */
3968 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
3969 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3970 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3974 silc_hmac_free(channel->hmac);
3975 channel->hmac = newhmac;
3977 /* Set the HMAC key out of current channel key. The client must do
3979 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
3980 channel->key_len / 8, hash);
3981 silc_hmac_set_key(channel->hmac, hash,
3982 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3983 memset(hash, 0, sizeof(hash));
3986 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
3987 /* Hmac mode is unset. Remove the hmac and revert back to
3990 unsigned char hash[32];
3991 hmac = channel->hmac_name;
3993 /* Delete old hmac and allocate default one */
3994 silc_hmac_free(channel->hmac);
3995 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
3996 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3997 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4001 silc_hmac_free(channel->hmac);
4002 channel->hmac = newhmac;
4004 /* Set the HMAC key out of current channel key. The client must do
4006 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
4007 channel->key_len / 8,
4009 silc_hmac_set_key(channel->hmac, hash,
4010 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4011 memset(hash, 0, sizeof(hash));
4015 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4016 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4017 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4018 /* Set the founder authentication */
4019 SilcAuthPayload auth;
4021 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4023 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4024 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4028 auth = silc_auth_payload_parse(tmp, tmp_len);
4030 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4031 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4035 /* Save the public key */
4036 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
4037 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
4040 channel->founder_method = silc_auth_get_method(auth);
4042 if (channel->founder_method == SILC_AUTH_PASSWORD) {
4043 tmp = silc_auth_get_data(auth, &tmp_len);
4044 channel->founder_passwd =
4045 silc_calloc(tmp_len + 1, sizeof(*channel->founder_passwd));
4046 memcpy(channel->founder_passwd, tmp, tmp_len);
4047 channel->founder_passwd_len = tmp_len;
4049 /* Verify the payload before setting the mode */
4050 if (!silc_auth_verify(auth, channel->founder_method,
4051 channel->founder_key, 0, idata->hash,
4052 client->id, SILC_ID_CLIENT)) {
4053 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4054 SILC_STATUS_ERR_AUTH_FAILED);
4059 silc_auth_payload_free(auth);
4063 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4064 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4065 if (channel->founder_key)
4066 silc_pkcs_public_key_free(channel->founder_key);
4067 if (channel->founder_passwd) {
4068 silc_free(channel->founder_passwd);
4069 channel->founder_passwd = NULL;
4075 /* Finally, set the mode */
4076 channel->mode = mode_mask;
4078 /* Send CMODE_CHANGE notify */
4079 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4080 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4081 SILC_NOTIFY_TYPE_CMODE_CHANGE, 4,
4082 cidp->data, cidp->len,
4084 cipher, cipher ? strlen(cipher) : 0,
4085 hmac, hmac ? strlen(hmac) : 0);
4087 /* Set CMODE notify type to network */
4088 if (!server->standalone)
4089 silc_server_send_notify_cmode(server, server->router->connection,
4090 server->server_type == SILC_ROUTER ?
4091 TRUE : FALSE, channel,
4092 mode_mask, client->id, SILC_ID_CLIENT,
4095 /* Send command reply to sender */
4096 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4097 SILC_STATUS_OK, ident, 2,
4098 2, tmp_id, tmp_len2,
4100 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4101 packet->data, packet->len, FALSE);
4103 silc_buffer_free(packet);
4104 silc_free(channel_id);
4108 silc_server_command_free(cmd);
4111 /* Server side of CUMODE command. Changes client's mode on a channel. */
4113 SILC_SERVER_CMD_FUNC(cumode)
4115 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4116 SilcServer server = cmd->server;
4117 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4118 SilcIDListData idata = (SilcIDListData)client;
4119 SilcChannelID *channel_id;
4120 SilcClientID *client_id;
4121 SilcChannelEntry channel;
4122 SilcClientEntry target_client;
4123 SilcChannelClientEntry chl;
4124 SilcBuffer packet, idp;
4125 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4126 uint32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4128 uint16 ident = silc_command_get_ident(cmd->payload);
4130 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4132 /* Get Channel ID */
4133 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4135 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4136 SILC_STATUS_ERR_NO_CHANNEL_ID);
4139 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
4141 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4142 SILC_STATUS_ERR_NO_CHANNEL_ID);
4146 /* Get channel entry */
4147 channel = silc_idlist_find_channel_by_id(server->local_list,
4150 channel = silc_idlist_find_channel_by_id(server->global_list,
4153 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4154 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4159 /* Check whether sender is on the channel */
4160 if (!silc_server_client_on_channel(client, channel)) {
4161 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4162 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4166 /* Check that client has rights to change other's rights */
4167 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4168 sender_mask = chl->mode;
4170 /* Get the target client's channel mode mask */
4171 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4173 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4174 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4177 SILC_GET32_MSB(target_mask, tmp_mask);
4179 /* Get target Client ID */
4180 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4182 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4183 SILC_STATUS_ERR_NO_CLIENT_ID);
4186 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
4188 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4189 SILC_STATUS_ERR_NO_CLIENT_ID);
4193 /* Get target client's entry */
4194 target_client = silc_idlist_find_client_by_id(server->local_list,
4195 client_id, TRUE, NULL);
4196 if (!target_client) {
4197 target_client = silc_idlist_find_client_by_id(server->global_list,
4198 client_id, TRUE, NULL);
4201 if (target_client != client &&
4202 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4203 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4204 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4205 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4209 /* Check whether target client is on the channel */
4210 if (target_client != client) {
4211 if (!silc_server_client_on_channel(target_client, channel)) {
4212 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4213 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4217 /* Get entry to the channel user list */
4218 silc_hash_table_find(channel->user_list, target_client, NULL,
4226 /* If the target client is founder, no one else can change their mode
4228 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
4229 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4230 SILC_STATUS_ERR_NOT_YOU);
4234 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4235 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4236 /* The client tries to claim the founder rights. */
4237 unsigned char *tmp_auth;
4238 uint32 tmp_auth_len, auth_len;
4241 if (target_client != client) {
4242 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4243 SILC_STATUS_ERR_NOT_YOU);
4247 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4248 !channel->founder_key || !idata->public_key ||
4249 !silc_pkcs_public_key_compare(channel->founder_key,
4250 idata->public_key)) {
4251 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4252 SILC_STATUS_ERR_NOT_YOU);
4256 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4258 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4259 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4263 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4264 (void *)channel->founder_passwd : (void *)channel->founder_key);
4265 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4266 channel->founder_passwd_len : 0);
4268 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4269 channel->founder_method, auth, auth_len,
4270 idata->hash, client->id, SILC_ID_CLIENT)) {
4271 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4272 SILC_STATUS_ERR_AUTH_FAILED);
4276 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4280 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4281 if (target_client == client) {
4282 /* Remove channel founder rights from itself */
4283 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4286 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4287 SILC_STATUS_ERR_NOT_YOU);
4293 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4294 /* Promote to operator */
4295 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4296 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4297 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4298 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4299 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4303 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4307 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4308 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4309 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4310 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4311 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4315 /* Demote to normal user */
4316 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4321 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4322 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4324 /* Send notify to channel, notify only if mode was actually changed. */
4326 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4327 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4328 idp->data, idp->len,
4332 /* Set CUMODE notify type to network */
4333 if (!server->standalone)
4334 silc_server_send_notify_cumode(server, server->router->connection,
4335 server->server_type == SILC_ROUTER ?
4336 TRUE : FALSE, channel,
4337 target_mask, client->id,
4342 /* Send command reply to sender */
4343 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4344 SILC_STATUS_OK, ident, 3,
4346 3, tmp_ch_id, tmp_ch_len,
4347 4, tmp_id, tmp_len);
4348 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4349 packet->data, packet->len, FALSE);
4351 silc_buffer_free(packet);
4352 silc_free(channel_id);
4353 silc_free(client_id);
4354 silc_buffer_free(idp);
4357 silc_server_command_free(cmd);
4360 /* Server side of KICK command. Kicks client out of channel. */
4362 SILC_SERVER_CMD_FUNC(kick)
4364 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4365 SilcServer server = cmd->server;
4366 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4367 SilcClientEntry target_client;
4368 SilcChannelID *channel_id;
4369 SilcClientID *client_id;
4370 SilcChannelEntry channel;
4371 SilcChannelClientEntry chl;
4374 unsigned char *tmp, *comment;
4376 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4378 /* Get Channel ID */
4379 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4381 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4382 SILC_STATUS_ERR_NO_CHANNEL_ID);
4385 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
4387 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4388 SILC_STATUS_ERR_NO_CHANNEL_ID);
4392 /* Get channel entry */
4393 channel = silc_idlist_find_channel_by_id(server->local_list,
4396 channel = silc_idlist_find_channel_by_id(server->local_list,
4399 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4400 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4405 /* Check whether sender is on the channel */
4406 if (!silc_server_client_on_channel(client, channel)) {
4407 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4408 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4412 /* Check that the kicker is channel operator or channel founder */
4413 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4414 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4415 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4416 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4420 /* Get target Client ID */
4421 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4423 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4424 SILC_STATUS_ERR_NO_CLIENT_ID);
4427 client_id = silc_id_payload_parse_id(tmp, tmp_len);
4429 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4430 SILC_STATUS_ERR_NO_CLIENT_ID);
4434 /* Get target client's entry */
4435 target_client = silc_idlist_find_client_by_id(server->local_list,
4436 client_id, TRUE, NULL);
4437 if (!target_client) {
4438 target_client = silc_idlist_find_client_by_id(server->global_list,
4439 client_id, TRUE, NULL);
4442 /* Check that the target client is not channel founder. Channel founder
4443 cannot be kicked from the channel. */
4444 silc_hash_table_find(channel->user_list, target_client, NULL, (void *)&chl);
4445 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4446 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4447 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4451 /* Check whether target client is on the channel */
4452 if (!silc_server_client_on_channel(target_client, channel)) {
4453 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4454 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4460 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4464 /* Send command reply to sender */
4465 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4468 /* Send KICKED notify to local clients on the channel */
4469 idp = silc_id_payload_encode(target_client->id, SILC_ID_CLIENT);
4470 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4471 SILC_NOTIFY_TYPE_KICKED,
4473 idp->data, idp->len,
4474 comment, comment ? strlen(comment) : 0);
4475 silc_buffer_free(idp);
4477 /* Remove the client from the channel. If the channel does not exist
4478 after removing the client then the client kicked itself off the channel
4479 and we don't have to send anything after that. */
4480 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4481 target_client, FALSE))
4484 /* Send KICKED notify to primary route */
4485 if (!server->standalone)
4486 silc_server_send_notify_kicked(server, server->router->connection,
4487 server->server_type == SILC_ROUTER ?
4488 TRUE : FALSE, channel,
4489 target_client->id, comment);
4491 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4492 /* Re-generate channel key */
4493 if (!silc_server_create_channel_key(server, channel, 0))
4496 /* Send the channel key to the channel. The key of course is not sent
4497 to the client who was kicked off the channel. */
4498 silc_server_send_channel_key(server, target_client->connection, channel,
4499 server->server_type == SILC_ROUTER ?
4500 FALSE : !server->standalone);
4504 silc_server_command_free(cmd);
4507 /* Server side of OPER command. Client uses this comand to obtain server
4508 operator privileges to this server/router. */
4510 SILC_SERVER_CMD_FUNC(oper)
4512 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4513 SilcServer server = cmd->server;
4514 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4515 unsigned char *username, *auth;
4517 SilcServerConfigSectionAdminConnection *admin;
4518 SilcIDListData idata = (SilcIDListData)client;
4520 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4522 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4525 /* Get the username */
4526 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4528 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4529 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4533 /* Get the admin configuration */
4534 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4535 username, client->nickname);
4537 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4538 username, client->nickname);
4540 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4541 SILC_STATUS_ERR_AUTH_FAILED);
4546 /* Get the authentication payload */
4547 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4549 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4550 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4554 /* Verify the authentication data */
4555 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4556 admin->auth_data, admin->auth_data_len,
4557 idata->hash, client->id, SILC_ID_CLIENT)) {
4558 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4559 SILC_STATUS_ERR_AUTH_FAILED);
4563 /* Client is now server operator */
4564 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4566 /* Send UMODE change to primary router */
4567 if (!server->standalone)
4568 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4569 client->id, client->mode);
4571 /* Send reply to the sender */
4572 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4576 silc_server_command_free(cmd);
4579 /* Server side of SILCOPER command. Client uses this comand to obtain router
4580 operator privileges to this router. */
4582 SILC_SERVER_CMD_FUNC(silcoper)
4584 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4585 SilcServer server = cmd->server;
4586 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4587 unsigned char *username, *auth;
4589 SilcServerConfigSectionAdminConnection *admin;
4590 SilcIDListData idata = (SilcIDListData)client;
4592 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4594 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4597 if (server->server_type != SILC_ROUTER) {
4598 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4599 SILC_STATUS_ERR_AUTH_FAILED);
4603 /* Get the username */
4604 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4606 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4607 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4611 /* Get the admin configuration */
4612 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4613 username, client->nickname);
4615 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4616 username, client->nickname);
4618 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4619 SILC_STATUS_ERR_AUTH_FAILED);
4624 /* Get the authentication payload */
4625 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4627 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4628 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4632 /* Verify the authentication data */
4633 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4634 admin->auth_data, admin->auth_data_len,
4635 idata->hash, client->id, SILC_ID_CLIENT)) {
4636 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4637 SILC_STATUS_ERR_AUTH_FAILED);
4641 /* Client is now router operator */
4642 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4644 /* Send UMODE change to primary router */
4645 if (!server->standalone)
4646 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4647 client->id, client->mode);
4649 /* Send reply to the sender */
4650 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4654 silc_server_command_free(cmd);
4657 /* Server side command of CONNECT. Connects us to the specified remote
4658 server or router. */
4660 SILC_SERVER_CMD_FUNC(connect)
4662 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4663 SilcServer server = cmd->server;
4664 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4665 unsigned char *tmp, *host;
4667 uint32 port = SILC_PORT;
4669 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CONNECT, cmd, 1, 2);
4671 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4674 /* Check whether client has the permissions. */
4675 if (client->mode == SILC_UMODE_NONE) {
4676 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4677 SILC_STATUS_ERR_NO_SERVER_PRIV);
4681 if (server->server_type == SILC_ROUTER &&
4682 client->mode & SILC_UMODE_SERVER_OPERATOR) {
4683 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4684 SILC_STATUS_ERR_NO_ROUTER_PRIV);
4688 /* Get the remote server */
4689 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4691 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4692 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4697 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4699 SILC_GET32_MSB(port, tmp);
4701 /* Create the connection. It is done with timeout and is async. */
4702 silc_server_create_connection(server, host, port);
4704 /* Send reply to the sender */
4705 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4709 silc_server_command_free(cmd);
4712 /* Server side of command BAN. This is used to manage the ban list of the
4713 channel. To add clients and remove clients from the ban list. */
4715 SILC_SERVER_CMD_FUNC(ban)
4717 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4718 SilcServer server = cmd->server;
4719 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4721 SilcChannelEntry channel;
4722 SilcChannelClientEntry chl;
4723 SilcChannelID *channel_id = NULL;
4724 unsigned char *id, *add, *del;
4725 uint32 id_len, tmp_len;
4726 uint16 ident = silc_command_get_ident(cmd->payload);
4728 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4731 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4733 /* Get Channel ID */
4734 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4736 channel_id = silc_id_payload_parse_id(id, id_len);
4738 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4739 SILC_STATUS_ERR_NO_CHANNEL_ID);
4744 /* Get channel entry. The server must know about the channel since the
4745 client is expected to be on the channel. */
4746 channel = silc_idlist_find_channel_by_id(server->local_list,
4749 channel = silc_idlist_find_channel_by_id(server->global_list,
4752 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4753 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4758 /* Check whether this client is on the channel */
4759 if (!silc_server_client_on_channel(client, channel)) {
4760 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4761 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4765 /* Get entry to the channel user list */
4766 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4768 /* The client must be at least channel operator. */
4769 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4770 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4771 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4775 /* Get the new ban and add it to the ban list */
4776 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4778 if (!channel->ban_list)
4779 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4781 channel->ban_list = silc_realloc(channel->ban_list,
4782 sizeof(*channel->ban_list) *
4784 strlen(channel->ban_list) + 2));
4785 if (add[tmp_len - 1] == ',')
4786 add[tmp_len - 1] = '\0';
4788 strncat(channel->ban_list, add, tmp_len);
4789 strncat(channel->ban_list, ",", 1);
4792 /* Get the ban to be removed and remove it from the list */
4793 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4794 if (del && channel->ban_list) {
4795 char *start, *end, *n;
4797 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4798 silc_free(channel->ban_list);
4799 channel->ban_list = NULL;
4801 start = strstr(channel->ban_list, del);
4802 if (start && strlen(start) >= tmp_len) {
4803 end = start + tmp_len;
4804 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4805 strncat(n, channel->ban_list, start - channel->ban_list);
4806 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4808 silc_free(channel->ban_list);
4809 channel->ban_list = n;
4814 /* Send the BAN notify type to our primary router. */
4815 if (!server->standalone && (add || del))
4816 silc_server_send_notify_ban(server, server->router->connection,
4817 server->server_type == SILC_ROUTER ?
4818 TRUE : FALSE, channel, add, del);
4820 /* Send the reply back to the client */
4821 if (channel->ban_list)
4823 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4824 SILC_STATUS_OK, ident, 2,
4826 3, channel->ban_list,
4827 strlen(channel->ban_list) - 1);
4830 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4831 SILC_STATUS_OK, ident, 1,
4834 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4835 packet->data, packet->len, FALSE);
4837 silc_buffer_free(packet);
4840 silc_free(channel_id);
4841 silc_server_command_free(cmd);
4844 /* Server side command of CLOSE. Closes connection to a specified server. */
4846 SILC_SERVER_CMD_FUNC(close)
4848 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4849 SilcServer server = cmd->server;
4850 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4851 SilcServerEntry server_entry;
4852 SilcSocketConnection sock;
4855 unsigned char *name;
4856 uint32 port = SILC_PORT;
4858 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CLOSE, cmd, 1, 2);
4860 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4863 /* Check whether client has the permissions. */
4864 if (client->mode == SILC_UMODE_NONE) {
4865 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4866 SILC_STATUS_ERR_NO_SERVER_PRIV);
4870 /* Get the remote server */
4871 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4873 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4874 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4879 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4881 SILC_GET32_MSB(port, tmp);
4883 server_entry = silc_idlist_find_server_by_conn(server->local_list,
4884 name, port, FALSE, NULL);
4886 server_entry = silc_idlist_find_server_by_conn(server->global_list,
4887 name, port, FALSE, NULL);
4888 if (!server_entry) {
4889 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4890 SILC_STATUS_ERR_NO_SERVER_ID);
4894 /* Send reply to the sender */
4895 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4898 /* Close the connection to the server */
4899 sock = (SilcSocketConnection)server_entry->connection;
4901 /* If we shutdown primary router connection manually then don't trigger
4902 any reconnect or backup router connections, by setting the router
4904 if (server->router == server_entry) {
4905 server->id_entry->router = NULL;
4906 server->router = NULL;
4907 server->standalone = TRUE;
4909 silc_server_free_sock_user_data(server, sock);
4910 silc_server_close_connection(server, sock);
4913 silc_server_command_free(cmd);
4916 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4917 active connections. */
4919 SILC_SERVER_CMD_FUNC(shutdown)
4921 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4922 SilcServer server = cmd->server;
4923 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4925 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4927 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4930 /* Check whether client has the permission. */
4931 if (client->mode == SILC_UMODE_NONE) {
4932 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4933 SILC_STATUS_ERR_NO_SERVER_PRIV);
4937 /* Send reply to the sender */
4938 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4941 /* Then, gracefully, or not, bring the server down. */
4942 silc_server_stop(server);
4946 silc_server_command_free(cmd);
4949 /* Server side command of LEAVE. Removes client from a channel. */
4951 SILC_SERVER_CMD_FUNC(leave)
4953 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4954 SilcServer server = cmd->server;
4955 SilcSocketConnection sock = cmd->sock;
4956 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4957 SilcChannelID *id = NULL;
4958 SilcChannelEntry channel;
4962 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4964 /* Get Channel ID */
4965 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4967 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4968 SILC_STATUS_ERR_NO_CHANNEL_ID);
4971 id = silc_id_payload_parse_id(tmp, len);
4973 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4974 SILC_STATUS_ERR_NO_CHANNEL_ID);
4978 /* Get channel entry */
4979 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4981 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4983 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4984 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4989 /* Check whether this client is on the channel */
4990 if (!silc_server_client_on_channel(id_entry, channel)) {
4991 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4992 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4996 /* Notify routers that they should remove this client from their list
4997 of clients on the channel. Send LEAVE notify type. */
4998 if (!server->standalone)
4999 silc_server_send_notify_leave(server, server->router->connection,
5000 server->server_type == SILC_ROUTER ?
5001 TRUE : FALSE, channel, id_entry->id);
5003 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5006 /* Remove client from channel */
5007 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5009 /* If the channel does not exist anymore we won't send anything */
5012 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5013 /* Re-generate channel key */
5014 if (!silc_server_create_channel_key(server, channel, 0))
5017 /* Send the channel key */
5018 silc_server_send_channel_key(server, NULL, channel,
5019 server->server_type == SILC_ROUTER ?
5020 FALSE : !server->standalone);
5025 silc_server_command_free(cmd);
5028 /* Server side of command USERS. Resolves clients and their USERS currently
5029 joined on the requested channel. The list of Client ID's and their modes
5030 on the channel is sent back. */
5032 SILC_SERVER_CMD_FUNC(users)
5034 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5035 SilcServer server = cmd->server;
5036 SilcChannelEntry channel;
5037 SilcChannelID *id = NULL;
5038 SilcBuffer packet, idp;
5039 unsigned char *channel_id;
5040 uint32 channel_id_len;
5041 SilcBuffer client_id_list;
5042 SilcBuffer client_mode_list;
5043 unsigned char lc[4];
5044 uint32 list_count = 0;
5045 uint16 ident = silc_command_get_ident(cmd->payload);
5048 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5050 /* Get Channel ID */
5051 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5053 /* Get channel name */
5054 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5056 if (!channel_id && !channel_name) {
5057 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5058 SILC_STATUS_ERR_NO_CHANNEL_ID);
5063 id = silc_id_payload_parse_id(channel_id, channel_id_len);
5065 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5066 SILC_STATUS_ERR_NO_CHANNEL_ID);
5071 /* If we are server and we don't know about this channel we will send
5072 the command to our router. If we know about the channel then we also
5073 have the list of users already. */
5075 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5077 channel = silc_idlist_find_channel_by_name(server->local_list,
5078 channel_name, NULL);
5080 if (!channel || channel->disabled) {
5081 if (server->server_type != SILC_ROUTER && !server->standalone &&
5085 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5086 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5088 /* Send USERS command */
5089 silc_server_packet_send(server, server->router->connection,
5090 SILC_PACKET_COMMAND, cmd->packet->flags,
5091 tmpbuf->data, tmpbuf->len, TRUE);
5093 /* Reprocess this packet after received reply */
5094 silc_server_command_pending(server, SILC_COMMAND_USERS,
5095 silc_command_get_ident(cmd->payload),
5096 silc_server_command_destructor,
5097 silc_server_command_users,
5098 silc_server_command_dup(cmd));
5099 cmd->pending = TRUE;
5100 silc_command_set_ident(cmd->payload, ident);
5102 silc_buffer_free(tmpbuf);
5107 /* Check the global list as well. */
5109 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5111 channel = silc_idlist_find_channel_by_name(server->global_list,
5112 channel_name, NULL);
5114 /* Channel really does not exist */
5115 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5116 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5121 /* If the channel is private or secret do not send anything, unless the
5122 user requesting this command is on the channel. */
5123 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5124 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5125 && !silc_server_client_on_channel(cmd->sock->user_data, channel)) {
5126 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5127 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5132 (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
5133 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5134 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5139 /* Get the users list */
5140 silc_server_get_users_on_channel(server, channel, &client_id_list,
5141 &client_mode_list, &list_count);
5144 SILC_PUT32_MSB(list_count, lc);
5147 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5148 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5149 SILC_STATUS_OK, ident, 4,
5150 2, idp->data, idp->len,
5152 4, client_id_list->data,
5153 client_id_list->len,
5154 5, client_mode_list->data,
5155 client_mode_list->len);
5156 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5157 packet->data, packet->len, FALSE);
5159 silc_buffer_free(idp);
5160 silc_buffer_free(packet);
5161 silc_buffer_free(client_id_list);
5162 silc_buffer_free(client_mode_list);
5166 silc_server_command_free(cmd);
5169 /* Server side of command GETKEY. This fetches the client's public key
5170 from the server where to the client is connected. */
5172 SILC_SERVER_CMD_FUNC(getkey)
5174 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5175 SilcServer server = cmd->server;
5177 SilcClientEntry client;
5178 SilcServerEntry server_entry;
5179 SilcClientID *client_id = NULL;
5180 SilcServerID *server_id = NULL;
5181 SilcIDPayload idp = NULL;
5182 uint16 ident = silc_command_get_ident(cmd->payload);
5183 unsigned char *tmp, *pkdata;
5184 uint32 tmp_len, pklen;
5185 SilcBuffer pk = NULL;
5188 SILC_LOG_DEBUG(("Start"));
5190 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5192 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5193 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5196 idp = silc_id_payload_parse_data(tmp, tmp_len);
5198 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5199 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5203 id_type = silc_id_payload_get_type(idp);
5204 if (id_type == SILC_ID_CLIENT) {
5205 client_id = silc_id_payload_get_id(idp);
5207 /* If the client is not found from local list there is no chance it
5208 would be locally connected client so send the command further. */
5209 client = silc_idlist_find_client_by_id(server->local_list,
5210 client_id, TRUE, NULL);
5212 client = silc_idlist_find_client_by_id(server->global_list,
5213 client_id, TRUE, NULL);
5215 if ((!client && !cmd->pending && !server->standalone) ||
5216 (client && !client->connection && !cmd->pending) ||
5217 (client && !client->data.public_key && !cmd->pending)) {
5220 SilcSocketConnection dest_sock;
5222 dest_sock = silc_server_get_client_route(server, NULL, 0,
5227 old_ident = silc_command_get_ident(cmd->payload);
5228 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5229 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5231 silc_server_packet_send(server, dest_sock,
5232 SILC_PACKET_COMMAND, cmd->packet->flags,
5233 tmpbuf->data, tmpbuf->len, TRUE);
5235 /* Reprocess this packet after received reply from router */
5236 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5237 silc_command_get_ident(cmd->payload),
5238 silc_server_command_destructor,
5239 silc_server_command_getkey,
5240 silc_server_command_dup(cmd));
5241 cmd->pending = TRUE;
5243 silc_command_set_ident(cmd->payload, old_ident);
5244 silc_buffer_free(tmpbuf);
5249 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5250 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5254 /* The client is locally connected, just get the public key and
5255 send it back. If they key does not exist then do not send it,
5256 send just OK reply */
5257 if (!client->data.public_key) {
5261 tmp = silc_pkcs_public_key_encode(client->data.public_key, &tmp_len);
5262 pk = silc_buffer_alloc(4 + tmp_len);
5263 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5264 silc_buffer_format(pk,
5265 SILC_STR_UI_SHORT(tmp_len),
5266 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5267 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5273 } else if (id_type == SILC_ID_SERVER) {
5274 server_id = silc_id_payload_get_id(idp);
5276 /* If the server is not found from local list there is no chance it
5277 would be locally connected server so send the command further. */
5278 server_entry = silc_idlist_find_server_by_id(server->local_list,
5279 server_id, TRUE, NULL);
5281 server_entry = silc_idlist_find_server_by_id(server->global_list,
5282 server_id, TRUE, NULL);
5284 if (server_entry != server->id_entry &&
5285 ((!server_entry && !cmd->pending && !server->standalone) ||
5286 (server_entry && !server_entry->connection && !cmd->pending &&
5287 !server->standalone) ||
5288 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5289 !server->standalone))) {
5293 old_ident = silc_command_get_ident(cmd->payload);
5294 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5295 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5297 silc_server_packet_send(server, server->router->connection,
5298 SILC_PACKET_COMMAND, cmd->packet->flags,
5299 tmpbuf->data, tmpbuf->len, TRUE);
5301 /* Reprocess this packet after received reply from router */
5302 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5303 silc_command_get_ident(cmd->payload),
5304 silc_server_command_destructor,
5305 silc_server_command_getkey,
5306 silc_server_command_dup(cmd));
5307 cmd->pending = TRUE;
5309 silc_command_set_ident(cmd->payload, old_ident);
5310 silc_buffer_free(tmpbuf);
5314 if (!server_entry) {
5315 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5316 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5320 /* If they key does not exist then do not send it, send just OK reply */
5321 if (!server_entry->data.public_key) {
5325 tmp = silc_pkcs_public_key_encode(server_entry->data.public_key,
5327 pk = silc_buffer_alloc(4 + tmp_len);
5328 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5329 silc_buffer_format(pk,
5330 SILC_STR_UI_SHORT(tmp_len),
5331 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5332 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5342 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5343 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5344 SILC_STATUS_OK, ident,
5348 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5349 packet->data, packet->len, FALSE);
5350 silc_buffer_free(packet);
5353 silc_buffer_free(pk);
5357 silc_id_payload_free(idp);
5358 silc_free(client_id);
5359 silc_free(server_id);
5360 silc_server_command_free(cmd);