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;
1948 /* Server side of command NICK. Sets nickname for user. Setting
1949 nickname causes generation of a new client ID for the client. The
1950 new client ID is sent to the client after changing the nickname. */
1952 SILC_SERVER_CMD_FUNC(nick)
1954 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1955 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1956 SilcServer server = cmd->server;
1957 SilcBuffer packet, nidp, oidp = NULL;
1958 SilcClientID *new_id;
1960 uint16 ident = silc_command_get_ident(cmd->payload);
1963 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1966 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
1968 /* Check nickname */
1969 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1970 if (silc_server_command_bad_chars(nick) == TRUE) {
1971 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1972 SILC_STATUS_ERR_BAD_NICKNAME);
1976 if (strlen(nick) > 128)
1979 /* Check for same nickname */
1980 if (!strcmp(client->nickname, nick)) {
1981 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1985 /* Create new Client ID */
1986 while (!silc_id_create_client_id(cmd->server, cmd->server->id,
1988 cmd->server->md5hash, nick,
1991 snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
1994 /* Send notify about nickname change to our router. We send the new
1995 ID and ask to replace it with the old one. If we are router the
1996 packet is broadcasted. Send NICK_CHANGE notify. */
1997 if (!server->standalone)
1998 silc_server_send_notify_nick_change(server, server->router->connection,
1999 server->server_type == SILC_SERVER ?
2000 FALSE : TRUE, client->id,
2003 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2005 /* Remove old cache entry */
2006 silc_idcache_del_by_context(server->local_list->clients, client);
2009 silc_free(client->id);
2011 /* Save the nickname as this client is our local client */
2012 silc_free(client->nickname);
2014 client->nickname = strdup(nick);
2015 client->id = new_id;
2017 /* Update client cache */
2018 silc_idcache_add(server->local_list->clients, client->nickname,
2019 client->id, (void *)client, FALSE);
2021 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2023 /* Send NICK_CHANGE notify to the client's channels */
2024 silc_server_send_notify_on_channels(server, NULL, client,
2025 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
2026 oidp->data, oidp->len,
2027 nidp->data, nidp->len);
2030 /* Send the new Client ID as reply command back to client */
2031 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
2032 SILC_STATUS_OK, ident, 1,
2033 2, nidp->data, nidp->len);
2034 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2035 0, packet->data, packet->len, FALSE);
2037 silc_buffer_free(packet);
2038 silc_buffer_free(nidp);
2040 silc_buffer_free(oidp);
2043 silc_server_command_free(cmd);
2046 /* Sends the LIST command reply */
2049 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2050 SilcChannelEntry *lch,
2052 SilcChannelEntry *gch,
2056 SilcBuffer packet, idp;
2057 SilcChannelEntry entry;
2058 SilcCommandStatus status;
2059 uint16 ident = silc_command_get_ident(cmd->payload);
2061 unsigned char usercount[4];
2064 for (i = 0; i < lch_count; i++)
2065 if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2067 for (i = 0; i < gch_count; i++)
2068 if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2071 status = SILC_STATUS_OK;
2072 if ((lch_count + gch_count) > 1)
2073 status = SILC_STATUS_LIST_START;
2076 for (i = 0; i < lch_count; i++) {
2083 status = SILC_STATUS_LIST_ITEM;
2085 if (lch_count > 1 && i == lch_count - 1 && !gch_count)
2086 status = SILC_STATUS_LIST_END;
2088 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2090 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2091 topic = "*private*";
2092 memset(usercount, 0, sizeof(usercount));
2094 topic = entry->topic;
2095 users = silc_hash_table_count(entry->user_list);
2096 SILC_PUT32_MSB(users, usercount);
2099 /* Send the reply */
2102 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2104 2, idp->data, idp->len,
2105 3, entry->channel_name,
2106 strlen(entry->channel_name),
2107 4, topic, strlen(topic),
2111 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2113 2, idp->data, idp->len,
2114 3, entry->channel_name,
2115 strlen(entry->channel_name),
2117 silc_server_packet_send(cmd->server, cmd->sock,
2118 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2119 packet->len, FALSE);
2120 silc_buffer_free(packet);
2121 silc_buffer_free(idp);
2124 status = i ? SILC_STATUS_LIST_ITEM : SILC_STATUS_OK;
2127 for (i = 0; i < gch_count; i++) {
2134 status = SILC_STATUS_LIST_ITEM;
2136 if (gch_count > 1 && i == lch_count - 1)
2137 status = SILC_STATUS_LIST_END;
2139 idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2141 if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2142 topic = "*private*";
2143 memset(usercount, 0, sizeof(usercount));
2145 topic = entry->topic;
2146 users = silc_hash_table_count(entry->user_list);
2147 SILC_PUT32_MSB(users, usercount);
2150 /* Send the reply */
2153 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2155 2, idp->data, idp->len,
2156 3, entry->channel_name,
2157 strlen(entry->channel_name),
2158 4, topic, strlen(topic),
2162 silc_command_reply_payload_encode_va(SILC_COMMAND_LIST,
2164 2, idp->data, idp->len,
2165 3, entry->channel_name,
2166 strlen(entry->channel_name),
2168 silc_server_packet_send(cmd->server, cmd->sock,
2169 SILC_PACKET_COMMAND_REPLY, 0, packet->data,
2170 packet->len, FALSE);
2171 silc_buffer_free(packet);
2172 silc_buffer_free(idp);
2176 /* Server side of LIST command. This lists the channel of the requested
2177 server. Secret channels are not listed. */
2179 SILC_SERVER_CMD_FUNC(list)
2181 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2182 SilcServer server = cmd->server;
2183 SilcChannelID *channel_id = NULL;
2186 SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2187 uint32 lch_count = 0, gch_count = 0;
2189 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2191 /* If we are normal server, send the command to router, since we
2192 want to know all channels in the network. */
2193 if (!cmd->pending && server->server_type == SILC_SERVER &&
2194 !server->standalone) {
2198 old_ident = silc_command_get_ident(cmd->payload);
2199 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2200 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2201 silc_server_packet_send(server, server->router->connection,
2202 SILC_PACKET_COMMAND, cmd->packet->flags,
2203 tmpbuf->data, tmpbuf->len, TRUE);
2205 /* Reprocess this packet after received reply from router */
2206 silc_server_command_pending(server, SILC_COMMAND_LIST,
2207 silc_command_get_ident(cmd->payload),
2208 silc_server_command_destructor,
2209 silc_server_command_list,
2210 silc_server_command_dup(cmd));
2211 cmd->pending = TRUE;
2212 silc_command_set_ident(cmd->payload, old_ident);
2213 silc_buffer_free(tmpbuf);
2217 /* Get Channel ID */
2218 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2220 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2222 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2223 SILC_STATUS_ERR_NO_CHANNEL_ID);
2228 /* Get the channels from local list */
2229 lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2232 /* Get the channels from global list */
2233 gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2236 /* Send the reply */
2237 silc_server_command_list_send_reply(cmd, lchannels, lch_count,
2238 gchannels, gch_count);
2241 silc_server_command_free(cmd);
2244 /* Server side of TOPIC command. Sets topic for channel and/or returns
2245 current topic to client. */
2247 SILC_SERVER_CMD_FUNC(topic)
2249 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2250 SilcServer server = cmd->server;
2251 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2252 SilcChannelID *channel_id;
2253 SilcChannelEntry channel;
2254 SilcChannelClientEntry chl;
2255 SilcBuffer packet, idp;
2257 uint32 argc, tmp_len;
2258 uint16 ident = silc_command_get_ident(cmd->payload);
2260 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2262 argc = silc_argument_get_arg_num(cmd->args);
2264 /* Get Channel ID */
2265 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2267 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2268 SILC_STATUS_ERR_NO_CHANNEL_ID);
2271 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2273 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2274 SILC_STATUS_ERR_NO_CHANNEL_ID);
2278 /* Check whether the channel exists */
2279 channel = silc_idlist_find_channel_by_id(server->local_list,
2282 channel = silc_idlist_find_channel_by_id(server->global_list,
2285 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2286 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2293 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2295 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2296 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2300 if (strlen(tmp) > 256) {
2301 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2302 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2306 /* See whether the client is on channel and has rights to change topic */
2307 if (!silc_hash_table_find(channel->user_list, client, NULL,
2309 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2310 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2314 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2315 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2316 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2317 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2322 /* Set the topic for channel */
2323 silc_free(channel->topic);
2324 channel->topic = strdup(tmp);
2326 /* Send TOPIC_SET notify type to the network */
2327 if (!server->standalone)
2328 silc_server_send_notify_topic_set(server, server->router->connection,
2329 server->server_type == SILC_ROUTER ?
2330 TRUE : FALSE, channel, client->id,
2333 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2335 /* Send notify about topic change to all clients on the channel */
2336 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2337 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2338 idp->data, idp->len,
2339 channel->topic, strlen(channel->topic));
2340 silc_buffer_free(idp);
2343 /* Send the topic to client as reply packet */
2344 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2346 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2347 SILC_STATUS_OK, ident, 2,
2348 2, idp->data, idp->len,
2350 strlen(channel->topic));
2352 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
2353 SILC_STATUS_OK, ident, 1,
2354 2, idp->data, idp->len);
2355 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2356 0, packet->data, packet->len, FALSE);
2358 silc_buffer_free(packet);
2359 silc_buffer_free(idp);
2360 silc_free(channel_id);
2363 silc_server_command_free(cmd);
2366 /* Server side of INVITE command. Invites some client to join some channel.
2367 This command is also used to manage the invite list of the channel. */
2369 SILC_SERVER_CMD_FUNC(invite)
2371 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2372 SilcServer server = cmd->server;
2373 SilcSocketConnection sock = cmd->sock, dest_sock;
2374 SilcChannelClientEntry chl;
2375 SilcClientEntry sender, dest;
2376 SilcClientID *dest_id = NULL;
2377 SilcChannelEntry channel;
2378 SilcChannelID *channel_id = NULL;
2379 SilcIDListData idata;
2380 SilcBuffer idp, idp2, packet;
2381 unsigned char *tmp, *add, *del;
2383 uint16 ident = silc_command_get_ident(cmd->payload);
2385 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2387 /* Get Channel ID */
2388 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2390 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2391 SILC_STATUS_ERR_NO_CHANNEL_ID);
2394 channel_id = silc_id_payload_parse_id(tmp, len);
2396 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2397 SILC_STATUS_ERR_NO_CHANNEL_ID);
2401 /* Get the channel entry */
2402 channel = silc_idlist_find_channel_by_id(server->local_list,
2405 channel = silc_idlist_find_channel_by_id(server->global_list,
2408 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2409 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2414 /* Check whether the sender of this command is on the channel. */
2415 sender = (SilcClientEntry)sock->user_data;
2416 if (!silc_server_client_on_channel(sender, channel)) {
2417 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2418 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2422 /* Check whether the channel is invite-only channel. If yes then the
2423 sender of this command must be at least channel operator. */
2424 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2425 silc_hash_table_find(channel->user_list, sender, NULL, (void *)&chl);
2426 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2427 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2428 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2433 /* Get destination client ID */
2434 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2438 dest_id = silc_id_payload_parse_id(tmp, len);
2440 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2441 SILC_STATUS_ERR_NO_CLIENT_ID);
2445 /* Get the client entry */
2446 dest = silc_server_get_client_resolve(server, dest_id);
2448 if (server->server_type != SILC_SERVER) {
2449 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2450 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2454 /* The client info is being resolved. Reprocess this packet after
2455 receiving the reply to the query. */
2456 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
2458 silc_server_command_destructor,
2459 silc_server_command_invite,
2460 silc_server_command_dup(cmd));
2461 cmd->pending = TRUE;
2462 silc_free(channel_id);
2467 /* Check whether the requested client is already on the channel. */
2468 if (silc_server_client_on_channel(dest, channel)) {
2469 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2470 SILC_STATUS_ERR_USER_ON_CHANNEL);
2474 /* Get route to the client */
2475 dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2477 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2478 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2482 memset(invite, 0, sizeof(invite));
2483 strncat(invite, dest->nickname, strlen(dest->nickname));
2484 strncat(invite, "!", 1);
2485 strncat(invite, dest->username, strlen(dest->username));
2486 if (!strchr(dest->username, '@')) {
2487 strncat(invite, "@", 1);
2488 strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2491 len = strlen(invite);
2492 if (!channel->invite_list)
2493 channel->invite_list = silc_calloc(len + 2,
2494 sizeof(*channel->invite_list));
2496 channel->invite_list = silc_realloc(channel->invite_list,
2497 sizeof(*channel->invite_list) *
2499 strlen(channel->invite_list) + 2));
2500 strncat(channel->invite_list, invite, len);
2501 strncat(channel->invite_list, ",", 1);
2503 /* Send notify to the client that is invited to the channel */
2504 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2505 idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2506 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
2508 SILC_NOTIFY_TYPE_INVITE, 3,
2509 idp->data, idp->len,
2510 channel->channel_name,
2511 strlen(channel->channel_name),
2512 idp2->data, idp2->len);
2513 silc_buffer_free(idp);
2514 silc_buffer_free(idp2);
2517 /* Add the client to the invite list of the channel */
2518 add = silc_argument_get_arg_type(cmd->args, 3, &len);
2520 if (!channel->invite_list)
2521 channel->invite_list = silc_calloc(len + 2,
2522 sizeof(*channel->invite_list));
2524 channel->invite_list = silc_realloc(channel->invite_list,
2525 sizeof(*channel->invite_list) *
2527 strlen(channel->invite_list) + 2));
2528 if (add[len - 1] == ',')
2529 add[len - 1] = '\0';
2531 strncat(channel->invite_list, add, len);
2532 strncat(channel->invite_list, ",", 1);
2535 /* Get the invite to be removed and remove it from the list */
2536 del = silc_argument_get_arg_type(cmd->args, 4, &len);
2537 if (del && channel->invite_list) {
2538 char *start, *end, *n;
2540 if (!strncmp(channel->invite_list, del,
2541 strlen(channel->invite_list) - 1)) {
2542 silc_free(channel->invite_list);
2543 channel->invite_list = NULL;
2545 start = strstr(channel->invite_list, del);
2546 if (start && strlen(start) >= len) {
2548 n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2549 strncat(n, channel->invite_list, start - channel->invite_list);
2550 strncat(n, end + 1, ((channel->invite_list +
2551 strlen(channel->invite_list)) - end) - 1);
2552 silc_free(channel->invite_list);
2553 channel->invite_list = n;
2558 /* Send notify to the primary router */
2559 if (!server->standalone)
2560 silc_server_send_notify_invite(server, server->router->connection,
2561 server->server_type == SILC_ROUTER ?
2562 TRUE : FALSE, channel,
2563 sender->id, add, del);
2565 /* Send command reply */
2566 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2570 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2571 SILC_STATUS_OK, ident, 2,
2573 3, channel->invite_list,
2574 channel->invite_list ?
2575 strlen(channel->invite_list) : 0);
2578 silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2579 SILC_STATUS_OK, ident, 1,
2581 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2582 packet->data, packet->len, FALSE);
2583 silc_buffer_free(packet);
2587 silc_free(channel_id);
2588 silc_server_command_free(cmd);
2593 SilcSocketConnection sock;
2597 /* Quits connection to client. This gets called if client won't
2598 close the connection even when it has issued QUIT command. */
2600 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2602 QuitInternal q = (QuitInternal)context;
2604 /* Free all client specific data, such as client entry and entires
2605 on channels this client may be on. */
2606 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2608 q->sock->user_data = NULL;
2610 /* Close the connection on our side */
2611 silc_server_close_connection(q->server, q->sock);
2613 silc_free(q->signoff);
2617 /* Quits SILC session. This is the normal way to disconnect client. */
2619 SILC_SERVER_CMD_FUNC(quit)
2621 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2622 SilcServer server = cmd->server;
2623 SilcSocketConnection sock = cmd->sock;
2625 unsigned char *tmp = NULL;
2628 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2630 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2633 /* Get destination ID */
2634 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2638 q = silc_calloc(1, sizeof(*q));
2641 q->signoff = tmp ? strdup(tmp) : NULL;
2643 /* We quit the connection with little timeout */
2644 silc_schedule_task_add(server->schedule, sock->sock,
2645 silc_server_command_quit_cb, (void *)q,
2646 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2649 silc_server_command_free(cmd);
2652 /* Server side of command KILL. This command is used by router operator
2653 to remove an client from the SILC Network temporarily. */
2655 SILC_SERVER_CMD_FUNC(kill)
2657 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2658 SilcServer server = cmd->server;
2659 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2660 SilcClientEntry remote_client;
2661 SilcClientID *client_id;
2662 unsigned char *tmp, *comment;
2663 uint32 tmp_len, tmp_len2;
2665 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2667 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2670 /* KILL command works only on router */
2671 if (server->server_type != SILC_ROUTER) {
2672 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2673 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2677 /* Check whether client has the permissions. */
2678 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2679 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2680 SILC_STATUS_ERR_NO_ROUTER_PRIV);
2684 /* Get the client ID */
2685 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2687 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2688 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2691 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2693 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2694 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2698 /* Get the client entry */
2699 remote_client = silc_idlist_find_client_by_id(server->local_list,
2700 client_id, TRUE, NULL);
2701 if (!remote_client) {
2702 remote_client = silc_idlist_find_client_by_id(server->global_list,
2703 client_id, TRUE, NULL);
2704 if (!remote_client) {
2705 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2706 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2712 comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2716 /* Send reply to the sender */
2717 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2720 /* Send the KILL notify packets. First send it to the channel, then
2721 to our primary router and then directly to the client who is being
2722 killed right now. */
2724 /* Send KILLED notify to the channels. It is not sent to the client
2725 as it will be sent differently destined directly to the client and not
2727 silc_server_send_notify_on_channels(server, remote_client,
2728 remote_client, SILC_NOTIFY_TYPE_KILLED,
2731 comment, comment ? tmp_len2 : 0);
2733 /* Send KILLED notify to primary route */
2734 if (!server->standalone)
2735 silc_server_send_notify_killed(server, server->router->connection, TRUE,
2736 remote_client->id, comment);
2738 /* Send KILLED notify to the client directly */
2739 silc_server_send_notify_killed(server, remote_client->connection ?
2740 remote_client->connection :
2741 remote_client->router->connection, FALSE,
2742 remote_client->id, comment);
2744 /* Remove the client from all channels. This generates new keys to the
2745 channels as well. */
2746 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
2749 /* Remove the client entry, If it is locally connected then we will also
2750 disconnect the client here */
2751 if (remote_client->connection) {
2752 /* Remove locally conneted client */
2753 SilcSocketConnection sock = remote_client->connection;
2754 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2755 silc_server_close_connection(server, sock);
2757 /* Remove remote client */
2758 if (!silc_idlist_del_client(server->global_list, remote_client))
2759 silc_idlist_del_client(server->local_list, remote_client);
2763 silc_server_command_free(cmd);
2766 /* Server side of command INFO. This sends information about us to
2767 the client. If client requested specific server we will send the
2768 command to that server. */
2770 SILC_SERVER_CMD_FUNC(info)
2772 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2773 SilcServer server = cmd->server;
2774 SilcBuffer packet, idp;
2777 char *dest_server, *server_info = NULL, *server_name;
2778 uint16 ident = silc_command_get_ident(cmd->payload);
2779 SilcServerEntry entry = NULL;
2780 SilcServerID *server_id = NULL;
2782 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2784 /* Get server name */
2785 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2788 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2790 server_id = silc_id_payload_parse_id(tmp, tmp_len);
2792 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2793 SILC_STATUS_ERR_NO_SERVER_ID);
2799 /* Check whether we have this server cached */
2800 entry = silc_idlist_find_server_by_id(server->local_list,
2801 server_id, TRUE, NULL);
2803 entry = silc_idlist_find_server_by_id(server->global_list,
2804 server_id, TRUE, NULL);
2805 if (!entry && server->server_type != SILC_SERVER) {
2806 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2807 SILC_STATUS_ERR_NO_SUCH_SERVER);
2813 /* Some buggy servers has sent request to router about themselves. */
2814 if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2817 if ((!dest_server && !server_id && !entry) || (entry &&
2818 entry == server->id_entry) ||
2819 (dest_server && !cmd->pending &&
2820 !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2821 /* Send our reply */
2822 char info_string[256];
2824 memset(info_string, 0, sizeof(info_string));
2825 snprintf(info_string, sizeof(info_string),
2826 "location: %s server: %s admin: %s <%s>",
2827 server->config->admin_info->location,
2828 server->config->admin_info->server_type,
2829 server->config->admin_info->admin_name,
2830 server->config->admin_info->admin_email);
2832 server_info = info_string;
2833 entry = server->id_entry;
2835 /* Check whether we have this server cached */
2836 if (!entry && dest_server) {
2837 entry = silc_idlist_find_server_by_name(server->global_list,
2838 dest_server, TRUE, NULL);
2840 entry = silc_idlist_find_server_by_name(server->local_list,
2841 dest_server, TRUE, NULL);
2845 if (!cmd->pending &&
2846 server->server_type != SILC_SERVER && entry && !entry->server_info) {
2847 /* Send to the server */
2851 old_ident = silc_command_get_ident(cmd->payload);
2852 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2853 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2855 silc_server_packet_send(server, entry->connection,
2856 SILC_PACKET_COMMAND, cmd->packet->flags,
2857 tmpbuf->data, tmpbuf->len, TRUE);
2859 /* Reprocess this packet after received reply from router */
2860 silc_server_command_pending(server, SILC_COMMAND_INFO,
2861 silc_command_get_ident(cmd->payload),
2862 silc_server_command_destructor,
2863 silc_server_command_info,
2864 silc_server_command_dup(cmd));
2865 cmd->pending = TRUE;
2866 silc_command_set_ident(cmd->payload, old_ident);
2867 silc_buffer_free(tmpbuf);
2871 if (!entry && !cmd->pending && !server->standalone) {
2872 /* Send to the primary router */
2876 old_ident = silc_command_get_ident(cmd->payload);
2877 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2878 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2880 silc_server_packet_send(server, server->router->connection,
2881 SILC_PACKET_COMMAND, cmd->packet->flags,
2882 tmpbuf->data, tmpbuf->len, TRUE);
2884 /* Reprocess this packet after received reply from router */
2885 silc_server_command_pending(server, SILC_COMMAND_INFO,
2886 silc_command_get_ident(cmd->payload),
2887 silc_server_command_destructor,
2888 silc_server_command_info,
2889 silc_server_command_dup(cmd));
2890 cmd->pending = TRUE;
2891 silc_command_set_ident(cmd->payload, old_ident);
2892 silc_buffer_free(tmpbuf);
2897 silc_free(server_id);
2900 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2901 SILC_STATUS_ERR_NO_SUCH_SERVER);
2905 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2907 server_info = entry->server_info;
2908 server_name = entry->server_name;
2910 /* Send the reply */
2912 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2913 SILC_STATUS_OK, ident, 3,
2914 2, idp->data, idp->len,
2916 strlen(server_name),
2918 strlen(server_info));
2920 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2921 SILC_STATUS_OK, ident, 2,
2922 2, idp->data, idp->len,
2924 strlen(server_name));
2925 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2926 packet->data, packet->len, FALSE);
2928 silc_buffer_free(packet);
2929 silc_buffer_free(idp);
2932 silc_server_command_free(cmd);
2935 /* Server side of command PING. This just replies to the ping. */
2937 SILC_SERVER_CMD_FUNC(ping)
2939 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2940 SilcServer server = cmd->server;
2945 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
2948 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2950 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2951 SILC_STATUS_ERR_NO_SERVER_ID);
2954 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2958 if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2959 /* Send our reply */
2960 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2963 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2964 SILC_STATUS_ERR_NO_SUCH_SERVER);
2971 silc_server_command_free(cmd);
2974 /* Internal routine to join channel. The channel sent to this function
2975 has been either created or resolved from ID lists. This joins the sent
2976 client to the channel. */
2978 static void silc_server_command_join_channel(SilcServer server,
2979 SilcServerCommandContext cmd,
2980 SilcChannelEntry channel,
2981 SilcClientID *client_id,
2986 SilcSocketConnection sock = cmd->sock;
2988 uint32 tmp_len, user_count;
2989 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
2990 SilcClientEntry client;
2991 SilcChannelClientEntry chl;
2992 SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
2993 uint16 ident = silc_command_get_ident(cmd->payload);
2994 char check[512], check2[512];
2996 SILC_LOG_DEBUG(("Start"));
3001 /* Get the client entry */
3002 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3003 client = (SilcClientEntry)sock->user_data;
3005 client = silc_server_get_client_resolve(server, client_id);
3010 /* The client info is being resolved. Reprocess this packet after
3011 receiving the reply to the query. */
3012 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
3013 server->cmd_ident, NULL,
3014 silc_server_command_join,
3015 silc_server_command_dup(cmd));
3016 cmd->pending = TRUE;
3020 cmd->pending = FALSE;
3024 * Check channel modes
3027 memset(check, 0, sizeof(check));
3028 memset(check2, 0, sizeof(check2));
3029 strncat(check, client->nickname, strlen(client->nickname));
3030 strncat(check, "!", 1);
3031 strncat(check, client->username, strlen(client->username));
3032 if (!strchr(client->username, '@')) {
3033 strncat(check, "@", 1);
3034 strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3037 strncat(check2, client->nickname, strlen(client->nickname));
3038 if (!strchr(client->nickname, '@')) {
3039 strncat(check2, "@", 1);
3040 strncat(check2, server->server_name, strlen(server->server_name));
3042 strncat(check2, "!", 1);
3043 strncat(check2, client->username, strlen(client->username));
3044 if (!strchr(client->username, '@')) {
3045 strncat(check2, "@", 1);
3046 strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3049 /* Check invite list if channel is invite-only channel */
3050 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3051 if (!channel->invite_list ||
3052 (!silc_string_match(channel->invite_list, check) &&
3053 !silc_string_match(channel->invite_list, check2))) {
3054 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3055 SILC_STATUS_ERR_NOT_INVITED);
3060 /* Check ban list if it exists. If the client's nickname, server,
3061 username and/or hostname is in the ban list the access to the
3062 channel is denied. */
3063 if (channel->ban_list) {
3064 if (!channel->ban_list ||
3065 silc_string_match(channel->ban_list, check) ||
3066 silc_string_match(channel->ban_list, check2)) {
3067 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3068 SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
3073 /* Get passphrase */
3074 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3076 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
3077 memcpy(passphrase, tmp, tmp_len);
3080 /* Check the channel passphrase if set. */
3081 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3082 if (!passphrase || !channel->passphrase ||
3083 memcmp(channel->passphrase, passphrase,
3084 strlen(channel->passphrase))) {
3085 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3086 SILC_STATUS_ERR_BAD_PASSWORD);
3091 /* Check user count limit if set. */
3092 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3093 if (silc_hash_table_count(channel->user_list) + 1 >
3094 channel->user_limit) {
3095 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3096 SILC_STATUS_ERR_CHANNEL_IS_FULL);
3102 * Client is allowed to join to the channel. Make it happen.
3105 /* Check whether the client already is on the channel */
3106 if (silc_server_client_on_channel(client, channel)) {
3107 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3108 SILC_STATUS_ERR_USER_ON_CHANNEL);
3112 /* Generate new channel key as protocol dictates */
3114 if (!silc_server_create_channel_key(server, channel, 0))
3117 /* Send the channel key. This is broadcasted to the channel but is not
3118 sent to the client who is joining to the channel. */
3119 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3120 silc_server_send_channel_key(server, NULL, channel,
3121 server->server_type == SILC_ROUTER ?
3122 FALSE : !server->standalone);
3125 /* Join the client to the channel by adding it to channel's user list.
3126 Add also the channel to client entry's channels list for fast cross-
3128 chl = silc_calloc(1, sizeof(*chl));
3130 chl->client = client;
3131 chl->channel = channel;
3132 silc_hash_table_add(channel->user_list, client, chl);
3133 silc_hash_table_add(client->channels, channel, chl);
3135 /* Get users on the channel */
3136 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3139 /* Encode Client ID Payload of the original client who wants to join */
3140 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3142 /* Encode command reply packet */
3143 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3144 SILC_PUT32_MSB(channel->mode, mode);
3145 SILC_PUT32_MSB(created, tmp2);
3146 SILC_PUT32_MSB(user_count, tmp3);
3148 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3149 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3150 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
3151 strlen(channel->channel_key->
3153 channel->channel_key->cipher->name,
3154 channel->key_len / 8, channel->key);
3159 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3160 SILC_STATUS_OK, ident, 13,
3161 2, channel->channel_name,
3162 strlen(channel->channel_name),
3163 3, chidp->data, chidp->len,
3164 4, clidp->data, clidp->len,
3167 7, keyp ? keyp->data : NULL,
3168 keyp ? keyp->len : 0,
3169 8, channel->ban_list,
3171 strlen(channel->ban_list) : 0,
3172 9, channel->invite_list,
3173 channel->invite_list ?
3174 strlen(channel->invite_list) : 0,
3177 strlen(channel->topic) : 0,
3178 11, silc_hmac_get_name(channel->hmac),
3179 strlen(silc_hmac_get_name(channel->
3182 13, user_list->data, user_list->len,
3183 14, mode_list->data,
3186 /* Send command reply */
3187 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
3188 reply->data, reply->len, FALSE);
3190 /* Send JOIN notify to locally connected clients on the channel. If
3191 we are normal server then router will send or have sent JOIN notify
3192 already. However since we've added the client already to our channel
3193 we'll ignore it (in packet_receive.c) so we must send it here. If
3194 we are router then this will send it to local clients and local
3196 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3197 SILC_NOTIFY_TYPE_JOIN, 2,
3198 clidp->data, clidp->len,
3199 chidp->data, chidp->len);
3201 if (!cmd->pending) {
3202 /* Send JOIN notify packet to our primary router */
3203 if (!server->standalone)
3204 silc_server_send_notify_join(server, server->router->connection,
3205 server->server_type == SILC_ROUTER ?
3206 TRUE : FALSE, channel, client->id);
3209 /* Distribute the channel key to all backup routers. */
3210 silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3211 keyp->data, keyp->len, FALSE, TRUE);
3214 silc_buffer_free(reply);
3215 silc_buffer_free(clidp);
3216 silc_buffer_free(chidp);
3217 silc_buffer_free(keyp);
3218 silc_buffer_free(user_list);
3219 silc_buffer_free(mode_list);
3222 silc_free(passphrase);
3225 /* Server side of command JOIN. Joins client into requested channel. If
3226 the channel does not exist it will be created. */
3228 SILC_SERVER_CMD_FUNC(join)
3230 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3231 SilcServer server = cmd->server;
3233 char *tmp, *channel_name = NULL, *cipher, *hmac;
3234 SilcChannelEntry channel;
3236 bool created = FALSE, create_key = TRUE;
3237 SilcClientID *client_id;
3239 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 1, 4);
3241 /* Get channel name */
3242 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3244 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3245 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3250 if (strlen(channel_name) > 256)
3251 channel_name[255] = '\0';
3253 if (silc_server_command_bad_chars(channel_name) == TRUE) {
3254 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3255 SILC_STATUS_ERR_BAD_CHANNEL);
3259 /* Get Client ID of the client who is joining to the channel */
3260 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3262 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3263 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3266 client_id = silc_id_payload_parse_id(tmp, tmp_len);
3268 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3269 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3273 /* Get cipher and hmac name */
3274 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3275 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3277 /* See if the channel exists */
3278 channel = silc_idlist_find_channel_by_name(server->local_list,
3279 channel_name, NULL);
3281 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3282 /* If this is coming from client the Client ID in the command packet must
3283 be same as the client's ID. */
3284 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3285 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3286 if (!SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
3287 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3288 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3293 if (!channel || channel->disabled) {
3294 /* Channel not found */
3296 /* If we are standalone server we don't have a router, we just create
3297 the channel by ourselves. */
3298 if (server->standalone) {
3299 channel = silc_server_create_new_channel(server, server->id, cipher,
3300 hmac, channel_name, TRUE);
3302 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3303 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3307 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3313 /* The channel does not exist on our server. If we are normal server
3314 we will send JOIN command to our router which will handle the
3315 joining procedure (either creates the channel if it doesn't exist
3316 or joins the client to it). */
3317 if (server->server_type != SILC_ROUTER) {
3321 /* If this is pending command callback then we've resolved
3322 it and it didn't work, return since we've notified the
3323 client already in the command reply callback. */
3327 old_ident = silc_command_get_ident(cmd->payload);
3328 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3329 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3331 /* Send JOIN command to our router */
3332 silc_server_packet_send(server, (SilcSocketConnection)
3333 server->router->connection,
3334 SILC_PACKET_COMMAND, cmd->packet->flags,
3335 tmpbuf->data, tmpbuf->len, TRUE);
3337 /* Reprocess this packet after received reply from router */
3338 silc_server_command_pending(server, SILC_COMMAND_JOIN,
3339 silc_command_get_ident(cmd->payload),
3340 silc_server_command_destructor,
3341 silc_server_command_join,
3342 silc_server_command_dup(cmd));
3343 cmd->pending = TRUE;
3347 /* We are router and the channel does not seem exist so we will check
3348 our global list as well for the channel. */
3349 channel = silc_idlist_find_channel_by_name(server->global_list,
3350 channel_name, NULL);
3352 /* Channel really does not exist, create it */
3353 channel = silc_server_create_new_channel(server, server->id, cipher,
3354 hmac, channel_name, TRUE);
3356 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3357 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3361 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3369 /* Channel not found */
3371 /* If the command came from router and we are normal server then
3372 something went wrong with the joining as the channel was not found.
3373 We can't do anything else but ignore this. */
3374 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3375 server->server_type != SILC_ROUTER)
3378 /* We are router and the channel does not seem exist so we will check
3379 our global list as well for the channel. */
3380 channel = silc_idlist_find_channel_by_name(server->global_list,
3381 channel_name, NULL);
3383 /* Channel really does not exist, create it */
3384 channel = silc_server_create_new_channel(server, server->id, cipher,
3385 hmac, channel_name, TRUE);
3387 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3388 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3392 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3399 /* Check whether the channel was created by our router */
3400 if (cmd->pending && context2) {
3401 SilcServerCommandReplyContext reply =
3402 (SilcServerCommandReplyContext)context2;
3403 if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3404 tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3405 SILC_GET32_MSB(created, tmp);
3406 create_key = FALSE; /* Router returned the key already */
3410 /* If the channel does not have global users and is also empty the client
3411 will be the channel founder and operator. */
3412 if (!channel->global_users && !silc_hash_table_count(channel->user_list))
3413 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3415 /* Join to the channel */
3416 silc_server_command_join_channel(server, cmd, channel, client_id,
3417 created, create_key, umode);
3419 silc_free(client_id);
3422 silc_server_command_free(cmd);
3425 /* Server side of command MOTD. Sends server's current "message of the
3426 day" to the client. */
3428 SILC_SERVER_CMD_FUNC(motd)
3430 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3431 SilcServer server = cmd->server;
3432 SilcBuffer packet, idp;
3433 char *motd, *dest_server;
3435 uint16 ident = silc_command_get_ident(cmd->payload);
3437 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3439 /* Get server name */
3440 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3442 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3443 SILC_STATUS_ERR_NO_SUCH_SERVER);
3447 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3450 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3452 if (server->config && server->config->motd &&
3453 server->config->motd->motd_file) {
3455 motd = silc_file_readfile(server->config->motd->motd_file, &motd_len);
3460 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3461 SILC_STATUS_OK, ident, 2,
3466 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3467 SILC_STATUS_OK, ident, 1,
3471 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3472 packet->data, packet->len, FALSE);
3473 silc_buffer_free(packet);
3474 silc_buffer_free(idp);
3476 SilcServerEntry entry;
3478 /* Check whether we have this server cached */
3479 entry = silc_idlist_find_server_by_name(server->global_list,
3480 dest_server, TRUE, NULL);
3482 entry = silc_idlist_find_server_by_name(server->local_list,
3483 dest_server, TRUE, NULL);
3486 if (server->server_type != SILC_SERVER && !cmd->pending &&
3487 entry && !entry->motd) {
3488 /* Send to the server */
3492 old_ident = silc_command_get_ident(cmd->payload);
3493 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3494 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3496 silc_server_packet_send(server, entry->connection,
3497 SILC_PACKET_COMMAND, cmd->packet->flags,
3498 tmpbuf->data, tmpbuf->len, TRUE);
3500 /* Reprocess this packet after received reply from router */
3501 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3502 silc_command_get_ident(cmd->payload),
3503 silc_server_command_destructor,
3504 silc_server_command_motd,
3505 silc_server_command_dup(cmd));
3506 cmd->pending = TRUE;
3507 silc_command_set_ident(cmd->payload, old_ident);
3508 silc_buffer_free(tmpbuf);
3512 if (!entry && !cmd->pending && !server->standalone) {
3513 /* Send to the primary router */
3517 old_ident = silc_command_get_ident(cmd->payload);
3518 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3519 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3521 silc_server_packet_send(server, server->router->connection,
3522 SILC_PACKET_COMMAND, cmd->packet->flags,
3523 tmpbuf->data, tmpbuf->len, TRUE);
3525 /* Reprocess this packet after received reply from router */
3526 silc_server_command_pending(server, SILC_COMMAND_MOTD,
3527 silc_command_get_ident(cmd->payload),
3528 silc_server_command_destructor,
3529 silc_server_command_motd,
3530 silc_server_command_dup(cmd));
3531 cmd->pending = TRUE;
3532 silc_command_set_ident(cmd->payload, old_ident);
3533 silc_buffer_free(tmpbuf);
3538 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3539 SILC_STATUS_ERR_NO_SUCH_SERVER);
3543 idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3546 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3547 SILC_STATUS_OK, ident, 2,
3550 strlen(entry->motd));
3552 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3553 SILC_STATUS_OK, ident, 1,
3556 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3557 packet->data, packet->len, FALSE);
3558 silc_buffer_free(packet);
3559 silc_buffer_free(idp);
3563 silc_server_command_free(cmd);
3566 /* Server side of command UMODE. Client can use this command to set/unset
3567 user mode. Client actually cannot set itself to be as server/router
3568 operator so this can be used only to unset the modes. */
3570 SILC_SERVER_CMD_FUNC(umode)
3572 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3573 SilcServer server = cmd->server;
3574 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3576 unsigned char *tmp_mask;
3578 uint16 ident = silc_command_get_ident(cmd->payload);
3580 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3583 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 2, 2);
3585 /* Get the client's mode mask */
3586 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3588 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3589 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3592 SILC_GET32_MSB(mask, tmp_mask);
3598 if (mask & SILC_UMODE_SERVER_OPERATOR) {
3599 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR)) {
3600 /* Cannot operator mode */
3601 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3602 SILC_STATUS_ERR_PERM_DENIED);
3606 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
3607 /* Remove the server operator rights */
3608 client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3611 if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3612 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
3613 /* Cannot operator mode */
3614 silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3615 SILC_STATUS_ERR_PERM_DENIED);
3619 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
3620 /* Remove the router operator rights */
3621 client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3624 if (mask & SILC_UMODE_GONE) {
3625 client->mode |= SILC_UMODE_GONE;
3627 if (client->mode & SILC_UMODE_GONE)
3628 /* Remove the gone status */
3629 client->mode &= ~SILC_UMODE_GONE;
3632 /* Send UMODE change to primary router */
3633 if (!server->standalone)
3634 silc_server_send_notify_umode(server, server->router->connection, TRUE,
3635 client->id, client->mode);
3637 /* Send command reply to sender */
3638 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3639 SILC_STATUS_OK, ident, 1,
3641 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3642 packet->data, packet->len, FALSE);
3643 silc_buffer_free(packet);
3646 silc_server_command_free(cmd);
3649 /* Checks that client has rights to add or remove channel modes. If any
3650 of the checks fails FALSE is returned. */
3652 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3653 SilcChannelClientEntry client,
3656 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3657 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3659 /* Check whether has rights to change anything */
3660 if (!is_op && !is_fo)
3663 /* Check whether has rights to change everything */
3667 /* We know that client is channel operator, check that they are not
3668 changing anything that requires channel founder rights. Rest of the
3669 modes are available automatically for channel operator. */
3671 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3672 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3673 if (is_op && !is_fo)
3676 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3677 if (is_op && !is_fo)
3682 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3683 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE))
3684 if (is_op && !is_fo)
3687 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3688 if (is_op && !is_fo)
3693 if (mode & SILC_CHANNEL_MODE_CIPHER) {
3694 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER))
3695 if (is_op && !is_fo)
3698 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3699 if (is_op && !is_fo)
3704 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3705 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH))
3706 if (is_op && !is_fo)
3709 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3710 if (is_op && !is_fo)
3718 /* Server side command of CMODE. Changes channel mode */
3720 SILC_SERVER_CMD_FUNC(cmode)
3722 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3723 SilcServer server = cmd->server;
3724 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3725 SilcIDListData idata = (SilcIDListData)client;
3726 SilcChannelID *channel_id;
3727 SilcChannelEntry channel;
3728 SilcChannelClientEntry chl;
3729 SilcBuffer packet, cidp;
3730 unsigned char *tmp, *tmp_id, *tmp_mask;
3731 char *cipher = NULL, *hmac = NULL;
3732 uint32 mode_mask, tmp_len, tmp_len2;
3733 uint16 ident = silc_command_get_ident(cmd->payload);
3735 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 2, 7);
3737 /* Get Channel ID */
3738 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3740 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3741 SILC_STATUS_ERR_NO_CHANNEL_ID);
3744 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3746 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3747 SILC_STATUS_ERR_NO_CHANNEL_ID);
3751 /* Get the channel mode mask */
3752 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3754 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3755 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3758 SILC_GET32_MSB(mode_mask, tmp_mask);
3760 /* Get channel entry */
3761 channel = silc_idlist_find_channel_by_id(server->local_list,
3764 channel = silc_idlist_find_channel_by_id(server->global_list,
3767 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3768 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3773 /* Check whether this client is on the channel */
3774 if (!silc_server_client_on_channel(client, channel)) {
3775 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3776 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3780 /* Get entry to the channel user list */
3781 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
3783 /* Check that client has rights to change any requested channel modes */
3784 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3785 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3786 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3791 * Check the modes. Modes that requires nothing special operation are
3795 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3796 /* Channel uses private keys to protect traffic. Client(s) has set the
3797 key locally they want to use, server does not know that key. */
3798 /* Nothing interesting to do here */
3800 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3801 /* The mode is removed and we need to generate and distribute
3802 new channel key. Clients are not using private channel keys
3803 anymore after this. */
3805 /* Re-generate channel key */
3806 if (!silc_server_create_channel_key(server, channel, 0))
3809 /* Send the channel key. This sends it to our local clients and if
3810 we are normal server to our router as well. */
3811 silc_server_send_channel_key(server, NULL, channel,
3812 server->server_type == SILC_ROUTER ?
3813 FALSE : !server->standalone);
3815 cipher = channel->channel_key->cipher->name;
3816 hmac = (char *)silc_hmac_get_name(channel->hmac);
3820 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3821 /* User limit is set on channel */
3824 /* Get user limit */
3825 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3827 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3828 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3829 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3833 SILC_GET32_MSB(user_limit, tmp);
3834 channel->user_limit = user_limit;
3837 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3838 /* User limit mode is unset. Remove user limit */
3839 channel->user_limit = 0;
3842 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3843 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3844 /* Passphrase has been set to channel */
3846 /* Get the passphrase */
3847 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3849 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3850 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3854 /* Save the passphrase */
3855 channel->passphrase = strdup(tmp);
3858 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3859 /* Passphrase mode is unset. remove the passphrase */
3860 if (channel->passphrase) {
3861 silc_free(channel->passphrase);
3862 channel->passphrase = NULL;
3867 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3868 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3869 /* Cipher to use protect the traffic */
3870 SilcCipher newkey, oldkey;
3873 cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3875 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3876 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3880 /* Delete old cipher and allocate the new one */
3881 if (!silc_cipher_alloc(cipher, &newkey)) {
3882 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3883 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3887 oldkey = channel->channel_key;
3888 channel->channel_key = newkey;
3890 /* Re-generate channel key */
3891 if (!silc_server_create_channel_key(server, channel, 0)) {
3892 /* We don't have new key, revert to old one */
3893 channel->channel_key = oldkey;
3897 /* Remove old channel key for good */
3898 silc_cipher_free(oldkey);
3900 /* Send the channel key. This sends it to our local clients and if
3901 we are normal server to our router as well. */
3902 silc_server_send_channel_key(server, NULL, channel,
3903 server->server_type == SILC_ROUTER ?
3904 FALSE : !server->standalone);
3907 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3908 /* Cipher mode is unset. Remove the cipher and revert back to
3910 SilcCipher newkey, oldkey;
3911 cipher = channel->cipher;
3913 /* Delete old cipher and allocate default one */
3914 if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
3915 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3916 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3920 oldkey = channel->channel_key;
3921 channel->channel_key = newkey;
3923 /* Re-generate channel key */
3924 if (!silc_server_create_channel_key(server, channel, 0)) {
3925 /* We don't have new key, revert to old one */
3926 channel->channel_key = oldkey;
3930 /* Remove old channel key for good */
3931 silc_cipher_free(oldkey);
3933 /* Send the channel key. This sends it to our local clients and if
3934 we are normal server to our router as well. */
3935 silc_server_send_channel_key(server, NULL, channel,
3936 server->server_type == SILC_ROUTER ?
3937 FALSE : !server->standalone);
3941 if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3942 if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3943 /* HMAC to use protect the traffic */
3944 unsigned char hash[32];
3948 hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3950 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3951 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3955 /* Delete old hmac and allocate the new one */
3956 if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
3957 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3958 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3962 silc_hmac_free(channel->hmac);
3963 channel->hmac = newhmac;
3965 /* Set the HMAC key out of current channel key. The client must do
3967 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
3968 channel->key_len / 8, hash);
3969 silc_hmac_set_key(channel->hmac, hash,
3970 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3971 memset(hash, 0, sizeof(hash));
3974 if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
3975 /* Hmac mode is unset. Remove the hmac and revert back to
3978 unsigned char hash[32];
3979 hmac = channel->hmac_name;
3981 /* Delete old hmac and allocate default one */
3982 silc_hmac_free(channel->hmac);
3983 if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
3984 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3985 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3989 silc_hmac_free(channel->hmac);
3990 channel->hmac = newhmac;
3992 /* Set the HMAC key out of current channel key. The client must do
3994 silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key,
3995 channel->key_len / 8,
3997 silc_hmac_set_key(channel->hmac, hash,
3998 silc_hash_len(silc_hmac_get_hash(channel->hmac)));
3999 memset(hash, 0, sizeof(hash));
4003 if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4004 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4005 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4006 /* Set the founder authentication */
4007 SilcAuthPayload auth;
4009 tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4011 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4012 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4016 auth = silc_auth_payload_parse(tmp, tmp_len);
4018 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4019 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4023 /* Save the public key */
4024 tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
4025 silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
4028 channel->founder_method = silc_auth_get_method(auth);
4030 if (channel->founder_method == SILC_AUTH_PASSWORD) {
4031 tmp = silc_auth_get_data(auth, &tmp_len);
4032 channel->founder_passwd =
4033 silc_calloc(tmp_len + 1, sizeof(*channel->founder_passwd));
4034 memcpy(channel->founder_passwd, tmp, tmp_len);
4035 channel->founder_passwd_len = tmp_len;
4037 /* Verify the payload before setting the mode */
4038 if (!silc_auth_verify(auth, channel->founder_method,
4039 channel->founder_key, 0, idata->hash,
4040 client->id, SILC_ID_CLIENT)) {
4041 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4042 SILC_STATUS_ERR_AUTH_FAILED);
4047 silc_auth_payload_free(auth);
4051 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4052 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4053 if (channel->founder_key)
4054 silc_pkcs_public_key_free(channel->founder_key);
4055 if (channel->founder_passwd) {
4056 silc_free(channel->founder_passwd);
4057 channel->founder_passwd = NULL;
4063 /* Finally, set the mode */
4064 channel->mode = mode_mask;
4066 /* Send CMODE_CHANGE notify */
4067 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4068 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4069 SILC_NOTIFY_TYPE_CMODE_CHANGE, 4,
4070 cidp->data, cidp->len,
4072 cipher, cipher ? strlen(cipher) : 0,
4073 hmac, hmac ? strlen(hmac) : 0);
4075 /* Set CMODE notify type to network */
4076 if (!server->standalone)
4077 silc_server_send_notify_cmode(server, server->router->connection,
4078 server->server_type == SILC_ROUTER ?
4079 TRUE : FALSE, channel,
4080 mode_mask, client->id, SILC_ID_CLIENT,
4083 /* Send command reply to sender */
4084 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4085 SILC_STATUS_OK, ident, 2,
4086 2, tmp_id, tmp_len2,
4088 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4089 packet->data, packet->len, FALSE);
4091 silc_buffer_free(packet);
4092 silc_free(channel_id);
4096 silc_server_command_free(cmd);
4099 /* Server side of CUMODE command. Changes client's mode on a channel. */
4101 SILC_SERVER_CMD_FUNC(cumode)
4103 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4104 SilcServer server = cmd->server;
4105 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4106 SilcIDListData idata = (SilcIDListData)client;
4107 SilcChannelID *channel_id;
4108 SilcClientID *client_id;
4109 SilcChannelEntry channel;
4110 SilcClientEntry target_client;
4111 SilcChannelClientEntry chl;
4112 SilcBuffer packet, idp;
4113 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4114 uint32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4116 uint16 ident = silc_command_get_ident(cmd->payload);
4118 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4120 /* Get Channel ID */
4121 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4123 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4124 SILC_STATUS_ERR_NO_CHANNEL_ID);
4127 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
4129 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4130 SILC_STATUS_ERR_NO_CHANNEL_ID);
4134 /* Get channel entry */
4135 channel = silc_idlist_find_channel_by_id(server->local_list,
4138 channel = silc_idlist_find_channel_by_id(server->global_list,
4141 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4142 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4147 /* Check whether sender is on the channel */
4148 if (!silc_server_client_on_channel(client, channel)) {
4149 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4150 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4154 /* Check that client has rights to change other's rights */
4155 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4156 sender_mask = chl->mode;
4158 /* Get the target client's channel mode mask */
4159 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4161 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4162 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4165 SILC_GET32_MSB(target_mask, tmp_mask);
4167 /* Get target Client ID */
4168 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4170 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4171 SILC_STATUS_ERR_NO_CLIENT_ID);
4174 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
4176 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4177 SILC_STATUS_ERR_NO_CLIENT_ID);
4181 /* Get target client's entry */
4182 target_client = silc_idlist_find_client_by_id(server->local_list,
4183 client_id, TRUE, NULL);
4184 if (!target_client) {
4185 target_client = silc_idlist_find_client_by_id(server->global_list,
4186 client_id, TRUE, NULL);
4189 if (target_client != client &&
4190 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4191 !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4192 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4193 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4197 /* Check whether target client is on the channel */
4198 if (target_client != client) {
4199 if (!silc_server_client_on_channel(target_client, channel)) {
4200 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4201 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4205 /* Get entry to the channel user list */
4206 silc_hash_table_find(channel->user_list, target_client, NULL,
4214 /* If the target client is founder, no one else can change their mode
4216 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
4217 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4218 SILC_STATUS_ERR_NOT_YOU);
4222 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4223 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4224 /* The client tries to claim the founder rights. */
4225 unsigned char *tmp_auth;
4226 uint32 tmp_auth_len, auth_len;
4229 if (target_client != client) {
4230 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4231 SILC_STATUS_ERR_NOT_YOU);
4235 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4236 !channel->founder_key || !idata->public_key ||
4237 !silc_pkcs_public_key_compare(channel->founder_key,
4238 idata->public_key)) {
4239 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4240 SILC_STATUS_ERR_NOT_YOU);
4244 tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4246 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4247 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4251 auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4252 (void *)channel->founder_passwd : (void *)channel->founder_key);
4253 auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4254 channel->founder_passwd_len : 0);
4256 if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4257 channel->founder_method, auth, auth_len,
4258 idata->hash, client->id, SILC_ID_CLIENT)) {
4259 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4260 SILC_STATUS_ERR_AUTH_FAILED);
4264 sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4268 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4269 if (target_client == client) {
4270 /* Remove channel founder rights from itself */
4271 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4274 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4275 SILC_STATUS_ERR_NOT_YOU);
4281 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4282 /* Promote to operator */
4283 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4284 if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4285 !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4286 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4287 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4291 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
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 /* Demote to normal user */
4304 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4309 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4310 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4312 /* Send notify to channel, notify only if mode was actually changed. */
4314 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4315 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4316 idp->data, idp->len,
4320 /* Set CUMODE notify type to network */
4321 if (!server->standalone)
4322 silc_server_send_notify_cumode(server, server->router->connection,
4323 server->server_type == SILC_ROUTER ?
4324 TRUE : FALSE, channel,
4325 target_mask, client->id,
4330 /* Send command reply to sender */
4331 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4332 SILC_STATUS_OK, ident, 3,
4334 3, tmp_ch_id, tmp_ch_len,
4335 4, tmp_id, tmp_len);
4336 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4337 packet->data, packet->len, FALSE);
4339 silc_buffer_free(packet);
4340 silc_free(channel_id);
4341 silc_free(client_id);
4342 silc_buffer_free(idp);
4345 silc_server_command_free(cmd);
4348 /* Server side of KICK command. Kicks client out of channel. */
4350 SILC_SERVER_CMD_FUNC(kick)
4352 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4353 SilcServer server = cmd->server;
4354 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4355 SilcClientEntry target_client;
4356 SilcChannelID *channel_id;
4357 SilcClientID *client_id;
4358 SilcChannelEntry channel;
4359 SilcChannelClientEntry chl;
4362 unsigned char *tmp, *comment;
4364 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4366 /* Get Channel ID */
4367 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4369 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4370 SILC_STATUS_ERR_NO_CHANNEL_ID);
4373 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
4375 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4376 SILC_STATUS_ERR_NO_CHANNEL_ID);
4380 /* Get channel entry */
4381 channel = silc_idlist_find_channel_by_id(server->local_list,
4384 channel = silc_idlist_find_channel_by_id(server->local_list,
4387 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4388 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4393 /* Check whether sender is on the channel */
4394 if (!silc_server_client_on_channel(client, channel)) {
4395 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4396 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4400 /* Check that the kicker is channel operator or channel founder */
4401 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4402 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4403 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4404 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4408 /* Get target Client ID */
4409 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4411 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4412 SILC_STATUS_ERR_NO_CLIENT_ID);
4415 client_id = silc_id_payload_parse_id(tmp, tmp_len);
4417 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4418 SILC_STATUS_ERR_NO_CLIENT_ID);
4422 /* Get target client's entry */
4423 target_client = silc_idlist_find_client_by_id(server->local_list,
4424 client_id, TRUE, NULL);
4425 if (!target_client) {
4426 target_client = silc_idlist_find_client_by_id(server->global_list,
4427 client_id, TRUE, NULL);
4430 /* Check that the target client is not channel founder. Channel founder
4431 cannot be kicked from the channel. */
4432 silc_hash_table_find(channel->user_list, target_client, NULL, (void *)&chl);
4433 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4434 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4435 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4439 /* Check whether target client is on the channel */
4440 if (!silc_server_client_on_channel(target_client, channel)) {
4441 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4442 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4448 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4452 /* Send command reply to sender */
4453 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4456 /* Send KICKED notify to local clients on the channel */
4457 idp = silc_id_payload_encode(target_client->id, SILC_ID_CLIENT);
4458 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4459 SILC_NOTIFY_TYPE_KICKED,
4461 idp->data, idp->len,
4462 comment, comment ? strlen(comment) : 0);
4463 silc_buffer_free(idp);
4465 /* Remove the client from the channel. If the channel does not exist
4466 after removing the client then the client kicked itself off the channel
4467 and we don't have to send anything after that. */
4468 if (!silc_server_remove_from_one_channel(server, NULL, channel,
4469 target_client, FALSE))
4472 /* Send KICKED notify to primary route */
4473 if (!server->standalone)
4474 silc_server_send_notify_kicked(server, server->router->connection,
4475 server->server_type == SILC_ROUTER ?
4476 TRUE : FALSE, channel,
4477 target_client->id, comment);
4479 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4480 /* Re-generate channel key */
4481 if (!silc_server_create_channel_key(server, channel, 0))
4484 /* Send the channel key to the channel. The key of course is not sent
4485 to the client who was kicked off the channel. */
4486 silc_server_send_channel_key(server, target_client->connection, channel,
4487 server->server_type == SILC_ROUTER ?
4488 FALSE : !server->standalone);
4492 silc_server_command_free(cmd);
4495 /* Server side of OPER command. Client uses this comand to obtain server
4496 operator privileges to this server/router. */
4498 SILC_SERVER_CMD_FUNC(oper)
4500 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4501 SilcServer server = cmd->server;
4502 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4503 unsigned char *username, *auth;
4505 SilcServerConfigSectionAdminConnection *admin;
4506 SilcIDListData idata = (SilcIDListData)client;
4508 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4510 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4513 /* Get the username */
4514 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4516 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4517 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4521 /* Get the admin configuration */
4522 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4523 username, client->nickname);
4525 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4526 username, client->nickname);
4528 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4529 SILC_STATUS_ERR_AUTH_FAILED);
4534 /* Get the authentication payload */
4535 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4537 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4538 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4542 /* Verify the authentication data */
4543 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4544 admin->auth_data, admin->auth_data_len,
4545 idata->hash, client->id, SILC_ID_CLIENT)) {
4546 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4547 SILC_STATUS_ERR_AUTH_FAILED);
4551 /* Client is now server operator */
4552 client->mode |= SILC_UMODE_SERVER_OPERATOR;
4554 /* Send UMODE change to primary router */
4555 if (!server->standalone)
4556 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4557 client->id, client->mode);
4559 /* Send reply to the sender */
4560 silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4564 silc_server_command_free(cmd);
4567 /* Server side of SILCOPER command. Client uses this comand to obtain router
4568 operator privileges to this router. */
4570 SILC_SERVER_CMD_FUNC(silcoper)
4572 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4573 SilcServer server = cmd->server;
4574 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4575 unsigned char *username, *auth;
4577 SilcServerConfigSectionAdminConnection *admin;
4578 SilcIDListData idata = (SilcIDListData)client;
4580 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4582 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4585 if (server->server_type != SILC_ROUTER) {
4586 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4587 SILC_STATUS_ERR_AUTH_FAILED);
4591 /* Get the username */
4592 username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4594 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4595 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4599 /* Get the admin configuration */
4600 admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4601 username, client->nickname);
4603 admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4604 username, client->nickname);
4606 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4607 SILC_STATUS_ERR_AUTH_FAILED);
4612 /* Get the authentication payload */
4613 auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4615 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4616 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4620 /* Verify the authentication data */
4621 if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth,
4622 admin->auth_data, admin->auth_data_len,
4623 idata->hash, client->id, SILC_ID_CLIENT)) {
4624 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4625 SILC_STATUS_ERR_AUTH_FAILED);
4629 /* Client is now router operator */
4630 client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4632 /* Send UMODE change to primary router */
4633 if (!server->standalone)
4634 silc_server_send_notify_umode(server, server->router->connection, TRUE,
4635 client->id, client->mode);
4637 /* Send reply to the sender */
4638 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4642 silc_server_command_free(cmd);
4645 /* Server side command of CONNECT. Connects us to the specified remote
4646 server or router. */
4648 SILC_SERVER_CMD_FUNC(connect)
4650 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4651 SilcServer server = cmd->server;
4652 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4653 unsigned char *tmp, *host;
4655 uint32 port = SILC_PORT;
4657 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CONNECT, cmd, 1, 2);
4659 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4662 /* Check whether client has the permissions. */
4663 if (client->mode == SILC_UMODE_NONE) {
4664 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4665 SILC_STATUS_ERR_NO_SERVER_PRIV);
4669 if (server->server_type == SILC_ROUTER &&
4670 client->mode & SILC_UMODE_SERVER_OPERATOR) {
4671 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4672 SILC_STATUS_ERR_NO_ROUTER_PRIV);
4676 /* Get the remote server */
4677 host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4679 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4680 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4685 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4687 SILC_GET32_MSB(port, tmp);
4689 /* Create the connection. It is done with timeout and is async. */
4690 silc_server_create_connection(server, host, port);
4692 /* Send reply to the sender */
4693 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4697 silc_server_command_free(cmd);
4700 /* Server side of command BAN. This is used to manage the ban list of the
4701 channel. To add clients and remove clients from the ban list. */
4703 SILC_SERVER_CMD_FUNC(ban)
4705 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4706 SilcServer server = cmd->server;
4707 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4709 SilcChannelEntry channel;
4710 SilcChannelClientEntry chl;
4711 SilcChannelID *channel_id = NULL;
4712 unsigned char *id, *add, *del;
4713 uint32 id_len, tmp_len;
4714 uint16 ident = silc_command_get_ident(cmd->payload);
4716 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4719 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4721 /* Get Channel ID */
4722 id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4724 channel_id = silc_id_payload_parse_id(id, id_len);
4726 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4727 SILC_STATUS_ERR_NO_CHANNEL_ID);
4732 /* Get channel entry. The server must know about the channel since the
4733 client is expected to be on the channel. */
4734 channel = silc_idlist_find_channel_by_id(server->local_list,
4737 channel = silc_idlist_find_channel_by_id(server->global_list,
4740 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4741 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4746 /* Check whether this client is on the channel */
4747 if (!silc_server_client_on_channel(client, channel)) {
4748 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4749 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4753 /* Get entry to the channel user list */
4754 silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4756 /* The client must be at least channel operator. */
4757 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4758 silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4759 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4763 /* Get the new ban and add it to the ban list */
4764 add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4766 if (!channel->ban_list)
4767 channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4769 channel->ban_list = silc_realloc(channel->ban_list,
4770 sizeof(*channel->ban_list) *
4772 strlen(channel->ban_list) + 2));
4773 if (add[tmp_len - 1] == ',')
4774 add[tmp_len - 1] = '\0';
4776 strncat(channel->ban_list, add, tmp_len);
4777 strncat(channel->ban_list, ",", 1);
4780 /* Get the ban to be removed and remove it from the list */
4781 del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4782 if (del && channel->ban_list) {
4783 char *start, *end, *n;
4785 if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4786 silc_free(channel->ban_list);
4787 channel->ban_list = NULL;
4789 start = strstr(channel->ban_list, del);
4790 if (start && strlen(start) >= tmp_len) {
4791 end = start + tmp_len;
4792 n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4793 strncat(n, channel->ban_list, start - channel->ban_list);
4794 strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) -
4796 silc_free(channel->ban_list);
4797 channel->ban_list = n;
4802 /* Send the BAN notify type to our primary router. */
4803 if (!server->standalone && (add || del))
4804 silc_server_send_notify_ban(server, server->router->connection,
4805 server->server_type == SILC_ROUTER ?
4806 TRUE : FALSE, channel, add, del);
4808 /* Send the reply back to the client */
4809 if (channel->ban_list)
4811 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4812 SILC_STATUS_OK, ident, 2,
4814 3, channel->ban_list,
4815 strlen(channel->ban_list) - 1);
4818 silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4819 SILC_STATUS_OK, ident, 1,
4822 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4823 packet->data, packet->len, FALSE);
4825 silc_buffer_free(packet);
4828 silc_free(channel_id);
4829 silc_server_command_free(cmd);
4832 /* Server side command of CLOSE. Closes connection to a specified server. */
4834 SILC_SERVER_CMD_FUNC(close)
4836 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4837 SilcServer server = cmd->server;
4838 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4839 SilcServerEntry server_entry;
4840 SilcSocketConnection sock;
4843 unsigned char *name;
4844 uint32 port = SILC_PORT;
4846 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CLOSE, cmd, 1, 2);
4848 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4851 /* Check whether client has the permissions. */
4852 if (client->mode == SILC_UMODE_NONE) {
4853 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4854 SILC_STATUS_ERR_NO_SERVER_PRIV);
4858 /* Get the remote server */
4859 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4861 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4862 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4867 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4869 SILC_GET32_MSB(port, tmp);
4871 server_entry = silc_idlist_find_server_by_conn(server->local_list,
4872 name, port, FALSE, NULL);
4874 server_entry = silc_idlist_find_server_by_conn(server->global_list,
4875 name, port, FALSE, NULL);
4876 if (!server_entry) {
4877 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4878 SILC_STATUS_ERR_NO_SERVER_ID);
4882 /* Send reply to the sender */
4883 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4886 /* Close the connection to the server */
4887 sock = (SilcSocketConnection)server_entry->connection;
4889 /* If we shutdown primary router connection manually then don't trigger
4890 any reconnect or backup router connections, by setting the router
4892 if (server->router == server_entry) {
4893 server->id_entry->router = NULL;
4894 server->router = NULL;
4895 server->standalone = TRUE;
4897 silc_server_free_sock_user_data(server, sock);
4898 silc_server_close_connection(server, sock);
4901 silc_server_command_free(cmd);
4904 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4905 active connections. */
4907 SILC_SERVER_CMD_FUNC(shutdown)
4909 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4910 SilcServer server = cmd->server;
4911 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4913 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4915 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4918 /* Check whether client has the permission. */
4919 if (client->mode == SILC_UMODE_NONE) {
4920 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4921 SILC_STATUS_ERR_NO_SERVER_PRIV);
4925 /* Send reply to the sender */
4926 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4929 /* Then, gracefully, or not, bring the server down. */
4930 silc_server_stop(server);
4934 silc_server_command_free(cmd);
4937 /* Server side command of LEAVE. Removes client from a channel. */
4939 SILC_SERVER_CMD_FUNC(leave)
4941 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4942 SilcServer server = cmd->server;
4943 SilcSocketConnection sock = cmd->sock;
4944 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4945 SilcChannelID *id = NULL;
4946 SilcChannelEntry channel;
4950 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4952 /* Get Channel ID */
4953 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4955 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4956 SILC_STATUS_ERR_NO_CHANNEL_ID);
4959 id = silc_id_payload_parse_id(tmp, len);
4961 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4962 SILC_STATUS_ERR_NO_CHANNEL_ID);
4966 /* Get channel entry */
4967 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4969 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4971 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4972 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4977 /* Check whether this client is on the channel */
4978 if (!silc_server_client_on_channel(id_entry, channel)) {
4979 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4980 SILC_STATUS_ERR_NOT_ON_CHANNEL);
4984 /* Notify routers that they should remove this client from their list
4985 of clients on the channel. Send LEAVE notify type. */
4986 if (!server->standalone)
4987 silc_server_send_notify_leave(server, server->router->connection,
4988 server->server_type == SILC_ROUTER ?
4989 TRUE : FALSE, channel, id_entry->id);
4991 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4994 /* Remove client from channel */
4995 if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4997 /* If the channel does not exist anymore we won't send anything */
5000 if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5001 /* Re-generate channel key */
5002 if (!silc_server_create_channel_key(server, channel, 0))
5005 /* Send the channel key */
5006 silc_server_send_channel_key(server, NULL, channel,
5007 server->server_type == SILC_ROUTER ?
5008 FALSE : !server->standalone);
5013 silc_server_command_free(cmd);
5016 /* Server side of command USERS. Resolves clients and their USERS currently
5017 joined on the requested channel. The list of Client ID's and their modes
5018 on the channel is sent back. */
5020 SILC_SERVER_CMD_FUNC(users)
5022 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5023 SilcServer server = cmd->server;
5024 SilcChannelEntry channel;
5025 SilcChannelID *id = NULL;
5026 SilcBuffer packet, idp;
5027 unsigned char *channel_id;
5028 uint32 channel_id_len;
5029 SilcBuffer client_id_list;
5030 SilcBuffer client_mode_list;
5031 unsigned char lc[4];
5032 uint32 list_count = 0;
5033 uint16 ident = silc_command_get_ident(cmd->payload);
5036 SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5038 /* Get Channel ID */
5039 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5041 /* Get channel name */
5042 channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5044 if (!channel_id && !channel_name) {
5045 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5046 SILC_STATUS_ERR_NO_CHANNEL_ID);
5051 id = silc_id_payload_parse_id(channel_id, channel_id_len);
5053 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5054 SILC_STATUS_ERR_NO_CHANNEL_ID);
5059 /* If we are server and we don't know about this channel we will send
5060 the command to our router. If we know about the channel then we also
5061 have the list of users already. */
5063 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5065 channel = silc_idlist_find_channel_by_name(server->local_list,
5066 channel_name, NULL);
5068 if (!channel || channel->disabled) {
5069 if (server->server_type != SILC_ROUTER && !server->standalone &&
5073 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5074 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5076 /* Send USERS command */
5077 silc_server_packet_send(server, server->router->connection,
5078 SILC_PACKET_COMMAND, cmd->packet->flags,
5079 tmpbuf->data, tmpbuf->len, TRUE);
5081 /* Reprocess this packet after received reply */
5082 silc_server_command_pending(server, SILC_COMMAND_USERS,
5083 silc_command_get_ident(cmd->payload),
5084 silc_server_command_destructor,
5085 silc_server_command_users,
5086 silc_server_command_dup(cmd));
5087 cmd->pending = TRUE;
5088 silc_command_set_ident(cmd->payload, ident);
5090 silc_buffer_free(tmpbuf);
5095 /* Check the global list as well. */
5097 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5099 channel = silc_idlist_find_channel_by_name(server->global_list,
5100 channel_name, NULL);
5102 /* Channel really does not exist */
5103 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5104 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5109 /* If the channel is private or secret do not send anything, unless the
5110 user requesting this command is on the channel. */
5111 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5112 if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5113 && !silc_server_client_on_channel(cmd->sock->user_data, channel)) {
5114 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5115 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5120 (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
5121 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5122 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5127 /* Get the users list */
5128 silc_server_get_users_on_channel(server, channel, &client_id_list,
5129 &client_mode_list, &list_count);
5132 SILC_PUT32_MSB(list_count, lc);
5135 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5136 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5137 SILC_STATUS_OK, ident, 4,
5138 2, idp->data, idp->len,
5140 4, client_id_list->data,
5141 client_id_list->len,
5142 5, client_mode_list->data,
5143 client_mode_list->len);
5144 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5145 packet->data, packet->len, FALSE);
5147 silc_buffer_free(idp);
5148 silc_buffer_free(packet);
5149 silc_buffer_free(client_id_list);
5150 silc_buffer_free(client_mode_list);
5154 silc_server_command_free(cmd);
5157 /* Server side of command GETKEY. This fetches the client's public key
5158 from the server where to the client is connected. */
5160 SILC_SERVER_CMD_FUNC(getkey)
5162 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5163 SilcServer server = cmd->server;
5165 SilcClientEntry client;
5166 SilcServerEntry server_entry;
5167 SilcClientID *client_id = NULL;
5168 SilcServerID *server_id = NULL;
5169 SilcIDPayload idp = NULL;
5170 uint16 ident = silc_command_get_ident(cmd->payload);
5171 unsigned char *tmp, *pkdata;
5172 uint32 tmp_len, pklen;
5173 SilcBuffer pk = NULL;
5176 SILC_LOG_DEBUG(("Start"));
5178 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5180 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5181 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5184 idp = silc_id_payload_parse_data(tmp, tmp_len);
5186 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5187 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5191 id_type = silc_id_payload_get_type(idp);
5192 if (id_type == SILC_ID_CLIENT) {
5193 client_id = silc_id_payload_get_id(idp);
5195 /* If the client is not found from local list there is no chance it
5196 would be locally connected client so send the command further. */
5197 client = silc_idlist_find_client_by_id(server->local_list,
5198 client_id, TRUE, NULL);
5200 client = silc_idlist_find_client_by_id(server->global_list,
5201 client_id, TRUE, NULL);
5203 if ((!client && !cmd->pending && !server->standalone) ||
5204 (client && !client->connection && !cmd->pending) ||
5205 (client && !client->data.public_key && !cmd->pending)) {
5208 SilcSocketConnection dest_sock;
5210 dest_sock = silc_server_get_client_route(server, NULL, 0,
5215 old_ident = silc_command_get_ident(cmd->payload);
5216 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5217 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5219 silc_server_packet_send(server, dest_sock,
5220 SILC_PACKET_COMMAND, cmd->packet->flags,
5221 tmpbuf->data, tmpbuf->len, TRUE);
5223 /* Reprocess this packet after received reply from router */
5224 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5225 silc_command_get_ident(cmd->payload),
5226 silc_server_command_destructor,
5227 silc_server_command_getkey,
5228 silc_server_command_dup(cmd));
5229 cmd->pending = TRUE;
5231 silc_command_set_ident(cmd->payload, old_ident);
5232 silc_buffer_free(tmpbuf);
5237 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5238 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5242 /* The client is locally connected, just get the public key and
5243 send it back. If they key does not exist then do not send it,
5244 send just OK reply */
5245 if (!client->data.public_key) {
5249 tmp = silc_pkcs_public_key_encode(client->data.public_key, &tmp_len);
5250 pk = silc_buffer_alloc(4 + tmp_len);
5251 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5252 silc_buffer_format(pk,
5253 SILC_STR_UI_SHORT(tmp_len),
5254 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5255 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5261 } else if (id_type == SILC_ID_SERVER) {
5262 server_id = silc_id_payload_get_id(idp);
5264 /* If the server is not found from local list there is no chance it
5265 would be locally connected server so send the command further. */
5266 server_entry = silc_idlist_find_server_by_id(server->local_list,
5267 server_id, TRUE, NULL);
5269 server_entry = silc_idlist_find_server_by_id(server->global_list,
5270 server_id, TRUE, NULL);
5272 if (server_entry != server->id_entry &&
5273 ((!server_entry && !cmd->pending && !server->standalone) ||
5274 (server_entry && !server_entry->connection && !cmd->pending &&
5275 !server->standalone) ||
5276 (server_entry && !server_entry->data.public_key && !cmd->pending &&
5277 !server->standalone))) {
5281 old_ident = silc_command_get_ident(cmd->payload);
5282 silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5283 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5285 silc_server_packet_send(server, server->router->connection,
5286 SILC_PACKET_COMMAND, cmd->packet->flags,
5287 tmpbuf->data, tmpbuf->len, TRUE);
5289 /* Reprocess this packet after received reply from router */
5290 silc_server_command_pending(server, SILC_COMMAND_GETKEY,
5291 silc_command_get_ident(cmd->payload),
5292 silc_server_command_destructor,
5293 silc_server_command_getkey,
5294 silc_server_command_dup(cmd));
5295 cmd->pending = TRUE;
5297 silc_command_set_ident(cmd->payload, old_ident);
5298 silc_buffer_free(tmpbuf);
5302 if (!server_entry) {
5303 silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5304 SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5308 /* If they key does not exist then do not send it, send just OK reply */
5309 if (!server_entry->data.public_key) {
5313 tmp = silc_pkcs_public_key_encode(server_entry->data.public_key,
5315 pk = silc_buffer_alloc(4 + tmp_len);
5316 silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5317 silc_buffer_format(pk,
5318 SILC_STR_UI_SHORT(tmp_len),
5319 SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5320 SILC_STR_UI_XNSTRING(tmp, tmp_len),
5330 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5331 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5332 SILC_STATUS_OK, ident,
5336 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
5337 packet->data, packet->len, FALSE);
5338 silc_buffer_free(packet);
5341 silc_buffer_free(pk);
5345 silc_id_payload_free(idp);
5346 silc_free(client_id);
5347 silc_free(server_id);
5348 silc_server_command_free(cmd);